package com.jwipc.finance.logic.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jwipc.constant.DictCode;
import com.jwipc.exception.DaoException;
import com.jwipc.finance.convert.CostInvoicedPaymentCertificateConvert;
import com.jwipc.finance.dto.CostInvoicedPaymentCertificateDTO;
import com.jwipc.finance.dto.CostInvoicedPaymentCertificateImportDTO;
import com.jwipc.finance.entity.AccountStatement;
import com.jwipc.finance.entity.CostInvoicedPaymentCertificate;
import com.jwipc.finance.logic.CostInvoicedPaymentCertificateLogic;
import com.jwipc.finance.model.po.CostInvoicedPaymentCertificatePO;
import com.jwipc.finance.model.query.InvoicedDetailQuery;
import com.jwipc.finance.service.ICostInvoicedPaymentCertificateService;
import com.jwipc.page.PageUtil;
import com.jwipc.page.PageView;
import com.jwipc.security.dto.CurrentUserDTO;
import com.jwipc.sys.client.DictClient;
import com.jwipc.sys.client.dto.DictDTO;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author shenyang.ou
 * @date 2024/3/5 13:27
 * @desc
 */
@Service
@RequiredArgsConstructor
public class CostInvoicedPaymentCertificateLogicImpl implements CostInvoicedPaymentCertificateLogic {
    private final CostInvoicedPaymentCertificateConvert costInvoicedPaymentCertificateConvert;
    private final ICostInvoicedPaymentCertificateService costInvoicedPaymentCertificateService;
    private final DictClient dictClient;

    /**
     * 根据开票申请单ID获取关联发票数据
     *
     * @param iaId 开票申请单ID
     * @return 关联发票数据
     */
    @Override
    public List<CostInvoicedPaymentCertificateDTO> getInvoiceReceiptListByIaId(Long iaId) {
        List<CostInvoicedPaymentCertificatePO> costInvoicedPaymentCertificatePOS = costInvoicedPaymentCertificateService.getInvoiceReceiptListByIaId(iaId);;
        return costInvoicedPaymentCertificateConvert.po2DTOList(costInvoicedPaymentCertificatePOS);
    }

    /**
     * 关联或取消关联发票
     *
     * @param costInvoicedPaymentCertificateData 发票数据
     * @param iaId                开票申请单ID
     * @param currentUser         当前用户
     */
    @Override
    public void operateInvoice(List<CostInvoicedPaymentCertificateDTO> costInvoicedPaymentCertificateData, Long iaId, CurrentUserDTO currentUser) {
        if (CollUtil.isNotEmpty(costInvoicedPaymentCertificateData)) {
            costInvoicedPaymentCertificateData.forEach(e -> e.setIaId(iaId));
            List<Long> allIds = costInvoicedPaymentCertificateData.stream().map(CostInvoicedPaymentCertificateDTO::getId).filter(Objects::nonNull).collect(Collectors.toList());
            List<CostInvoicedPaymentCertificate> existList = costInvoicedPaymentCertificateService.list(Wrappers.lambdaQuery(CostInvoicedPaymentCertificate.class).eq(CostInvoicedPaymentCertificate::getIaId,iaId));
            List<Long> exitIds = existList.stream().map(CostInvoicedPaymentCertificate::getId).collect(Collectors.toList());
            List<Long> removeIds = exitIds.stream().filter(f -> !allIds.contains(f)).collect(Collectors.toList());

            // 删除
            if (CollUtil.isNotEmpty(removeIds)) {
                costInvoicedPaymentCertificateService.removeBatchByIds(removeIds);
            }
            //判断本次发票号码是否重复
            List<CostInvoicedPaymentCertificateDTO> nonNullNameList = costInvoicedPaymentCertificateData.stream()
                    .filter(p -> StringUtils.isNotEmpty(p.getInvoiceNumber()))
                    .toList();
            if(CollectionUtils.isNotEmpty(nonNullNameList)){
                Map<String, List<CostInvoicedPaymentCertificateDTO>> ext = nonNullNameList.stream()
                        .collect(Collectors.groupingBy(CostInvoicedPaymentCertificateDTO::getInvoiceNumber))
                        .entrySet().stream()
                        .filter(entry -> entry.getValue().size() > 1)
                        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
                if (ObjectUtil.isNotNull(ext)){
                    ext.forEach((key, value) -> {
                        throw new DaoException("发票号码："+key+"重复录入"+value.size()+"条，请删除其中"+(value.size()-1)+"条");
                    });
                }
            }
//            //判断本次数电发票号码是否重复
//            List<CostInvoicedPaymentCertificateDTO> nonNullElectronNameList = costInvoicedPaymentCertificateData.stream()
//                    .filter(p -> StringUtils.isNotEmpty(p.getElectronInvoiceNumber()))
//                    .toList();
//            if(CollectionUtils.isNotEmpty(nonNullElectronNameList)){
//                Map<String, List<CostInvoicedPaymentCertificateDTO>> electronExt = nonNullElectronNameList.stream()
//                        .collect(Collectors.groupingBy(CostInvoicedPaymentCertificateDTO::getElectronInvoiceNumber))
//                        .entrySet().stream()
//                        .filter(entry -> entry.getValue().size() > 1)
//                        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
//                if (ObjectUtil.isNotNull(electronExt)){
//                    electronExt.forEach((key, value) -> {
//                        throw new DaoException("数电发票号码："+key+"重复录入"+value.size()+"条，请删除其中"+(value.size()-1)+"条");
//                    });
//                }
//            }
            //判断发票号码是否重复
            for (CostInvoicedPaymentCertificateDTO costInvoicedPaymentCertificate : costInvoicedPaymentCertificateData){
                if(StrUtil.isNotEmpty(costInvoicedPaymentCertificate.getInvoiceNumber())){
                    CostInvoicedPaymentCertificate costInvoicedPaymentCertificate1 = costInvoicedPaymentCertificateService.getExitDataByIaIdAndInvoiceNumber(iaId,costInvoicedPaymentCertificate.getInvoiceNumber());
                    if (ObjectUtil.isNotNull(costInvoicedPaymentCertificate1)){
                        throw new DaoException("发票号码："+costInvoicedPaymentCertificate.getInvoiceNumber()+"在系统中已存在，不可录入");
                    }
                }

            }
//            //判断数电发票号码是否重复
//            for (CostInvoicedPaymentCertificateDTO costInvoicedPaymentCertificate : costInvoicedPaymentCertificateData){
//                costInvoicedPaymentCertificate.setDeleteFlag(0);
//                if(StrUtil.isNotEmpty(costInvoicedPaymentCertificate.getElectronInvoiceNumber())){
//                    costInvoicedPaymentCertificate.setElectronInvoiceNumber(costInvoicedPaymentCertificate.getElectronInvoiceNumber().trim());//去除空格
//                    CostInvoicedPaymentCertificate costInvoicedPaymentCertificate1 = costInvoicedPaymentCertificateService.getExitDataByIaIdAndElectronInvoiceNumber(iaId,costInvoicedPaymentCertificate.getElectronInvoiceNumber());
//                    if (ObjectUtil.isNotNull(costInvoicedPaymentCertificate1)){
//                        throw new DaoException("数电发票号码："+costInvoicedPaymentCertificate.getElectronInvoiceNumber()+"在系统中已存在，不可录入");
//                    }
//                }
//            }
            // 新增或编辑
            costInvoicedPaymentCertificateService.saveOrUpdateBatch(costInvoicedPaymentCertificateConvert.dto2EntityList(costInvoicedPaymentCertificateData));

        }
    }

    @Override
    public PageView getInvoiceReceiptListByQuery(InvoicedDetailQuery query) {
        final Page<AccountStatement> dbPage = PageUtil.toPage(query);
        List<CostInvoicedPaymentCertificatePO> costInvoicedPaymentCertificatePOS = costInvoicedPaymentCertificateService.findPageByQuery(dbPage, query);
        List<CostInvoicedPaymentCertificateDTO> costInvoicedPaymentCertificateDTOS = costInvoicedPaymentCertificateConvert.po2PageListDTO(costInvoicedPaymentCertificatePOS);
        return PageUtil.getPV(costInvoicedPaymentCertificateDTOS, dbPage.getTotal());
    }

    @Override
    public List<CostInvoicedPaymentCertificateDTO> listAll(InvoicedDetailQuery query) {
        List<CostInvoicedPaymentCertificatePO> costInvoicedPaymentCertificatePOS = costInvoicedPaymentCertificateService.findPageByQuery(null, query);
        return costInvoicedPaymentCertificateConvert.po2PageListDTO(costInvoicedPaymentCertificatePOS);
    }

    @Override
    public void updateDeductionStatus(List<String> idList, String deductionStatus, String note) {
        List<CostInvoicedPaymentCertificate> costInvoicedPaymentCertificateList = costInvoicedPaymentCertificateService.listByIds(idList);
        if (CollectionUtils.isNotEmpty(costInvoicedPaymentCertificateList)){
            for (CostInvoicedPaymentCertificate costInvoicedPaymentCertificate : costInvoicedPaymentCertificateList){
                costInvoicedPaymentCertificate.setNote(note);
                costInvoicedPaymentCertificate.setDeductionStatus(deductionStatus);
            }
        }
        costInvoicedPaymentCertificateService.updateBatchById(costInvoicedPaymentCertificateList);
    }

    @Override
    public List<CostInvoicedPaymentCertificateImportDTO> importData(MultipartFile file) {
        List<CostInvoicedPaymentCertificateImportDTO> cachedDataList = ListUtils.newArrayList();
        //币种
        List<DictDTO> currencys = dictClient.getDicByType(DictCode.CURRENCY.getCode());
        final Map<String, DictDTO> currencyCache = currencys.stream().collect(Collectors.toMap(DictDTO::getCode, a -> a));
        final Set<String> currencyCodes = currencyCache.keySet();
        try {
            EasyExcel.read(file.getInputStream(), CostInvoicedPaymentCertificateImportDTO.class,
                    new ReadListener<CostInvoicedPaymentCertificateImportDTO>() {
                        @Override
                        public void invoke(CostInvoicedPaymentCertificateImportDTO data, AnalysisContext context) {
                            final String currencyCode = data.getCurrencyCode();
                            final String deductionCodeTypeStr = data.getDeductionCodeTypeStr();
                            if (StringUtils.isNotEmpty(deductionCodeTypeStr)&&"可抵扣".equals(deductionCodeTypeStr)){
                                data.setDeductionCodeType(1);
                            }
                            if (StringUtils.isNotEmpty(deductionCodeTypeStr)&&"不可抵扣".equals(deductionCodeTypeStr)){
                                data.setDeductionCodeType(2);
                            }
                            if (StringUtils.isNotEmpty(currencyCode)&&!currencyCodes.contains(currencyCode)){
                                throw new DaoException(StrUtil.format("币种：{}在系统中不存在",currencyCode));
                            }
                            cachedDataList.add(data);
                        }
                        @Override
                        public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                        }
                    }).sheet().doRead();
        } catch (IOException e) {
            throw new DaoException("导入失败！");
        }
        return cachedDataList;
    }
}
