package com.testor.module.contractor.ledger.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.testor.biz.sys.dict.data.model.domain.SysDictData;
import com.testor.common.constant.StatusEnum;
import com.testor.common.core.utils.StringUtils;
import com.testor.module.contractor.enums.GeneralFlagEnum;
import com.testor.module.contractor.ledger.dao.TContractorLedgerDao;
import com.testor.module.contractor.ledger.model.domain.TContractorContract;
import com.testor.module.contractor.ledger.model.domain.TContractorInfo;
import com.testor.module.contractor.ledger.model.domain.TContractorLedger;
import com.testor.module.contractor.ledger.model.dto.LedgerTypeVo;
import com.testor.module.contractor.ledger.model.dto.TContractorLedgerDto;
import com.testor.module.contractor.ledger.model.dto.TContractorLedgerParam;
import com.testor.module.contractor.ledger.service.TContractorContractService;
import com.testor.module.contractor.ledger.service.TContractorInfoService;
import com.testor.module.contractor.ledger.service.TContractorLedgerService;
import com.testor.module.contractor.manage.service.TContractorBlacklistService;
import com.testor.module.sys.model.domian.NewSysOrg;
import com.testor.module.sys.service.NewSysDictDataService;
import com.testor.module.sys.service.NewSysOrgService;
import com.tongtech.tfw.backend.common.biz.constants.BizConstants;
import com.tongtech.tfw.backend.common.context.ContextUtils;
import com.tongtech.tfw.backend.common.models.exceptions.ServiceException;
import com.tongtech.tfw.backend.common.models.response.ResponseInfo;
import com.tongtech.tfw.backend.common.models.supers.SuperServiceImpl;
import com.tongtech.tfw.backend.common.models.sys.UserInfo;
import com.tongtech.tfw.backend.core.helper.IdHelper;
import com.tongtech.tfw.backend.core.helper.ObjectHelper;
import com.tongtech.tfw.backend.core.helper.StringHelper;
import com.tongtech.tfw.backend.core.helper.bean.BeanHelper;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 承包商台账Service业务层处理
 * 
 * @author testor-framework
 * @date 2024-11-19 10:01:42
 */
@Service
public class TContractorLedgerServiceImpl extends SuperServiceImpl<TContractorLedgerDao, TContractorLedger> implements TContractorLedgerService
{
    @Autowired(required = false)
    private TContractorLedgerDao tContractorLedgerDao;

    @Autowired
    private TContractorContractService tContractorContractService;

    @Autowired
    private TContractorInfoService tContractorInfoService;

    @Autowired
    private NewSysOrgService newSysOrgService;

    @Autowired
    private TContractorBlacklistService tContractorBlacklistService;

    @Autowired
    private NewSysDictDataService newSysDictDataService;

    private boolean verifyContractorInformation(TContractorLedgerDto tContractorLedgerDto) {
        // 使用 LambdaQueryWrapper 查询是否存在相同 InfoId 和 TypeId，且状态不是 DELETE 的记录
        String orgId = ContextUtils.getLoginUser().getOrgId();
        return this.count(new LambdaQueryWrapper<TContractorLedger>()
                .eq(TContractorLedger::getInfoId, tContractorLedgerDto.getInfoId())
                .eq(TContractorLedger::getTypeId, tContractorLedgerDto.getTypeId())
                .eq(TContractorLedger::getOrgId, orgId)
                .ne(StringUtils.isNotBlank(tContractorLedgerDto.getId()),TContractorLedger::getId,tContractorLedgerDto.getId())
                .ne(TContractorLedger::getStatus, StatusEnum.DELETE.getCode())) == 0;
    }

    @Override
    public TContractorLedger addContractorLedger(TContractorLedgerDto addRequest) {
        // 校验输入参数是否为空
        if (ObjectHelper.isEmpty(addRequest)) {
            throw new ServiceException(new ResponseInfo(400, "请求参数不能为空"));
        }
        // 验证承包商信息是否存在重复
        if (!this.verifyContractorInformation(addRequest)) {
            throw new ServiceException(new ResponseInfo(400, "承包商信息已存在"));
        }
        // 生成 32 位 ID
        String id = IdHelper.getId32bit();
        // 转换 DTO 为实体对象
        TContractorLedger data = BeanHelper.beanToBean(addRequest, TContractorLedger.class);
        data.setId(id);
        data.setInfoId(checkContractorInfo(addRequest.getTContractorInfo())); // 设置承包商信息 ID
        // 保存承包商台账数据
        if (this.save(data)) {
            // 保存合同信息
            List<TContractorContract> contracts = addRequest.getTContractorContracts();
            contracts.forEach(contract -> contract.setContractorId(id));
            tContractorContractService.saveBatch(contracts);
            // 返回新建的承包商台账实体
            TContractorLedger newEntity = new TContractorLedger();
            newEntity.setId(id);
            return newEntity;
        }
        return null;
    }

    private String checkContractorInfo(TContractorInfo tContractorInfo) {
        if (tContractorInfo == null) {
            throw new ServiceException(new ResponseInfo(400, "承包商信息不能为空"));
        }
        String infoId = tContractorInfo.getId();

        // 根据名称和统一社会信用代码获取承包商信息
        TContractorInfo existingInfo = tContractorInfoService.getInfoByNameAndCreditCode(
                tContractorInfo.getName(),
                tContractorInfo.getCreditCode()
        );
        if (existingInfo != null) {
            // 如果传入的 infoId 不为空，且与查询到的 infoId 不一致，表示更换了承包商信息
            if (StringUtils.isNotBlank(infoId) && !infoId.equals(existingInfo.getId())) {
                handleUnboundContractor(existingInfo.getId());
            }
            // 修改信息
            tContractorInfo.setId(existingInfo.getId());
            tContractorInfoService.updateById(tContractorInfo);
            return existingInfo.getId();
        }
        // 不存在的情况下处理新增
        if (StringUtils.isNotBlank(infoId)) {
            handleUnboundContractor(infoId);
        }
        String id32bit = IdHelper.getId32bit();
        tContractorInfo.setId(id32bit);
        // 保存新的承包商信息
        tContractorInfoService.save(tContractorInfo);
        return tContractorInfo.getId();
    }

    /**
     * 处理未绑定的承包商信息，如果未绑定则删除
     */
    private void handleUnboundContractor(String infoId) {
        int count = this.count(new LambdaQueryWrapper<TContractorLedger>()
                .eq(TContractorLedger::getInfoId, infoId)
                .ne(TContractorLedger::getStatus, StatusEnum.DELETE.getCode()));

        // 如果没有绑定记录，删除承包商信息
        if (count == 0) {
            tContractorInfoService.deleteEntity(infoId);
        }
    }

    @Override
    public TContractorLedgerDto getLedgerById(String id) {
        // 获取台账信息
        TContractorLedger ledger = this.getById(id);
        if (ledger == null) {
            return null;
        }
        // 转换台账信息为 DTO
        TContractorLedgerDto ledgerDto = BeanHelper.beanToBean(ledger, TContractorLedgerDto.class);
        // 获取承包商信息
        TContractorInfo contractorInfo = tContractorInfoService.getById(ledger.getInfoId());
        if(contractorInfo != null && GeneralFlagEnum.YES.getCode().equals(contractorInfo.getIsBlacklist())) {
            String name = StringUtils.format("{}（黑名单）", contractorInfo.getName());
            contractorInfo.setName(name);
        }
        ledgerDto.setTContractorInfo(contractorInfo);
        // 获取合同信息
        List<TContractorContract> contracts = tContractorContractService.findByContractId(id);
        ledgerDto.setTContractorContracts(contracts);
        return ledgerDto;
    }

    @Override
    public Page<TContractorLedger> pageList(TContractorLedgerParam param) {
        param.setOrgId(ContextUtils.getLoginUser().getOrgId());

        Long page=
                StringHelper.isEmpty(param.getPage())? BizConstants.PAGE:Long.valueOf(param.getPage());
        Long limit=
                StringHelper.isEmpty(param.getLimit())?BizConstants.LIMIT:Long.valueOf(param.getLimit());
        Page<TContractorLedger> resultPage=new Page<>(page,limit);
//        QueryWrapper<TContractorLedger> queryWrapper=this.createQuery(param);
        Page<TContractorLedger> pageList = tContractorLedgerDao.pageList(resultPage, param);
        List<TContractorLedger> records = pageList.getRecords();
        for (TContractorLedger record : records) {
            TContractorInfo tContractorInfo = tContractorInfoService.getById(record.getInfoId());
            if (tContractorInfo != null) {
                String isBlacklist = tContractorInfo.getIsBlacklist();
                if(GeneralFlagEnum.YES.getCode().equals(isBlacklist)) {
                    String name = StringHelper.format("{}（黑名单）", tContractorInfo.getName());
                    tContractorInfo.setName(name);
                }
                record.setTContractorInfo(tContractorInfo);
            }
            String orgId = record.getOrgId();
            NewSysOrg sysOrg = newSysOrgService.getById(orgId);
            if (sysOrg != null) {
                record.setOrgName(sysOrg.getOrgName());
            }

        }
        return pageList;
    }

    @Override
    public TContractorLedger updateEntity(TContractorLedgerDto updateRequest) {
        TContractorLedger data=BeanHelper.beanToBean(updateRequest, TContractorLedger.class);
        data.setInfoId(checkContractorInfo(updateRequest.getTContractorInfo()));
        // 验证承包商信息是否存在重复
        if (!this.verifyContractorInformation(updateRequest)) {
            throw new ServiceException(new ResponseInfo(400, "承包商信息已存在"));
        }

        boolean result = this.updateById(data);
        if(result) {
            //删除合同
            tContractorContractService.remove(new LambdaQueryWrapper<TContractorContract>().eq(TContractorContract::getContractorId, updateRequest.getId()));
            //新增合同
            tContractorContractService.saveBatch(updateRequest.getTContractorContracts());
            //修改企业信息
            TContractorInfo tContractorInfo = updateRequest.getTContractorInfo();
            tContractorInfoService.updateById(tContractorInfo);
        }
        return null;
    }

    @Override
    public List<LedgerTypeVo> getLedgerTypeVo(TContractorLedgerParam param) {
        String orgId = ContextUtils.getLoginUser().getOrgId();
        List<TContractorLedger> tContractorLedgers = this.list(new LambdaQueryWrapper<TContractorLedger>().eq(TContractorLedger::getInfoId,param.getInfoId()).eq(TContractorLedger::getOrgId, orgId));
        List<String> alreadyHasTypeIds = tContractorLedgers.stream().map(TContractorLedger::getTypeId).collect(Collectors.toList());
        List<SysDictData> dictByType = newSysDictDataService.getDictByType("contractor_type");
        List<String> typeIds = dictByType.stream().map(SysDictData::getDictDataId).collect(Collectors.toList());

        return typeIds.stream().map(typeId -> {
            LedgerTypeVo ledgerTypeVo = new LedgerTypeVo();
            ledgerTypeVo.setLedgerTypeId(typeId);
            // 判断是否已经选择
            ledgerTypeVo.setIsChoose(alreadyHasTypeIds.contains(typeId) ? "0" : "1");
            return ledgerTypeVo;
        }).collect(Collectors.toList());
    }

    @Override
    public TContractorLedger findLedgerByName(String name) {
        Page<TContractorLedger> resultPage=new Page<>(1,10);
        TContractorLedgerParam param=new TContractorLedgerParam();
        param.setName(name);
        param.setOrgId(ContextUtils.getLoginUser().getOrgId());
        Page<TContractorLedger> tContractorLedgerPage = tContractorLedgerDao.pageList(resultPage, param);
        if (tContractorLedgerPage!=null && CollectionUtils.isNotEmpty(tContractorLedgerPage.getRecords())  ){
            return tContractorLedgerPage.getRecords().stream().findFirst().orElse(null);
        }
       return null;
    }

    /**
     * 列表查询条件及查询参数
     */
    private QueryWrapper<TContractorLedger> createQuery(TContractorLedgerParam queryParam){
        QueryWrapper<TContractorLedger> queryWrapper=new QueryWrapper<>();
        UserInfo loginUser = ContextUtils.getLoginUser();
        String orgId = loginUser.getOrgId();
        List<String> idsChildrenById = newSysOrgService.getIdsChildrenById(orgId);
        //查询下级机构id
        queryWrapper.in("org_id", idsChildrenById);
        if (queryParam.getName() != null){
            List<TContractorInfo> tContractorInfos = tContractorInfoService.list(new LambdaQueryWrapper<TContractorInfo>().like(TContractorInfo::getName, queryParam.getName()));
            if (tContractorInfos != null && tContractorInfos.size() > 0) {
                queryWrapper.in("info_id", tContractorInfos.stream().map(TContractorInfo::getId).collect(Collectors.toList()));
            }
        }
        if(ObjectHelper.isNotEmpty(queryParam.getValidPeriodStart())&&StringUtils.isNotEmpty(queryParam.getValidPeriodEnd())) {
            List<TContractorInfo> tContractorInfos =
                    tContractorInfoService.list(new LambdaQueryWrapper<TContractorInfo>().between(TContractorInfo::getValidPeriod,
                            queryParam.getValidPeriodStart(), queryParam.getValidPeriodEnd()));
            if (tContractorInfos != null && tContractorInfos.size() > 0) {
                queryWrapper.in("info_id", tContractorInfos.stream().map(TContractorInfo::getId).collect(Collectors.toList()));
            }
        }
        if (StringHelper.isNotEmpty(queryParam.getStatus())) {
            queryWrapper.eq(TContractorLedger.STATUS, queryParam.getStatus());
        } else {
            queryWrapper.ne(TContractorLedger.STATUS, BizConstants.STATUS_DELETE);
        }
        if (StringHelper.isNotEmpty(queryParam.getOrderBy())){
            if(StringHelper.isNotEmpty(queryParam.getOrderType())
                    &&BizConstants.ASC.equals(queryParam.getOrderType())){
                queryWrapper.orderByAsc(queryParam.getOrderBy());
            }else{
                queryWrapper.orderByDesc(queryParam.getOrderBy());
            }
        }else{
            queryWrapper.orderByDesc(TContractorLedger.UPDATE_DATE);
        }
        return queryWrapper;
    }
}
