package com.jwipc.sys.logic.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jwipc.exception.DaoException;
import com.jwipc.page.PageUtil;
import com.jwipc.page.PageView;
import com.jwipc.security.LoginUtil;
import com.jwipc.sys.convert.BusinessAttachmentConvert;
import com.jwipc.sys.dto.BusinessAttachmentDTO;
import com.jwipc.sys.dto.BusinessAttachmentDeleteOrUpdateDTO;
import com.jwipc.sys.entity.Attachment;
import com.jwipc.sys.entity.BusinessAttachment;
import com.jwipc.sys.entity.DigitalSealBusinessDetail;
import com.jwipc.sys.logic.BusinessAttachmentLogic;
import com.jwipc.sys.model.po.BusinessAttachmentPO;
import com.jwipc.sys.model.query.BusinessAttachmentQuery;
import com.jwipc.sys.service.IAttachmentService;
import com.jwipc.sys.service.IBusinessAttachmentService;
import com.jwipc.sys.service.IDigitalSealBusinessDetailService;
import com.jwipc.sys.service.impl.AttachmentServiceImpl;
import lombok.RequiredArgsConstructor;
import org.ehcache.core.util.CollectionUtil;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.baomidou.dynamic.datasource.support.DdConstants.SLAVE;


/**
 * <p>
 *
 * </p>
 *
 * @author Chen Tianshi
 * @since 2025/9/11 13:39
 */
@Service
@RequiredArgsConstructor
public class BusinessAttachmentLogicImpl implements BusinessAttachmentLogic {
    private final IBusinessAttachmentService businessAttachmentService;
    private final BusinessAttachmentConvert businessAttachmentConvert;
    private final IAttachmentService attachmentService;
    private final IDigitalSealBusinessDetailService digitalSealBusinessDetailService;

    @Override
    public PageView list(BusinessAttachmentQuery query) {
        final Page<BusinessAttachment> dbPage = PageUtil.toPage(query);
        List<BusinessAttachmentPO> list = businessAttachmentService.queryByPage(dbPage, query);
        list.stream().forEach(oitem -> {
            if (oitem.getBusinessTypeCode().equals("contract_payment_apply")) {
                if (null != oitem.getType() && "contractType".equals(oitem.getType())) {
//                    oitem.setBillCode(query.getBillCode());
                } else if (null != oitem.getType() && "contract_delivery".equals(oitem.getType())) {
                    BusinessAttachment businessAttachmentTemp = businessAttachmentService.getOne(new LambdaQueryWrapper<BusinessAttachment>()
                            .eq(BusinessAttachment::getFileId,oitem.getFileId())
                            .eq(BusinessAttachment::getDeleteFlag,0)
                            .eq(BusinessAttachment::getBusinessTypeCode,"contract_delivery"));
                    if (Objects.nonNull(businessAttachmentTemp)) {
                        oitem.setBillCode(businessAttachmentTemp.getBusinessCode());
                    }
                }
            }
        });
        return PageUtil.getPV(list, ObjectUtil.isEmpty(dbPage)? list.size(): Objects.requireNonNull(dbPage).getTotal());
    }

    @Override
    public PageView listNoPage(BusinessAttachmentQuery query) {
        List<BusinessAttachmentPO> list = businessAttachmentService.queryByPage(null, query);
        return PageUtil.getPV(list, list.size());
    }

    @Override
    public PageView listNoPageByCodes(BusinessAttachmentQuery query) {
        List<BusinessAttachmentPO> list = businessAttachmentService.queryByPageByCodes(null, query);
        if (query.getBusinessTypeCodes().contains("purchase_to_delivery_order")){
            List<String> businessCodeList = query.getBusinessCodeList();
            List<String> purchaseCodeAndDeliveryCodeList = query.getPurchaseCodeAndDeliveryCodeList();
            if (CollUtil.isNotEmpty(purchaseCodeAndDeliveryCodeList)){
                businessCodeList.forEach(businessCode -> {
                    purchaseCodeAndDeliveryCodeList.forEach(purchaseCodeAndDeliveryCode -> {
                        //取purchaseCodeAndDeliveryCode中_号之前的字符串
                        String purchaseCode = purchaseCodeAndDeliveryCode.split("_")[0];
                        if (purchaseCode.equals(businessCode)){
                            String deliveryOrderCodes = purchaseCodeAndDeliveryCode.split("_")[1];
                            BusinessAttachmentQuery query1 = new BusinessAttachmentQuery();
                            query1.setBusinessCodes(deliveryOrderCodes);
                            query1.setTypes(query.getTypes());
                            List<BusinessAttachmentPO> list1 = businessAttachmentService.queryByPageByCodes(null, query1);
                            if (CollUtil.isNotEmpty(list1)){
//                                list1.forEach(detailPO -> {detailPO.setBusinessCode(businessCode);});
                                list.addAll(list1);
                            }
                        }
                    });
                });
            }
        }
        if (query.getBusinessTypeCodes().contains("delivery_to_purchase_order")){
            List<String> businessCodeList = query.getBusinessCodeList();
            List<String> purchaseCodeAndDeliveryCodeList = query.getPurchaseCodeAndDeliveryCodeList();
            if (CollUtil.isNotEmpty(purchaseCodeAndDeliveryCodeList)){
                businessCodeList.forEach(businessCode -> {
                    purchaseCodeAndDeliveryCodeList.forEach(purchaseCodeAndDeliveryCode -> {
                        //取purchaseCodeAndDeliveryCode中_号之前的字符串
                        String deliveryCode = purchaseCodeAndDeliveryCode.split("_")[1];
                        if (deliveryCode.equals(businessCode)){
                            String poCodes = purchaseCodeAndDeliveryCode.split("_")[0];
                            BusinessAttachmentQuery query1 = new BusinessAttachmentQuery();
                            query1.setBusinessCodes(poCodes);
                            query1.setTypes("delivery_order");
                            List<BusinessAttachmentPO> list1 = businessAttachmentService.queryByPageByCodes(null, query1);
                            if (CollUtil.isNotEmpty(list1)){
                                list1.forEach(detailPO -> {detailPO.setBusinessCode(businessCode);});
                                list.addAll(list1);
                            }
                        }
                    });
                });
            }
        }
        //加载采购订单最新的签署附件
        if (query.getBusinessTypeCodes().contains("purchase_order_sign")){
            List<BusinessAttachmentPO> purchaseOrderList = new ArrayList<>();
            List<String> businessCodeList = query.getBusinessCodeList();
            businessCodeList.forEach(businessCode -> {
                DigitalSealBusinessDetail digitalSealBusinessDetail = digitalSealBusinessDetailService.getLastPurchaseOrderByBusinessCode(businessCode);
                if (ObjectUtil.isNotNull(digitalSealBusinessDetail)){
                    BusinessAttachmentPO detailPO = businessAttachmentConvert.signDetail2PO(digitalSealBusinessDetail);
                    detailPO.setBusinessTypeCode("purchase_order");
                    detailPO.setType("purchase_order");
                    detailPO.setBusinessCode(businessCode);
                    Attachment attachment = attachmentService.getById(detailPO.getFileId());
                    if (ObjectUtil.isNotNull(attachment)){
                        detailPO.setFileName(attachment.getFileName());
                    }
                    purchaseOrderList.add(detailPO);
                }else {
                    BusinessAttachmentPO detailPO = digitalSealBusinessDetailService.getLastPurchaseOrderAttachmentByBusinessCode(businessCode);
                    if (ObjectUtil.isNotNull(detailPO)){
                        detailPO.setBusinessTypeCode("purchase_order");
                        detailPO.setType("purchase_order");
                        detailPO.setBusinessCode(businessCode);
                        purchaseOrderList.add(detailPO);
                    }
                }
            });
            if (CollUtil.isNotEmpty(purchaseOrderList)){
                list.addAll(purchaseOrderList);
            }
        }
        //加载送货单最新的签署附件
        if (query.getBusinessTypeCodes().contains("delivery_order_sign")){
            List<BusinessAttachmentPO> purchaseOrderList = new ArrayList<>();
            List<String> businessCodeList = query.getBusinessCodeList();
            businessCodeList.forEach(businessCode -> {
                DigitalSealBusinessDetail digitalSealBusinessDetail = digitalSealBusinessDetailService.getLastDeliveryOrderByBusinessCode(businessCode);
                if (ObjectUtil.isNotNull(digitalSealBusinessDetail)){
                    BusinessAttachmentPO detailPO = businessAttachmentConvert.signDetail2PO(digitalSealBusinessDetail);
                    detailPO.setBusinessTypeCode("delivery_order");
                    detailPO.setType("delivery_order");
                    detailPO.setBusinessCode(businessCode);
                    Attachment attachment = attachmentService.getById(detailPO.getFileId());
                    if (ObjectUtil.isNotNull(attachment)){
                        detailPO.setFileName(attachment.getFileName());
                    }
                    purchaseOrderList.add(detailPO);
                }
            });
            if (CollUtil.isNotEmpty(purchaseOrderList)){
                list.addAll(purchaseOrderList);
            }
        }

        if (StrUtil.isEmpty(query.getBusinessIds())){
            list.forEach(po -> po.setImageCode(null));
        }
        //list中根据fileId去除重复的
        if (CollUtil.isNotEmpty(list)){
            List<BusinessAttachmentPO> list1 = list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(()
                    -> new TreeSet<>(Comparator.comparing(o -> o.getFileId() + ";" + o.getBusinessCode()))), ArrayList::new));
            return PageUtil.getPV(businessAttachmentConvert.poList2dtoList(list1), list.size());
        }

        return PageUtil.getPV(businessAttachmentConvert.poList2dtoList(list), list.size());
    }

    @Override
    public List<BusinessAttachment> saveAttachment(List<BusinessAttachmentDTO> saveList) {
        List<BusinessAttachment> entityList = businessAttachmentConvert.dtoList2EntityList(saveList);
        for (BusinessAttachment entity : entityList) {
            Attachment attachment = attachmentService.getById(entity.getFileId());
            if (ObjectUtil.isNull(attachment)){
                continue;
            }
            entity.setFileName(attachment.getFileName());
            entity.setCreateUser(LoginUtil.getUserId());
            entity.setCreateTime(LocalDateTime.now());
            entity.setUpdateUser(LoginUtil.getUserId());
            entity.setUpdateTime(LocalDateTime.now());
        }
        businessAttachmentService.saveOrUpdateBatch(entityList);
        return entityList;
    }

    @Override
    public void deleteAttachment(BusinessAttachmentDeleteOrUpdateDTO deleteDTO) {
        BusinessAttachment deleteEntity = businessAttachmentService.getById(deleteDTO.getId());
        deleteEntity.setDeleteFlag(1);
        deleteEntity.setRemark(deleteDTO.getRemark());
        deleteEntity.setUpdateTime(LocalDateTime.now());
        deleteEntity.setUpdateUser(LoginUtil.getUserId());
        businessAttachmentService.saveOrUpdate(deleteEntity);
        /**
         * 如果是合同资产付款申请删除附件，则不需要解绑文件关系
         */
        if (null != deleteDTO.getBusinessTypeCode() && "contract_payment_apply".equals(deleteDTO.getBusinessTypeCode())) {

        } else {
            final LambdaQueryWrapper<BusinessAttachment> queryWrapper = new LambdaQueryWrapper<>();
            //删除附件时，需要同步解绑附件与其他单据的关系（附件与源单据的关系无需解绑）
            queryWrapper.eq(BusinessAttachment::getFileId, deleteEntity.getFileId())
                    .ne(BusinessAttachment::getBusinessId, deleteEntity.getBusinessId());
            businessAttachmentService.remove(queryWrapper);
        }
    }
    @Override
    public void deleteCheck(BusinessAttachmentDeleteOrUpdateDTO deleteDTO) {
        BusinessAttachment deleteEntity = businessAttachmentService.getById(deleteDTO.getId());
        //如果是送货单，则检查该附件是否被对账单使用
        if (deleteEntity.getBusinessTypeCode().equals("delivery_order")){
            BusinessAttachment businessAttachment = businessAttachmentService.getAccountByFileIdAndNotEqId(deleteEntity.getFileId(),deleteEntity.getId());
            if (ObjectUtil.isNotNull(businessAttachment)){
                throw new DaoException(StrUtil.format("附件已被对账单：{}使用，不可删除", businessAttachment.getBusinessCode()));
            }
        }
        if (deleteEntity.getBusinessTypeCode().equals("purchase_order")){
            BusinessAttachment businessAttachment = businessAttachmentService.getPurchaseByFileIdAndNotEqId(deleteEntity.getFileId(),deleteEntity.getId());
            if (ObjectUtil.isNotNull(businessAttachment)){
                throw new DaoException(StrUtil.format("附件已被开票申请单：{}使用，不可删除", businessAttachment.getBusinessCode()));
            }
        }
        if (deleteEntity.getBusinessTypeCode().equals("customs_declaration")){
            BusinessAttachment businessAttachment = businessAttachmentService.getCustomsByFileIdAndNotEqId(deleteEntity.getFileId(),deleteEntity.getId());
            if (ObjectUtil.isNotNull(businessAttachment)){
                throw new DaoException(StrUtil.format("附件已被报关单：{}使用，不可删除", businessAttachment.getBusinessCode()));
            }
        }
        if (deleteEntity.getBusinessTypeCode().equals("payment_notice")){
            BusinessAttachment businessAttachment = businessAttachmentService.getPaymentNoticeByFileIdAndNotEqId(deleteEntity.getFileId(),deleteEntity.getId());
            if (ObjectUtil.isNotNull(businessAttachment)){
                throw new DaoException(StrUtil.format("附件已被付款通知单：{}使用，不可删除", businessAttachment.getBusinessCode()));
            }
        }

    }

    @Override
    public void remarkAttachment(BusinessAttachmentDeleteOrUpdateDTO updateDTO) {
        BusinessAttachment deleteEntity = businessAttachmentService.getById(updateDTO.getId());
        deleteEntity.setRemark(updateDTO.getRemark());
        deleteEntity.setUpdateTime(LocalDateTime.now());
        deleteEntity.setUpdateUser(LoginUtil.getUserId());
        businessAttachmentService.saveOrUpdate(deleteEntity);
    }

    @Override
    public List<BusinessAttachmentDTO> getListByBusinessIds(List<Long> businessIds, String type) {
        final LambdaQueryWrapper<BusinessAttachment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(BusinessAttachment::getBusinessId, businessIds)
                .eq(BusinessAttachment::getType, type)
                .eq(BusinessAttachment::getDeleteFlag, 0);
        List<BusinessAttachment> list = businessAttachmentService.list(queryWrapper);
        return businessAttachmentConvert.entityList2dtoList(list);
    }

    @Override
    public List<BusinessAttachmentDTO> getListByBusinessId(Long businessId) {
        List<BusinessAttachmentPO> listPO = businessAttachmentService.getListByBusinessId(businessId);
        return businessAttachmentConvert.poList2dtoList(listPO);
    }

    @Override
    public List<String> findInvoiceByFileId(Long id) {
        return businessAttachmentService.findInvoiceByFileId(id);
    }
}
