package com.trade.admin.trade.exportrebate.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.trade.admin.trade.exportrebate.dto.ExportTaxRefundBatchRequest;
import com.trade.admin.trade.exportrebate.dto.ExportTaxRefundDetailsRequest;
import com.trade.admin.trade.exportrebate.service.ExportTaxRebateService;
import com.trade.common.constant.HttpStatus;
import com.trade.common.core.page.GridPage;
import com.trade.common.exception.ServiceException;
import com.trade.common.utils.DateUtils;
import com.trade.service.DictConstants;
import com.trade.service.finance.paymentcollection.dto.ExportTaxRefundV2Dto;
import com.trade.service.finance.paymentcollection.service.BillingIncomeService;
import com.trade.service.thirdparty.xiaotu.service.XiaotuRequestService;
import com.trade.service.trade.exportrebate.dto.*;
import com.trade.service.trade.exportrebate.dto.search.TaxRebateExportAbstractInfoSearchDto;
import com.trade.service.trade.exportrebate.dto.search.TaxRebatePurchaseAbstractInfoSearchDto;
import com.trade.service.trade.exportrebate.dto.search.TaxRebateSummarySearchDto;
import com.trade.service.trade.exportrebate.service.TaxRebateExportDetailsBaseService;
import com.trade.service.trade.exportrebate.service.TaxRebatePurchaseDetailsBaseService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 出口退税服务实现类
 *
 * @author hlb
 * @since 2024-10-22 15:46:46
 */
@Service("exportTaxRebateService")
public class ExportTaxRebateServiceImpl implements ExportTaxRebateService {

    private static final Logger logger = LoggerFactory.getLogger(ExportTaxRebateServiceImpl.class);
    @Resource
    private TaxRebateExportDetailsBaseService taxRebateExportDetailsBaseService;
    @Resource
    private TaxRebatePurchaseDetailsBaseService taxRebatePurchaseDetailsBaseService;
    @Resource
    private XiaotuRequestService xiaotuRequestService;
    @Resource
    private BillingIncomeService billingIncomeService;

    @Override
    public TaxRebateTotalDataDto getTaxRebateTotalDataBySearch(TaxRebateSummarySearchDto search) {
        return taxRebateExportDetailsBaseService.getTaxRebateTotalDataBySearch(search);
    }

    @Override
    public GridPage<TaxRebateSummaryDataDto> getTaxRebateSummaryDataPagesBySearch(TaxRebateSummarySearchDto search) {
        return taxRebateExportDetailsBaseService.getTaxRebateSummaryDataPagesBySearch(search);
    }

    @Override
    public GridPage<TaxRebateExportAbstractInfo> getTaxRebateExportAbstractInfoPagesBySearch(
            TaxRebateExportAbstractInfoSearchDto search) {
        return taxRebateExportDetailsBaseService.getTaxRebateExportAbstractInfoPagesBySearch(search);
    }

    @Override
    public GridPage<TaxRebatePurchaseAbstractInfo> getTaxRebatePurchaseAbstractInfoPagesBySearch(
            TaxRebatePurchaseAbstractInfoSearchDto search) {
        return taxRebatePurchaseDetailsBaseService.getTaxRebatePurchaseAbstractInfoPagesBySearch(search);
    }

    @Override
    public String getTaxRebateUrl(String xtUserId, String xtEid) {
        if (StrUtil.isEmpty(xtUserId) || StrUtil.isEmpty(xtEid)) {
            throw new ServiceException("贸易平台未认证", HttpStatus.BAD_REQUEST);
        }
        return xiaotuRequestService.getExportRebateUrl(xtUserId, xtEid, "/02/0202/020204");
    }

    @Override
    public BigDecimal getRefundAmountForDeclarationBatch(ExportTaxRefundBatchRequest request) {
        if (request == null || CollUtil.isEmpty(request.getSearchDtos())) {
            throw new ServiceException("请求参数错误", HttpStatus.BAD_REQUEST);
        }
        int page = 1;
        int pageSize = 100;
        BigDecimal refundAmount = BigDecimal.ZERO;
        for (TaxRebateExportAbstractInfoSearchDto searchDto : request.getSearchDtos()) {
            searchDto.setStatus(DictConstants.REBATE_PROCESS_STATUS_DONE);
            searchDto.setPaymentStatus(DictConstants.REBATE_PAYMENT_STATUS_NOT_PAY);
            searchDto.setRows(pageSize);
            while (true) {
                searchDto.setPage(page);
                GridPage<TaxRebateExportAbstractInfo> pages = taxRebateExportDetailsBaseService
                        .getTaxRebateExportAbstractInfoPagesBySearch(searchDto);
                List<TaxRebateExportAbstractInfo> rows = pages.getRows();
                BigDecimal amount = rows.stream().map(TaxRebateExportAbstractInfo::getTaxRefundAmount)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                refundAmount = refundAmount.add(amount);
                if (rows.size() < pageSize) {
                    break;
                }
                page++;
            }
        }
        return refundAmount;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean refundExportTaxForDeclarationBatch(ExportTaxRefundBatchRequest request) {
        if (request == null || CollUtil.isEmpty(request.getSearchDtos())) {
            throw new ServiceException("请求参数错误", HttpStatus.BAD_REQUEST);
        }
        int page = 1;
        int pageSize = 100;
        List<ExportTaxRefundV2Dto> exportTaxRefundDtos = new ArrayList<>();
        List<Long> recordIds = new ArrayList<>();
        for (TaxRebateExportAbstractInfoSearchDto searchDto : request.getSearchDtos()) {
            searchDto.setStatus(DictConstants.REBATE_PROCESS_STATUS_DONE);
            searchDto.setPaymentStatus(DictConstants.REBATE_PAYMENT_STATUS_NOT_PAY);
            searchDto.setRows(pageSize);
            while (true) {
                searchDto.setPage(page);
                GridPage<TaxRebateExportAbstractInfo> pages = taxRebateExportDetailsBaseService
                        .getTaxRebateExportAbstractInfoPagesBySearch(searchDto);
                List<TaxRebateExportAbstractInfo> rows = pages.getRows();
                buildRefundSaveParam(rows, recordIds, exportTaxRefundDtos, request.getEntryDate(),
                        request.getAccountNumber());
                if (rows.size() < pageSize) {
                    break;
                }
                page++;
            }
        }
        if (CollUtil.isNotEmpty(exportTaxRefundDtos)) {
            // 生成退税入账确认记录
            billingIncomeService.saveExportTaxRefundV2(exportTaxRefundDtos);
        }
        if (CollUtil.isNotEmpty(recordIds)) {
            // 更新退税状态
            taxRebateExportDetailsBaseService.batchUpdatePaymentStatusAndPaymentDate(recordIds,
                    DictConstants.REBATE_PAYMENT_STATUS_AUDITING,
                    DateUtils.parseLocalDate2Date(request.getEntryDate()));
        }
        return true;
    }

    @Override
    public BigDecimal getRefundAmountForExportDetails(List<TaxRebateExportAbstractInfo> request) {
        if (CollUtil.isNotEmpty(request)) {
            return BigDecimal.ZERO;
        }
        return request.stream()
                .filter(o -> DictConstants.REBATE_PROCESS_STATUS_DONE.equals(o.getStatus())
                        && DictConstants.REBATE_PAYMENT_STATUS_NOT_PAY.equals(o.getPaymentStatus()))
                .map(TaxRebateExportAbstractInfo::getTaxRefundAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean refundExportTaxForExportDetails(ExportTaxRefundDetailsRequest request) {
        if (CollUtil.isEmpty(request.getDetails())) {
            return false;
        }
        List<TaxRebateExportAbstractInfo> details = request.getDetails().stream()
                .filter(o -> DictConstants.REBATE_PROCESS_STATUS_DONE.equals(o.getStatus())
                        && DictConstants.REBATE_PAYMENT_STATUS_NOT_PAY.equals(o.getPaymentStatus()))
                .collect(Collectors.toList());
        List<ExportTaxRefundV2Dto> exportTaxRefundDtos = new ArrayList<>();
        List<Long> recordIds = new ArrayList<>();
        buildRefundSaveParam(details, recordIds, exportTaxRefundDtos, request.getEntryDate(),
                request.getAccountNumber());
        if (CollUtil.isNotEmpty(exportTaxRefundDtos)) {
            // 生成退税入账确认记录
            billingIncomeService.saveExportTaxRefundV2(exportTaxRefundDtos);
        }
        if (CollUtil.isNotEmpty(recordIds)) {
            // 更新退税状态
            taxRebateExportDetailsBaseService.batchUpdatePaymentStatusAndPaymentDate(recordIds,
                    DictConstants.REBATE_PAYMENT_STATUS_AUDITING,
                    DateUtils.parseLocalDate2Date(request.getEntryDate()));
        }
        return true;
    }

    private void buildRefundSaveParam(List<TaxRebateExportAbstractInfo> details, List<Long> recordIds,
            List<ExportTaxRefundV2Dto> exportTaxRefundDtos, LocalDate entryDate, String accountNumber) {
        Map<String, List<TaxRebateExportAbstractInfo>> map = details.stream()
                .collect(Collectors.groupingBy(o -> o.getDeclarationBatch() + "_" + o.getDeclarationMonthYear() + "_"
                        + o.getAgencyCertNo() + "_" + o.getSalesContractId()));
        for (Map.Entry<String, List<TaxRebateExportAbstractInfo>> entry : map.entrySet()) {
            String key = entry.getKey();
            String[] arr = key.split("_");
            String declarationBatch = arr[0];
            String declarationMonthYear = arr[1];
            // String agencyCertNo = arr[2];
            Long salesContractId = Long.valueOf(arr[3]);
            List<TaxRebateExportAbstractInfo> records = entry.getValue();
            BigDecimal refundAmount = records.stream().map(TaxRebateExportAbstractInfo::getTaxRefundAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            List<Long> detailIds = records.stream().map(o -> o.getId()).distinct().collect(Collectors.toList());
            recordIds.addAll(
                    records.stream().map(TaxRebateExportAbstractInfo::getId).distinct().collect(Collectors.toList()));
            ExportTaxRefundV2Dto dto = new ExportTaxRefundV2Dto();
            dto.setDeclarationMonthYear(declarationMonthYear);
            dto.setDeclarationBatch(declarationBatch);
            dto.setDetailIds(detailIds);
            dto.setRefundAmount(refundAmount);
            dto.setSaleContractId(salesContractId);
            dto.setEntryDate(entryDate);
            dto.setAccountNumber(accountNumber);
            exportTaxRefundDtos.add(dto);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean refundExportTaxAuditPassed(List<Long> detailIds) {
        taxRebateExportDetailsBaseService.batchUpdatePaymentStatusAndPaymentDate(detailIds,
                DictConstants.REBATE_PAYMENT_STATUS_PAYED, null);
        return true;
    }
}
