package com.jwipc.shopping.logic.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jwipc.api.constant.RestCode;
import com.jwipc.api.dto.ApiResult;
import com.jwipc.api.dto.OaFileParamDTO;
import com.jwipc.constant.DelFlag;
import com.jwipc.exception.DaoException;
import com.jwipc.inquiry.client.PurchaseApplyBillClient;
import com.jwipc.inquiry.dto.PurchaseApplyBillClientDTO;
import com.jwipc.page.PageUtil;
import com.jwipc.page.PageView;
import com.jwipc.query.BasePageQuery;
import com.jwipc.security.LoginUtil;
import com.jwipc.shopping.constant.ShoppingPayOaClient;
import com.jwipc.shopping.convert.CostCenterConvert;
import com.jwipc.shopping.convert.ShoppingPayConvert;
import com.jwipc.shopping.dto.CostCenterBaseDTO;
import com.jwipc.shopping.dto.ShoppingPayDTO;
import com.jwipc.shopping.entity.CostCenter;
import com.jwipc.shopping.entity.ShoppingCartInfo;
import com.jwipc.shopping.entity.ShoppingPay;
import com.jwipc.shopping.entity.ShoppingPayDetail;
import com.jwipc.shopping.logic.ShoppingPayLogic;
import com.jwipc.shopping.model.po.RelatedProcessPO;
import com.jwipc.shopping.model.po.ShoppingPayDetailPO;
import com.jwipc.shopping.model.po.ShoppingPayOA;
import com.jwipc.shopping.model.query.CostCenterQuery;
import com.jwipc.shopping.model.query.ShoppingPayDetailQuery;
import com.jwipc.shopping.model.query.ShoppingPayQuery;
import com.jwipc.shopping.service.ICostCenterService;
import com.jwipc.shopping.service.IShoppingCartInfoService;
import com.jwipc.shopping.service.IShoppingPayDetailService;
import com.jwipc.shopping.service.IShoppingPayService;
import com.jwipc.sys.client.DictClient;
import com.jwipc.sys.client.FileClient;
import com.jwipc.sys.client.dto.DictDTO;
import com.jwipc.sys.client.dto.FileResposePreviewCDTO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: swq
 * @Date: 2024/4/10 13:23
 */
@Service
@RequiredArgsConstructor
public class ShoppingPayLogicImpl implements ShoppingPayLogic {
    private final IShoppingPayService shoppingPayService;
    private final ICostCenterService costCenterService;
    private final IShoppingPayDetailService shoppingPayDetailService;
    private final IShoppingCartInfoService shoppingCartInfoService;
    private final PurchaseApplyBillClient purchaseApplyBillClient;
    private final ShoppingPayConvert shoppingPayConvert;
    private final CostCenterConvert costCenterConvert;
    private final DictClient dictClient;
    private final ShoppingPayOaClient shoppingPayOaClient ;
    private final FileClient fileClient;


    @Override
    public PageView shoppingPayListPage(ShoppingPayQuery query) {

        final Page<ShoppingPay> page = PageUtil.toPage(query);
        List<ShoppingPay> pays = shoppingPayService.findShoppingPay(page, query);
        return PageUtil.getPV(pays, page.getTotal());

//        final Page<ShoppingPay> page = PageUtil.toPage(query);
//        List<ShoppingPay> pays = shoppingPayService.list(page,
//                new LambdaQueryWrapper<ShoppingPay>()
//                        .eq(ShoppingPay::getDeleteFlag, DelFlag.NORMAL.getStatus())
//                        .like(!StringUtils.isEmpty(query.getTitle()), ShoppingPay::getPayTitle, query.getTitle())
//                        .orderByDesc(ShoppingPay::getCreateTime)
//        );
//        return PageUtil.getPV(pays, page.getTotal());
//        final Page<ShoppingPay> page = PageUtil.toPage(query);
//
//        LambdaQueryWrapper<ShoppingPay> queryWrapper = new LambdaQueryWrapper<ShoppingPay>()
//                .eq(ShoppingPay::getDeleteFlag, DelFlag.NORMAL.getStatus())
//                .like(!StringUtils.isEmpty(query.getTitle()), ShoppingPay::getPayTitle, query.getTitle());
//
//        if (query.getOrder() != null && query.getSort() != null) {
//            switch (query.getSort()) {
//                case "createTime":
//                    queryWrapper.orderByDesc(ShoppingPay::getCreateTime);
//                    break;
//                // 可以根据需要添加其他排序字段的处理逻辑
//                default:
//                    queryWrapper.orderByDesc(ShoppingPay::getCreateTime);
//                    break;
//            }
//        } else {
//            queryWrapper.orderByDesc(ShoppingPay::getCreateTime);
//        }
//
//        List<ShoppingPay> pays = shoppingPayService.list(page, queryWrapper);
//        return PageUtil.getPV(pays, page.getTotal());

    }

    @Override
    public ShoppingPayDTO formShoppingPay(String id) {
        ShoppingPay shoppingPay = shoppingPayService.getById(id);
        return shoppingPayConvert.entitiePoToDto(shoppingPay);
    }

    @Override
    public PageView findPayDetail(ShoppingPayDetailQuery query) {
        List<ShoppingPayDetailPO> poList = shoppingPayService.findPayDetail(query);
        for (ShoppingPayDetailPO shoppingPayDetailPO : poList) {
            //单价
            BigDecimal unitCost = shoppingPayDetailPO.getUnitCost() == null ? BigDecimal.ZERO : shoppingPayDetailPO.getUnitCost();
            //收货数量
            BigDecimal ReceiptNum = shoppingPayDetailPO.getReceiptNum() == null ? BigDecimal.ZERO : shoppingPayDetailPO.getReceiptNum();
            //退货数量
            BigDecimal ReturnQuatity = shoppingPayDetailPO.getReturnQuatity() == null ? BigDecimal.ZERO : shoppingPayDetailPO.getReturnQuatity();
            //实际收货数量
//            BigDecimal actualReceivedQuantity = ReceiptNum.subtract(ReturnQuatity) == null ? BigDecimal.ZERO : ReceiptNum.subtract(ReturnQuatity);
            shoppingPayDetailPO.setActualReceivedQuantity(ReceiptNum.subtract(ReturnQuatity));
            //实际付款总金额(元)
            shoppingPayDetailPO.setActualTotalAmount(shoppingPayDetailPO.getActualReceivedQuantity().multiply(unitCost));
            //退款金额
            shoppingPayDetailPO.setRefundAmount(ReturnQuatity.multiply(unitCost));
            //收货金额(合计金额)
            shoppingPayDetailPO.setTotalAmount(unitCost.multiply(shoppingPayDetailPO.getActualReceivedQuantity()).setScale(2, RoundingMode.HALF_UP));
//            shoppingPayDetailPO.setTotalAmount(shoppingPayDetailPO.getActualTotalAmount().setScale(2, RoundingMode.HALF_UP));
        }
        BasePageQuery basePageQuery = new BasePageQuery();
        basePageQuery.setPage(1);
        basePageQuery.setRows(poList.size());

        final Page<ShoppingPayDetailPO> dbPage = PageUtil.toPage(basePageQuery);
        PageView pageView = PageUtil.getPV(poList, poList.size());
        return pageView;
    }

    @Override
    public PageView costCenterList(CostCenterQuery query) {
        final LambdaQueryWrapper<CostCenter> queryWrapper = new LambdaQueryWrapper<CostCenter>()
                .apply("RowNumber=1")
                .eq(CostCenter::getBloc, "800")//默认传入800
                .eq(StrUtil.isNotEmpty(query.getContractCompanyCode()),CostCenter::getCompanyCode,query.getContractCompanyCode())
                .like(
                        StrUtil.isNotEmpty(query.getCode()), CostCenter::getCostCenter, query.getCodeLike())
                .like(StrUtil.isNotEmpty(query.getName()), CostCenter::getDescribe, query.getNameLike());
        Integer count = costCenterService.findCount(queryWrapper);
        final Integer rows = query.getRows();
        final Integer page = query.getPage();
        Integer offset = (page - 1) * rows;
        List<CostCenter> list = costCenterService.findListForPage(offset, rows, queryWrapper);
        List<CostCenterBaseDTO> dtos = costCenterConvert.entities2Dto(list);
        return PageUtil.getPV(dtos, count);
    }

    @Override
    public List<CostCenterBaseDTO> costCenterListAll(CostCenterQuery query) {
        final LambdaQueryWrapper<CostCenter> queryWrapper = new LambdaQueryWrapper<CostCenter>()
                .eq(CostCenter::getBloc, "800")//默认传入800
                .like(
                        StrUtil.isNotEmpty(query.getCode()), CostCenter::getCostCenter, query.getCodeLike())
                .like(StrUtil.isNotEmpty(query.getName()), CostCenter::getDescribe, query.getNameLike());
        List<CostCenter> list = costCenterService.list( queryWrapper);
        List<CostCenterBaseDTO> dtos = costCenterConvert.entities2Dto(list);
        return dtos;
    }

    @Override
    public Long selectOnlyPayCode(String code, Long payId) {
        Long count = shoppingPayService.count(
                new LambdaQueryWrapper<ShoppingPay>()
                        .eq(Objects.nonNull(code), ShoppingPay::getPayCode, code)
                        .notIn(Objects.nonNull(payId), ShoppingPay::getId, payId));
        return count;
    }

    @Override
    public void  saveShoppingPayDeatils(ShoppingPayDTO bean, String orderlist) {
        //bean.setPayState(1);//设置审批中状态
        bean.setCreateUserName(LoginUtil.getName());
        bean.setCreateUser(LoginUtil.getUserId());
        bean.setCreateUserCode(LoginUtil.getAccount());
        ShoppingPay shoppingPay = shoppingPayConvert.entitieDtoToPo(bean);
        shoppingPayService.saveOrUpdate(shoppingPay);
        String ProcessId = "";
        //修改时操作
        if (bean.getId() != null) {//修改
            //先删除商城付款明细的数据
            List<ShoppingPayDetail> spdList = shoppingPayDetailService.list(new LambdaQueryWrapper<ShoppingPayDetail>().eq(ShoppingPayDetail::getPayId, bean.getId()));
            Set<Long> carInfoIds = spdList.stream().map(ShoppingPayDetail::getCartInfoId).collect(Collectors.toSet()); // 将值收集到 Set 中，确保不重复
            //批量删除商城付款明细
            shoppingPayDetailService.removeBatchByIds(spdList);
            //修改商城订单明细的状态
            shoppingCartInfoService.update(new LambdaUpdateWrapper<ShoppingCartInfo>()
                    .set(ShoppingCartInfo::getStatus, DelFlag.NORMAL.getStatus())
                    .in(ShoppingCartInfo::getId, carInfoIds));

            ShoppingPay byId = shoppingPayService.getById(bean.getId());
            if (byId != null && !StringUtils.isEmpty(byId.getOaProcessId())) {
                ProcessId = byId.getOaProcessId();
            }
        }
        List<Long> cartInfoIdList = new ArrayList<>();
        List<ShoppingPayDetail> orders = JSON.parseArray(orderlist, ShoppingPayDetail.class);
        if (orders != null && orders.size() > 0) {
            orders.stream().forEach(a -> {
                a.setPayId(shoppingPay.getId());
                a.setId(null);
                cartInfoIdList.add(a.getCartInfoId());
            });
            shoppingPayDetailService.saveBatch(orders);
        }
        //批量更新
        shoppingCartInfoService.update(new LambdaUpdateWrapper<ShoppingCartInfo>()
                .set(ShoppingCartInfo::getStatus, DelFlag.DELETE.getStatus())
                .in(ShoppingCartInfo::getId, cartInfoIdList));//批量更新成状态为1

        ShoppingPay byId = shoppingPayService.getById(bean.getId());
        //调用oa审批接口
        if(bean.getTotalAmount() != null && bean.getTotalAmount().compareTo(BigDecimal.ZERO) != 0){
        List<DictDTO> subs = dictClient.getDicByType("pay_mode");
        List<DictDTO> type = dictClient.getDicByType("contractPayCategory");
        List<DictDTO> driveType = dictClient.getDicByType("contract_pay_boot_item");
        Map<String, String> subMap = subs.stream().collect(Collectors.toMap(DictDTO::getCode, DictDTO::getName, (key1, key2) -> key2));
        Map<String, String> typeMap = type.stream().collect(Collectors.toMap(DictDTO::getCode, DictDTO::getName, (key1, key2) -> key2));
        Map<String, String> driveTypeMap = driveType.stream().collect(Collectors.toMap(DictDTO::getCode, DictDTO::getName, (key1, key2) -> key2));

        ShoppingPayOA payOA = new ShoppingPayOA();

        ShoppingPayOA.Head head = new ShoppingPayOA.Head();
        ShoppingPayOA.Item item = new ShoppingPayOA.Item();
        List<ShoppingPayOA.PaymentItem> paymentItem = new ArrayList<>();
        //过滤出不同的采购订单号
        Set<String> purCodes = orders.stream().map(ShoppingPayDetail::getPurCode).collect(Collectors.toSet()); // 将值收集到 Set 中，确保不重复
        List<PurchaseApplyBillClientDTO> billList = purchaseApplyBillClient.listByBillCodeList(purCodes);
        List<RelatedProcessPO> reppList = new ArrayList<>();
        RelatedProcessPO relatedProcessPO = null;
        if (billList != null && billList.size() > 0) {
            for (PurchaseApplyBillClientDTO purchaseApplyBill : billList) {
                relatedProcessPO = new RelatedProcessPO();
                relatedProcessPO.setSubject(purchaseApplyBill.getMainUses());
                relatedProcessPO.setDocId(purchaseApplyBill.getBillCode());
                reppList.add(relatedProcessPO);
            }
        }
        String relatedProcess = JSON.toJSONString(reppList);

        String files = shoppingPay.getPayFiles();
        List<OaFileParamDTO> lists = new ArrayList<>();
        if (!StringUtils.isEmpty(files)) {
            List<FileResposePreviewCDTO> previewDTOS = fileClient.getPreviewUrl(Arrays.asList(files.split(",")));
            previewDTOS.stream().forEach(a -> {
                final OaFileParamDTO build = OaFileParamDTO.builder().url(a.getPreviewUrl())
                        .fileName(a.getFileName()).downloadUrl(a.getDownloadUrl()).build();
                lists.add(build);
            });

        }
        head.setProcessId(ProcessId);
        head.setSRMToS("11");
        head.setApplicant(shoppingPay.getCreateUserCode());

        LocalDate dateTime = shoppingPay.getCreateTime();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String formattedDateTime = dateTime.format(formatter);
        head.setApplyDate(formattedDateTime);
        head.setCompanyCode(shoppingPay.getPayOrgCode());
        head.setCompanyName(shoppingPay.getPayOrgName());
        String code = "";
        if (!StringUtils.isEmpty(shoppingPay.getSettlementMethod())) {
            code = subMap.get(shoppingPay.getSettlementMethod());
            head.setPayMethod(code);
        }

        head.setPayeeName(shoppingPay.getPayeeName());
        head.setSupplierCode(shoppingPay.getPayeeCode());
        head.setBankNo(shoppingPay.getBankCode());
        head.setSwiftCode(shoppingPay.getBankSwiftCode());
        head.setCurrency(shoppingPay.getPayCurrency());
        head.setBankName(shoppingPay.getBankName());
        head.setPayeeAccount(shoppingPay.getBankAccount());
        head.setSapOrderPayment("否");
        head.setAdvancePayment("否");
        head.setContractAmountPrepaid(shoppingPay.getTotalAmount());
        head.setContractAmount(shoppingPay.getTotalAmount());
        head.setCostAscriptionDept(shoppingPay.getBelongDeptName());
        head.setRelatedProcess(relatedProcess);
        head.setTotalAmount(shoppingPay.getTotalAmount());
        head.setExcludingTaxAmount(shoppingPay.getTotalAmountNo());
        //head.setTotalTaxAmount(shoppingPay.getTaxAmount());
        head.setPaymentAmountWords(shoppingPay.getAmountCapital());
        head.setAttachment(JSON.toJSONString(lists));
        head.setRelatedYanShou(shoppingPay.getAccepProcessData());
        orders.stream().forEach(a -> {
            ShoppingPayOA.PaymentItem mentItem = new ShoppingPayOA.PaymentItem();
            String typeCode = "";
            if (!StringUtils.isEmpty(a.getPayCategory())) {
                typeCode = typeMap.get(a.getPayCategory());
                mentItem.setReimburseType(typeCode);
            }
            String businessDesc ="";
            if(StringUtils.isEmpty(a.getServiceDesc())){
                businessDesc = a.getSkuName();
            }else{
                businessDesc = a.getServiceDesc();
            }
            mentItem.setBusinessDesc(businessDesc);
            mentItem.setAmount(a.getTotalAmount());
            mentItem.setUser(a.getRequireName());
            mentItem.setInternalOrder("");
            mentItem.setProjectNo(a.getProjectNo());
            mentItem.setCustomer(a.getCustomerName());
            mentItem.setCustomerCode(a.getCustomerCode());
            String driverName = "";
            if (!StringUtils.isEmpty(a.getDrivingFactors())) {
               // driverName = driveTypeMap.get(a.getDrivingFactors());
                mentItem.setDrivingFactors(a.getDrivingFactors());
            }
            mentItem.setFixedAssetCode("");
            mentItem.setCostCenter(a.getCostCenterName());
            mentItem.setCostCenterCode(a.getCostCenterCode());
            paymentItem.add(mentItem);
        });
        item.setPaymentItem(paymentItem);

        payOA.setHead(head);
        payOA.setItem(item);
        ApiResult result = shoppingPayOaClient.saveShoppingPay(payOA);
        //状态 0 待提交  1审批中 2 通过 3 驳回4异常
        if (result == null) {
            shoppingPay.setPayState(4);
            shoppingPayService.updateById(shoppingPay);
            throw new DaoException("商城付款流程调用失败");
        } else {
            if (result.getCode().equals(RestCode.SAP_SUCCESS.getCode())) {
                shoppingPay.setPayState(1);
                shoppingPay.setOaCode(RestCode.SAP_SUCCESS.getCode());
                shoppingPay.setOaMsg(result.getMessage());
                shoppingPay.setOaProcessId(String.valueOf(result.getData()));
                shoppingPayService.updateById(shoppingPay);
            } else {
                shoppingPay.setPayState(4);
                shoppingPayService.updateById(shoppingPay);
                throw new DaoException(result.getMessage());
            }
        }
    }
    }

    @Override
    public PageView detailOrderLists(ShoppingPayDetailQuery query) {
        final Page<ShoppingPayDetail> page = PageUtil.toPage(query);
        List<ShoppingPayDetailPO> detailList = shoppingPayDetailService.selectDetailOrderByQuery(page, query);
        return PageUtil.getPV(detailList, page.getTotal());
//        final Page<ShoppingPayDetail> page = PageUtil.toPage(query);
//        List<ShoppingPayDetail> detailList = shoppingPayDetailService.list(page,new LambdaQueryWrapper<ShoppingPayDetail>()
//                .eq(ShoppingPayDetail::getPayId, query.getPayId())
//                .orderByDesc(ShoppingPayDetail::getId));
//        return PageUtil.getPV(detailList, page.getTotal());
    }

    @Override
    public void removeShoppingPayDetail(String id) {
        ShoppingPayDetail shoppingPayDetail=shoppingPayDetailService.getById(id);
        //删除商城付款明细
        shoppingPayDetailService.removeById(id);
        Long carInfoId = shoppingPayDetail.getCartInfoId();
        //修改商城订单明细的状态
        shoppingCartInfoService.update(new LambdaUpdateWrapper<ShoppingCartInfo>()
                .set(ShoppingCartInfo::getStatus,DelFlag.NORMAL.getStatus())
                .eq(ShoppingCartInfo::getId,carInfoId));
    }
    @Override
    public void removeShoppingPay(String id) {
        //删除商城主表
        shoppingPayService.removeById(id);
        List<ShoppingPayDetail>  spdList=shoppingPayDetailService.list(new LambdaQueryWrapper<ShoppingPayDetail>().eq(ShoppingPayDetail::getPayId, id));
        if(spdList!=null && spdList.size()>0){
            //批量删除商城付款明细
            shoppingPayDetailService.removeBatchByIds(spdList);
            Set<Long> carInfoIds = spdList.stream().map(ShoppingPayDetail::getCartInfoId).collect(Collectors.toSet()); // 将值收集到 Set 中，确保不重复
            //修改商城订单明细的状态
            shoppingCartInfoService.update(new LambdaUpdateWrapper<ShoppingCartInfo>()
                    .set(ShoppingCartInfo::getStatus,DelFlag.NORMAL.getStatus())
                    .in(ShoppingCartInfo::getId,carInfoIds));
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void oaExamine(Long id, Integer state) {
        final ShoppingPay shoppingPay = shoppingPayService.getById(id);
        shoppingPay.setPayState(state);
        shoppingPayService.updateById(shoppingPay);
    }

    @Override
    public List<ShoppingPayDetailPO> selectPayExportData(ShoppingPayDetailQuery query) {
        List<ShoppingPayDetailPO> shoppingPayDetailPOList = shoppingPayService.selectPayExportData(query);
        List<DictDTO> driver = dictClient.getDicByType("contract_pay_boot_item");

        Map<String, String> drivingFactors = driver.stream().collect(Collectors.toMap(DictDTO::getCode,DictDTO::getName,(key1, key2)->key2));




        for (ShoppingPayDetailPO shoppingPayDetailPO : shoppingPayDetailPOList) {
            shoppingPayDetailPO.setDrivingFactorsText(drivingFactors.get(String.valueOf(shoppingPayDetailPO.getDrivingFactors())));

        }
        return shoppingPayDetailPOList;
    }
}
