package com.yd.csf.service.service.impl;
import java.util.Date;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yd.auth.core.dto.AuthUserDto;
import com.yd.auth.core.utils.SecurityUtil;
import com.yd.common.enums.CommonEnum;
import com.yd.common.enums.ResultCode;
import com.yd.common.exception.BusinessException;
import com.yd.common.result.Result;
import com.yd.common.utils.RandomStringGenerator;
import com.yd.csf.service.common.ErrorCode;
import com.yd.csf.service.dto.*;
import com.yd.csf.service.enums.FnaStatusEnum;
import com.yd.csf.service.enums.PolicyFollowStatusEnum;
import com.yd.csf.service.enums.PolicyStatusEnum;
import com.yd.csf.service.model.*;
import com.yd.csf.service.service.*;
import com.yd.csf.service.dao.PolicyFollowMapper;
import com.yd.csf.service.utils.AsyncQueryUtil;
import com.yd.csf.service.vo.PolicyAdditionalVO;
import com.yd.csf.service.vo.PolicyFollowDetailVO;
import com.yd.csf.service.vo.PolicyFollowVO;
import com.yd.csf.service.vo.PolicyNumberResponseVO;
import com.yd.insurance.base.feign.client.insurancereconciliationcompany.ApiInsuranceReconciliationCompanyFeignClient;
import com.yd.insurance.base.feign.request.insurancereconciliationcompany.ApiInsuranceReconciliationCompanyPageRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author Zhang Jianan
* @description 针对表【policy_follow(新单跟进表)】的数据库操作Service实现
* @createDate 2025-09-16 18:18:06
*/
@Service
@Slf4j
public class PolicyFollowServiceImpl extends ServiceImpl<PolicyFollowMapper, PolicyFollow>
    implements PolicyFollowService{

    @Resource
    private PolicyBrokerService policyBrokerService;
    @Resource
    private PolicyService policyService;
    @Resource
    private PolicyFollowService policyFollowService;
    @Resource
    private PolicyFollowRecordService policyFollowRecordService;
    @Resource
    private PolicyFollowFileService policyFollowFileService;
    @Resource
    private AsyncQueryUtil asyncQueryUtil;
    @Resource
    private PolicyPolicyholderService policyPolicyholderService;
    @Resource
    private PolicyInsurantService policyInsurantService;
    @Resource
    private PolicyBeneficiaryService policyBeneficiaryService;
    @Resource
    private PolicySecondHolderService policySecondHolderService;
    @Resource
    private PolicyAdditionalService policyAdditionalService;
    @Resource
    private IExpectedFortuneService expectedFortuneService;
    @Autowired
    private CommissionExpectedService commissionExpectedService;
    @Resource
    private IAppointmentService appointmentService;
    @Resource
    private FnaService fnaService;
    @Resource
    private ApiInsuranceReconciliationCompanyFeignClient apiInsuranceReconciliationCompanyFeignClient;


    @Override
    public PolicyFollow getByPolicyBizId(String policyBizId) {
        return this.getOne(new QueryWrapper<PolicyFollow>().eq("policy_biz_id", policyBizId));
    }

    @Override
    public QueryWrapper<PolicyFollow> getQueryWrapper(PolicyFollowQueryRequest policyFollowQueryRequest) {
        QueryWrapper<PolicyFollow> queryWrapper = new QueryWrapper<>();
        if (policyFollowQueryRequest == null) {
            return queryWrapper;
        }

        String policyNo = policyFollowQueryRequest.getPolicyNo();
        String status = policyFollowQueryRequest.getStatus();
        String appointmentNo = policyFollowQueryRequest.getAppointmentNo();
        Date signDateStart = policyFollowQueryRequest.getSignDateStart();
        Date signDateEnd = policyFollowQueryRequest.getSignDateEnd();
        Date latestPaymentDate = policyFollowQueryRequest.getLatestPaymentDate();
        List<String> insuranceCompanyBizIdList = policyFollowQueryRequest.getInsuranceCompanyBizIdList();
        List<String> productLaunchBizIdList = policyFollowQueryRequest.getProductLaunchBizIdList();
        String issueNumber = policyFollowQueryRequest.getIssueNumber();

        queryWrapper.like(ObjectUtils.isNotEmpty(policyNo), "policy_no", policyNo);
        queryWrapper.eq(ObjectUtils.isNotEmpty(status), "status", status);
        queryWrapper.eq(ObjectUtils.isNotEmpty(appointmentNo), "appointment_no", appointmentNo);
        queryWrapper.ge(ObjectUtils.isNotEmpty(signDateStart), "sign_date", signDateStart);
        queryWrapper.le(ObjectUtils.isNotEmpty(signDateEnd), "sign_date", signDateEnd);
        queryWrapper.ge(ObjectUtils.isNotEmpty(latestPaymentDate), "latest_payment_date", latestPaymentDate);

        if (CollectionUtils.isNotEmpty(insuranceCompanyBizIdList)) {
            queryWrapper.in("insurance_company_biz_id", insuranceCompanyBizIdList);
        }
        if (CollectionUtils.isNotEmpty(productLaunchBizIdList)) {
            queryWrapper.in("product_launch_biz_id", productLaunchBizIdList);
        }
        queryWrapper.eq(ObjectUtils.isNotEmpty(issueNumber), "issue_number", issueNumber);
        // 排序：按创建时间倒序
        queryWrapper.orderByDesc("id");

        return queryWrapper;
    }

    @Override
    public Page<PolicyFollowVO> getPolicyFollowVOPage(Page<PolicyFollow> policyFollowPage) {
        List<PolicyFollow> policyFollowList = policyFollowPage.getRecords();
        Page<PolicyFollowVO> policyFollowVOPage = new Page<>(policyFollowPage.getCurrent(), policyFollowPage.getSize(), policyFollowPage.getTotal());
        if (CollUtil.isEmpty(policyFollowList)) {
            return policyFollowVOPage;
        }
        // 对象列表 => 封装对象列表
        List<PolicyFollowVO> policyFollowVOList = policyFollowList.stream().map(PolicyFollowVO::objToVo).collect(Collectors.toList());

        return policyFollowVOPage.setRecords(policyFollowVOList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updatePolicyFollow(PolicyFollowUpdateRequest policyFollowUpdateRequest) {
        // 校验参数
        if (StringUtils.isBlank(policyFollowUpdateRequest.getPolicyBizId())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR.getCode(), "policyBizId不能为空");
        }
        String policyBizId = policyFollowUpdateRequest.getPolicyBizId();
        PolicyFollow policyFollow = getByPolicyBizId(policyBizId);
        if (policyFollow == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR.getCode(), ErrorCode.NOT_FOUND_ERROR.getMessage());
        }
        // 跟进信息
        PolicyFollowUpdateDto policyFollowUpdateDto = policyFollowUpdateRequest.getPolicyFollowUpdateDto();
        if (policyFollowUpdateDto != null) {
            BeanUtils.copyProperties(policyFollowUpdateDto, policyFollow, "id", "policyBizId");

            // 计算冷却期结束日期
            if (policyFollowUpdateDto.getCoolingOffDays() != null && policyFollowUpdateDto.getEffectiveDate() != null) {
                policyFollow.setCoolingOffEndDate(DateUtil.offset(policyFollowUpdateDto.getEffectiveDate(), DateField.DAY_OF_MONTH, policyFollowUpdateDto.getCoolingOffDays()));
            }
            // 获取币种字典值
            policyFollow.setPolicyCurrency(this.getCurrencyValue(policyFollowUpdateDto.getPolicyCurrency()));
        }
        // 设置核保信息
        setValidPolicyInfo(policyFollow, policyFollowUpdateRequest.getVerifyPolicyInfo());
        // 设置保单邮寄
        setPolicyMailing(policyFollow, policyFollowUpdateRequest.getPolicyMailing());

        // 获取当前登录用户
        AuthUserDto currentLoginUser = SecurityUtil.getCurrentLoginUser();
        String loginUserId = currentLoginUser.getId().toString();
        policyFollow.setUpdaterId(loginUserId);
        policyFollow.setUpdateTime(new Date());

        return updateById(policyFollow);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updatePolicyFollowDto(PolicyFollowDto policyFollowDto) {
        // 校验参数
        if (StringUtils.isBlank(policyFollowDto.getPolicyBizId())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR.getCode(), "policyBizId不能为空");
        }
        String policyBizId = policyFollowDto.getPolicyBizId();
        PolicyFollow policyFollow = getByPolicyBizId(policyBizId);
        if (policyFollow == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR.getCode(), "新单跟进记录不存在");
        }

        // 复制属性，排除系统字段
        BeanUtils.copyProperties(policyFollowDto, policyFollow, "id", "policyBizId", "brokerList");

        // 检查保单号是否从空变为有值
        String oldPolicyNo = policyFollow.getPolicyNo();
        String newPolicyNo = policyFollowDto.getPolicyNo();
        boolean isPolicyNoUpdated = StringUtils.isBlank(oldPolicyNo) && StringUtils.isNotBlank(newPolicyNo);

        // 计算冷却期结束日期
        if (policyFollowDto.getCoolingOffDays() != null && policyFollowDto.getEffectiveDate() != null) {
            policyFollow.setCoolingOffEndDate(DateUtil.offset(policyFollowDto.getEffectiveDate(), DateField.DAY_OF_MONTH, policyFollowDto.getCoolingOffDays()));
        }

        // 获取当前登录用户
        AuthUserDto currentLoginUser = SecurityUtil.getCurrentLoginUser();
        String loginUserId = currentLoginUser.getId().toString();
        policyFollow.setUpdaterId(loginUserId);
        policyFollow.setUpdateTime(new Date());

        boolean result = updateById(policyFollow);

        // 如果保单号从空变为有值，更新关联的FNA状态为"签单完成"
        if (isPolicyNoUpdated && result) {
            fnaService.lambdaUpdate()
                    .eq(Fna::getFnaBizId, policyFollow.getFnaBizId())
                    .set(Fna::getStatus, FnaStatusEnum.SIGNED_COMPLETED.getItemValue())
                    .update();
        }

        return result;
    }

    private void setPolicyMailing(PolicyFollow policyFollow, PolicyMailing policyMailing) {
        if (policyMailing == null) {
            return;
        }
        policyFollow.setMailingMethod(policyMailing.getMailingMethod());
//        policyFollow.setBrokerSignDate(policyMailing.getBrokerSignDate());
//        policyFollow.setInsurerMailingDate(policyMailing.getInsurerMailingDate());
//        policyFollow.setCustomerSignDate(policyMailing.getCustomerSignDate());
    }

    private void setValidPolicyInfo(PolicyFollow policyFollow, VerifyPolicyInfo verifyPolicyInfo) {
        if (verifyPolicyInfo == null) {
            return;
        }
        policyFollow.setSubmitDate(verifyPolicyInfo.getSubmitDate());
        policyFollow.setSignDate(verifyPolicyInfo.getSignDate());
        policyFollow.setIssueDate(verifyPolicyInfo.getIssueDate());
        policyFollow.setEffectiveDate(verifyPolicyInfo.getEffectiveDate());
//        policyFollow.setIsPrepaid(verifyPolicyInfo.getIsPrepaid());
        policyFollow.setPrepaidAmount(verifyPolicyInfo.getPrepaidAmount());
        policyFollow.setPrepaidAmountAfterDiscount(verifyPolicyInfo.getPrepaidAmountAfterDiscount());
        policyFollow.setPolicyExpirationDate(verifyPolicyInfo.getPolicyExpirationDate());
    }

    @Override
    public PolicyFollowVO getPolicyFollowVO(PolicyFollow policyFollow) {
        if (policyFollow == null) {
            return null;
        }
        PolicyFollowVO policyFollowVO = PolicyFollowVO.objToVo(policyFollow);
        // 关联查询转介人
        QueryWrapper<PolicyBroker> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("policy_biz_id", policyFollow.getPolicyBizId());

        return policyFollowVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> addPolicyFollow(PolicyFollowAddRequest policyFollowAddRequest) {
        PolicyFollow policyFollow = new PolicyFollow();
        BeanUtils.copyProperties(policyFollowAddRequest, policyFollow);
        // 生成新单编号
        String policyBizId = RandomStringGenerator.generateBizId16(CommonEnum.UID_TYPE_POLICY.getCode());
        policyFollow.setPolicyBizId(policyBizId);

        // 计算冷却期结束日期
        if (policyFollowAddRequest.getCoolingOffDays() != null) {
            policyFollow.setCoolingOffEndDate(DateUtil.offset(policyFollowAddRequest.getEffectiveDate(), DateField.DAY_OF_MONTH, policyFollowAddRequest.getCoolingOffDays()));
        }
        // 获取币种字典值
        policyFollow.setPolicyCurrency(this.getCurrencyValue(policyFollowAddRequest.getCurrency()));


        // 保存转介人
        List<PolicyBroker> policyBrokerList = policyFollowAddRequest.getBrokerList();
        if (CollUtil.isNotEmpty(policyBrokerList)) {
            policyBrokerList.forEach(policyBroker -> {
                policyBroker.setPolicyBizId(policyBizId);
            });
        }

        this.save(policyFollow);
        policyBrokerService.saveBatch(policyBrokerList);

        // 保险产品相关字段不为空，则查询获取保单预计来佣
//        String policyNo = policyFollowAddRequest.getPolicyNo();
//        String productLaunchBizId = policyFollowAddRequest.getProductLaunchBizId();
//        String insuranceCompanyBizId = policyFollowAddRequest.getInsuranceCompanyBizId();
//        String reconciliationCompany = policyFollowAddRequest.getReconciliationCompany();
//        String reconciliationCompanyCode = policyFollowAddRequest.getReconciliationCompanyCode();
//        String reconciliationCompanyBizId = policyFollowAddRequest.getReconciliationCompanyBizId();
//        // 保存保单预计来佣
//        commissionExpectedService.getExpectedCommissionByProductlaunchId(policyNo, productLaunchBizId, insuranceCompanyBizId, reconciliationCompany, reconciliationCompanyCode, reconciliationCompanyBizId);

        // 返回新单跟进唯一业务ID
        return Collections.singletonMap("policyBizId", policyBizId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> addPolicyFollowDto(PolicyFollowDto policyFollowDto) {
        PolicyFollow policyFollow = new PolicyFollow();
        // 复制属性，排除系统字段
        BeanUtils.copyProperties(policyFollowDto, policyFollow, "id", "policyBizId", "brokerList", "signerList");

        // 生成新单编号
        String policyBizId = RandomStringGenerator.generateBizId16(CommonEnum.UID_TYPE_POLICY.getCode());
        policyFollow.setPolicyBizId(policyBizId);

        // 计算冷却期结束日期
        if (policyFollowDto.getCoolingOffDays() != null && policyFollowDto.getEffectiveDate() != null) {
            policyFollow.setCoolingOffEndDate(DateUtil.offset(policyFollowDto.getEffectiveDate(), DateField.DAY_OF_MONTH, policyFollowDto.getCoolingOffDays()));
        }

        // 获取当前登录用户
        AuthUserDto currentLoginUser = SecurityUtil.getCurrentLoginUser();
        String loginUserId = currentLoginUser.getId().toString();
        policyFollow.setCreatorId(loginUserId);
        policyFollow.setCreateTime(new Date());
        policyFollow.setUpdaterId(loginUserId);
        policyFollow.setUpdateTime(new Date());


        this.save(policyFollow);


        // 返回新单跟进唯一业务ID
        return Collections.singletonMap("policyBizId", policyBizId);
    }

    @Override
    public PolicyFollowDetailVO getPolicyFollowDetailVO(String policyBizId) {
        if (StringUtils.isBlank(policyBizId)) {
            return null;
        }
        // 查询主表
        PolicyFollow policyFollow = getByPolicyBizId(policyBizId);
        if (policyFollow == null) {
            return null;
        }

        // 转换为 DetailVO
        PolicyFollowDetailVO detailVO = PolicyFollowDetailVO.objToVo(policyFollow);

        // 查询介绍人列表
        List<PolicyBroker> brokerList = policyBrokerService.list(
                new QueryWrapper<PolicyBroker>()
                        .eq("policy_biz_id", policyBizId)
                        .eq("is_deleted", 0)
        );
        detailVO.setBrokerList(brokerList);

        // 查询附加险列表
        List<PolicyAdditional> additionalList = policyAdditionalService.lambdaQuery()
                .eq(PolicyAdditional::getPolicyBizId, policyBizId).list();
        List<PolicyAdditionalVO> additionalVOList = additionalList.stream()
                .map(PolicyAdditionalVO::objToVo)
                .collect(Collectors.toList());
        detailVO.setAdditionalList(additionalVOList);

        return detailVO;
    }


    @Override
     public Boolean addToPolicy(List<String> policyNoList) {
         if (CollectionUtils.isEmpty(policyNoList)) {
             throw new BusinessException(ErrorCode.PARAMS_ERROR.getCode(), "保单号列表不能为空");
         }
         // 获取当前登录用户
         AuthUserDto currentLoginUser = SecurityUtil.getCurrentLoginUser();
         String loginUserId = currentLoginUser.getId().toString();

         // 查询所有跟进记录
         List<PolicyFollow> policyFollowList = list(new QueryWrapper<PolicyFollow>().in("policy_no", policyNoList));
         for (PolicyFollow policyFollow : policyFollowList) {
             // 查询保单是否存在
             String policyBizId = policyFollow.getPolicyBizId();
             Policy policy = policyService.getOne(new QueryWrapper<Policy>().eq("policy_biz_id", policyBizId));
             if (policy != null) {
                 // 更新
                 BeanUtils.copyProperties(policyFollow, policy, "id");
                 policy.setUpdaterId(loginUserId);
                 policy.setUpdateTime(new Date());

                 policyService.updateById(policy);
             } else {
                 // 不存在则创建
                 policy = new Policy();
                 BeanUtils.copyProperties(policyFollow, policy, "id");
                 policy.setId(null);
                 policy.setPolicyBizId(policyBizId);
                 policy.setCreatorId(loginUserId);
                 policy.setCreateTime(new Date());
                 policy.setUpdaterId(loginUserId);
                 policy.setUpdateTime(new Date());

                 try {
                     policyService.save(policy);
                 } catch (DuplicateKeyException e) {
                     // 保单号已存在
                     throw new BusinessException("保单号 " + policyFollow.getPolicyNo() + " 已存在，请勿重复添加");
                 }
             }
             // 更新转介人
             updatePolicyBrokerPolicyNo(policyBizId, policyFollow.getPolicyNo());
         }
         return true;
     }

    private void updatePolicyBrokerPolicyNo(String policyBizId, String policyNo) {
        // 更新转介人保单号
        policyBrokerService.update(
                new UpdateWrapper<PolicyBroker>()
                        .set("policy_no", policyNo)
                        .eq("policy_biz_id", policyBizId)
                        .eq("is_deleted", 0)
        );
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean changePolicyFollowStatus(ChangePolicyFollowStatusRequest changePolicyFollowStatusRequest, PolicyFollow policyFollow) {
        if (changePolicyFollowStatusRequest == null || StringUtils.isBlank(changePolicyFollowStatusRequest.getPolicyBizId())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR.getCode(), "policyBizId不能为空");
        }
        if (policyFollow == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR.getCode(), ErrorCode.NOT_FOUND_ERROR.getMessage());
        }
        // 校验状态是否存在
        PolicyFollowStatusEnum policyFollowStatusEnum = PolicyFollowStatusEnum.getEnumByValue(changePolicyFollowStatusRequest.getStatus());
        if (policyFollowStatusEnum == null) {
            throw new BusinessException(ResultCode.PARAM_CHECK_ERROR.getCode(), "跟进状态不存在");
        }
        // 获取当前跟进状态
        PolicyFollowStatusEnum currentStatusEnum = PolicyFollowStatusEnum.getEnumByValue(policyFollow.getStatus());
        // 校验状态是否可变更 - 终态状态不能变更
        if (PolicyFollowStatusEnum.EFFECTIVE.equals(currentStatusEnum)
                || PolicyFollowStatusEnum.DECLINED.equals(currentStatusEnum)
                || PolicyFollowStatusEnum.CANCELLED.equals(currentStatusEnum)
                || PolicyFollowStatusEnum.CLOSED.equals(currentStatusEnum)
                || PolicyFollowStatusEnum.LAPSED.equals(currentStatusEnum)
        ) {
            throw new BusinessException(ResultCode.PARAM_CHECK_ERROR.getCode(), "生效、拒保、取消投保、关闭、失效状态不能变更");
        }

        String policyBizId = changePolicyFollowStatusRequest.getPolicyBizId();

        // 保单号和转接人都有的情况下，才能修改为生效状态
        if (PolicyFollowStatusEnum.EFFECTIVE.equals(policyFollowStatusEnum)) {
            if (StringUtils.isBlank(policyFollow.getPolicyNo())) {
                throw new BusinessException(ResultCode.PARAM_CHECK_ERROR.getCode(), "保单号不能为空，才能修改为生效状态");
            }
            boolean exists = policyBrokerService.exists(new QueryWrapper<PolicyBroker>().eq("policy_biz_id", policyBizId));
            if (!exists) {
                throw new BusinessException(ResultCode.PARAM_CHECK_ERROR.getCode(), "转介人不能为空，才能修改为生效状态");
            }
        }

        // 获取当前登录用户
        AuthUserDto currentLoginUser = SecurityUtil.getCurrentLoginUser();
        String loginUserId = currentLoginUser.getId().toString();

        policyFollowService.lambdaUpdate()
                .set(PolicyFollow::getEffectiveDate, changePolicyFollowStatusRequest.getEffectiveDate())
                .set(PolicyFollow::getUnderwritingDate, changePolicyFollowStatusRequest.getUnderwritingDate())
                .set(PolicyFollow::getStatus, changePolicyFollowStatusRequest.getStatus())
                .set(PolicyFollow::getNextStatusList, getNextStatus(policyFollowStatusEnum))
                .set(PolicyFollow::getUpdaterId, loginUserId)
                .eq(PolicyFollow::getId, policyFollow.getId())
                .update();

        // 如果是生效状态，同步保单、预计发佣、预计来佣
        if (PolicyFollowStatusEnum.EFFECTIVE.equals(policyFollowStatusEnum)) {
            Policy policy = new Policy();
            BeanUtils.copyProperties(policyFollow, policy, "id");
            policy.setStatus(PolicyStatusEnum.INFORCE.getItemValue());
            // 手动映射不同名的字段
            policy.setPaymentPremium(policyFollow.getInitialPremium());
            policy.setCurrency(policyFollow.getPolicyCurrency());
            policy.setPaymentTerm(policyFollow.getIssueNumber());
            policy.setUnderwritingDate(changePolicyFollowStatusRequest.getUnderwritingDate());
            policy.setEffectiveDate(changePolicyFollowStatusRequest.getEffectiveDate());

            if (ObjectUtils.isEmpty(policy.getInsuranceCompany()) || ObjectUtils.isEmpty(policy.getReconciliationCompanyBizId())) {
                // 获取保单产品信息，填充对账公司相关字段
                PolicyProductInfo productInfo = getPolicyProductInfo(policyFollow.getProductLaunchBizId());
                if (productInfo != null) {
                    policy.setInsuranceCompany(productInfo.getInsuranceCompany());
                    policy.setInsuranceCompanyBizId(productInfo.getInsuranceCompanyBizId());
                    policy.setReconciliationCompany(productInfo.getReconciliationCompany());
                    policy.setReconciliationCompanyBizId(productInfo.getReconciliationCompanyBizId());

                    // 调用对账公司 feignclient，查询对账公司编码
                    String reconciliationCompanyCode = queryReconciliationCompanyByFeign(policy.getReconciliationCompanyBizId());

                    // 如果仍然没有获取到编码，抛异常
                    if (StringUtils.isBlank(reconciliationCompanyCode)) {
                        throw new BusinessException("未能从对账公司服务获取编码，请补充，当前对账公司：" + productInfo.getReconciliationCompany());
                    }
                    policy.setReconciliationCompanyCode(reconciliationCompanyCode);
                }
            }
            // 保存保单
            try {
                policyService.save(policy);
            } catch (DuplicateKeyException e) {
                // 保单号已存在
                throw new BusinessException("保单号 " + policy.getPolicyNo() + " 已存在，请勿重复添加");
            }

            // 更新转介人保单号
            updatePolicyBrokerPolicyNo(policyBizId, policy.getPolicyNo());

            // 根据保单生成预计入账记录
            generateExpectedCommission(policyFollow, policy);
        }

        // 新增新单状态记录
        PolicyFollowRecord policyFollowRecord = new PolicyFollowRecord();
        policyFollowRecord.setId(null);
        policyFollowRecord.setPolicyBizId(policyBizId);
        policyFollowRecord.setTitle(Objects.requireNonNull(policyFollowStatusEnum.getItemLabel()));
        policyFollowRecord.setMessage(changePolicyFollowStatusRequest.getMessage());
        policyFollowRecord.setCreatorId(loginUserId);
        policyFollowRecord.setCreateTime(new Date());
        policyFollowRecordService.save(policyFollowRecord);

        return true;
    }

    /**
     * 调用对账公司 feignclient，查询对账公司编码
     */
    @Override
    public String queryReconciliationCompanyByFeign(String reconciliationCompanyBizId) {
        ApiInsuranceReconciliationCompanyPageRequest reconciliationCompanyPageRequest = new ApiInsuranceReconciliationCompanyPageRequest();
        reconciliationCompanyPageRequest.setPageNo(1);
        reconciliationCompanyPageRequest.setPageSize(999);
        Result iPageResult = apiInsuranceReconciliationCompanyFeignClient.page(reconciliationCompanyPageRequest);

        // 解析响应获取对账公司编码
        if (iPageResult != null && iPageResult.getCode() == 200) {
            try {
                // Feign 返回的泛型会被反序列化为 LinkedHashMap，需要手动提取
                Object data = iPageResult.getData();
                if (data instanceof Map) {
                    Map<String, Object> dataMap = (Map<String, Object>) data;
                    Object recordsObj = dataMap.get("records");
                    if (recordsObj instanceof List) {
                        List<Map<String, Object>> records = (List<Map<String, Object>>) recordsObj;
                        // 遍历分页结果，找到匹配的对账公司
                        for (Map<String, Object> record : records) {
                            String recordBizId = (String) record.get("reconciliationCompanyBizId");
                            if (reconciliationCompanyBizId.equals(recordBizId)) {
                                // 获取对账公司编码
                                return (String) record.get("code");
                            }
                        }
                    }
                }
            } catch (Exception e) {
                log.error("解析对账公司响应失败: {}", e.getMessage(), e);
            }
        }
        return null;
    }

    @Override
    public String getNextStatus(PolicyFollowStatusEnum policyFollowStatusEnum) {
        // 根据当前状态返回可能的下一步状态
        switch (policyFollowStatusEnum) {
            case PENDING_SIGN:
                return PolicyFollowStatusEnum.SIGNED.getItemValue() + ","
                        + PolicyFollowStatusEnum.CANCELLED.getItemValue();
            case SIGNED:
                return PolicyFollowStatusEnum.WAITING_PAYMENT.getItemValue() + ","
                        + PolicyFollowStatusEnum.CANCELLED.getItemValue();
            case WAITING_PAYMENT:
                return PolicyFollowStatusEnum.PREMIUM_RECONCILING.getItemValue() + ","
                        + PolicyFollowStatusEnum.CANCELLED.getItemValue();
            case PREMIUM_RECONCILING:
                return PolicyFollowStatusEnum.PREMIUM_RECONCILED_UNDERWRITING.getItemValue();
            case PREMIUM_RECONCILED_UNDERWRITING:
                return PolicyFollowStatusEnum.EFFECTIVE.getItemValue() + ","
                        + PolicyFollowStatusEnum.DECLINED.getItemValue() + ","
                        + PolicyFollowStatusEnum.DELAYED_UNDERWRITING.getItemValue();
            case DELAYED_UNDERWRITING:
                return PolicyFollowStatusEnum.PREMIUM_RECONCILED_UNDERWRITING.getItemValue() + ","
                        + PolicyFollowStatusEnum.DECLINED.getItemValue() + ","
                        + PolicyFollowStatusEnum.CANCELLED.getItemValue();
            default:
                return "";
        }
    }

    @Override
    public String getCurrencyValue(String currency) {
        if (StringUtils.isBlank(currency)) {
            return null;
        }
        switch (currency) {
            case "美元":
                currency = "USD";
                break;
            case "人民幣":
                currency = "CNY";
                break;
            case "港幣":
                currency = "HKD";
                break;
            case "澳元":
                currency = "AUD";
                break;
            case "加元":
                currency = "CAD";
                break;
            case "欧元":
                currency = "EUR";
                break;
            case "英鎊":
                currency = "GBP";
                break;
            case "新加坡元":
                currency = "SGD";
                break;
            default:
                break;
        }
        return currency;
    }

    @Override
    public PolicyReportData queryPolicyReportData(String policyBizId) {
        // 查询主险信息
        PolicyReportData policyReportData = this.baseMapper.queryPolicyReportData(policyBizId);
        // 处理附加险信息
        List<PolicyAdditional> additionalList= policyAdditionalService.list(new QueryWrapper<PolicyAdditional>().eq("policy_biz_id", policyBizId));
        List<PolicyReportData.AdditionalInsurance> additionalInsurances = new ArrayList<>();
        if (CollUtil.isNotEmpty(additionalList)) {
            for (PolicyAdditional additional : additionalList) {
                PolicyReportData.AdditionalInsurance additionalInsurance = new PolicyReportData.AdditionalInsurance();
                additionalInsurance.setName(additional.getProductLaunchName());
                additionalInsurance.setPaymentTerm(null);
                additionalInsurance.setCurrency(getCurrencyValue(additional.getPolicyCurrency()));
                additionalInsurance.setFirstYearAmount(additional.getEachIssuePremium());
                additionalInsurances.add(additionalInsurance);
            }
        }
        // 处理附加险信息
        policyReportData.setAdditionalInsurances(additionalInsurances);

        return policyReportData;
    }

    /**
     * 根据保单号查询保单跟进信息
     * @param policyNo
     * @return
     */
    @Override
    public PolicyFollow queryOneByPolicyNo(String policyNo) {
        return this.getOne(new LambdaQueryWrapper<PolicyFollow>()
                .eq(PolicyFollow::getPolicyNo,policyNo)
                .last(" limit 1 ")
        );
    }

    @Override
    public Boolean uploadAttachment(AttachmentUploadRequest attachmentUploadRequest) {
        String policyBizId = attachmentUploadRequest.getPolicyBizId();
        if (policyBizId == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR.getCode(), "policyBizId不能为空");
        }
        String fileName = attachmentUploadRequest.getFileName();
        if (fileName == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR.getCode(), "fileName不能为空");
        }
        String fileUrl = attachmentUploadRequest.getFileUrl();
        if (fileUrl == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR.getCode(), "fileUrl不能为空");
        }
        String ossFileBizId = attachmentUploadRequest.getOssFileBizId();
        if (ossFileBizId == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR.getCode(), "ossFileBizId不能为空");
        }

        PolicyFollowFile policyFollowFile = new PolicyFollowFile();
        policyFollowFile.setPolicyBizId(attachmentUploadRequest.getPolicyBizId());
        policyFollowFile.setOssFileBizId(attachmentUploadRequest.getOssFileBizId());
        policyFollowFile.setFileName(attachmentUploadRequest.getFileName());
        policyFollowFile.setFileUrl(attachmentUploadRequest.getFileUrl());

        return policyFollowFileService.save(policyFollowFile);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveInitialPayment(InitialPaymentSaveRequest initialPaymentSaveRequest) {
        // 校验参数
        if (StringUtils.isBlank(initialPaymentSaveRequest.getPolicyBizId())) {
            throw new BusinessException(ResultCode.PARAMS_ERROR.getCode(), "policyBizId不能为空");
        }

        String policyBizId = initialPaymentSaveRequest.getPolicyBizId();
        PolicyFollow policyFollow = getByPolicyBizId(policyBizId);
        if (policyFollow == null) {
            throw new BusinessException(ResultCode.NULL_ERROR.getCode(), "新单跟进记录不存在");
        }

        // 获取当前登录用户
        AuthUserDto currentLoginUser = SecurityUtil.getCurrentLoginUser();
        String loginUserId = currentLoginUser.getId().toString();

        // 更新相关字段
        boolean result = this.lambdaUpdate()
                .eq(PolicyFollow::getPolicyBizId, policyBizId)
                .set(initialPaymentSaveRequest.getInitialPremium() != null, PolicyFollow::getInitialPremium, initialPaymentSaveRequest.getInitialPremium())
                .set(initialPaymentSaveRequest.getPolicyLevy() != null, PolicyFollow::getPolicyLevy, initialPaymentSaveRequest.getPolicyLevy())
                .set(initialPaymentSaveRequest.getInitialPaymentMethod() != null, PolicyFollow::getInitialPaymentMethod, initialPaymentSaveRequest.getInitialPaymentMethod())
                .set(initialPaymentSaveRequest.getInitialPremiumPaid() != null, PolicyFollow::getInitialPremiumPaid, initialPaymentSaveRequest.getInitialPremiumPaid())
                .set(initialPaymentSaveRequest.getInitialPremiumDue() != null, PolicyFollow::getInitialPremiumDue, initialPaymentSaveRequest.getInitialPremiumDue())
                .set(initialPaymentSaveRequest.getInitialPremiumTotal() != null, PolicyFollow::getInitialPremiumTotal, initialPaymentSaveRequest.getInitialPremiumTotal())
                .set(initialPaymentSaveRequest.getLatestPaymentDate() != null, PolicyFollow::getLatestPaymentDate, initialPaymentSaveRequest.getLatestPaymentDate())
                .set(initialPaymentSaveRequest.getInitialPremiumDiscount() != null, PolicyFollow::getInitialPremiumDiscount, initialPaymentSaveRequest.getInitialPremiumDiscount())
                .set(initialPaymentSaveRequest.getInitialPaymentStatus() != null, PolicyFollow::getInitialPaymentStatus, initialPaymentSaveRequest.getInitialPaymentStatus())
                .set(PolicyFollow::getUpdaterId, loginUserId)
                .set(PolicyFollow::getUpdateTime, new Date())
                .update();

        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveMailingInfo(MailingInfoSaveRequest mailingInfoSaveRequest) {
        // 校验参数
        if (StringUtils.isBlank(mailingInfoSaveRequest.getPolicyBizId())) {
            throw new BusinessException(ResultCode.PARAMS_ERROR.getCode(), "policyBizId不能为空");
        }

        String policyBizId = mailingInfoSaveRequest.getPolicyBizId();
        PolicyFollow policyFollow = getByPolicyBizId(policyBizId);
        if (policyFollow == null) {
            throw new BusinessException(ResultCode.NULL_ERROR.getCode(), "新单跟进记录不存在");
        }

        // 获取当前登录用户
        AuthUserDto currentLoginUser = SecurityUtil.getCurrentLoginUser();
        String loginUserId = currentLoginUser.getId().toString();

        // 更新邮寄信息相关字段
        boolean result = this.lambdaUpdate()
                .eq(PolicyFollow::getPolicyBizId, policyBizId)
                .set(mailingInfoSaveRequest.getMailingMethod() != null, PolicyFollow::getMailingMethod, mailingInfoSaveRequest.getMailingMethod())
                .set(mailingInfoSaveRequest.getDeliveryNo() != null, PolicyFollow::getDeliveryNo, mailingInfoSaveRequest.getDeliveryNo())
                .set(mailingInfoSaveRequest.getBrokerSignDate() != null, PolicyFollow::getBrokerSignDate, mailingInfoSaveRequest.getBrokerSignDate())
                .set(mailingInfoSaveRequest.getCustomerSignDate() != null, PolicyFollow::getCustomerSignDate, mailingInfoSaveRequest.getCustomerSignDate())
                .set(PolicyFollow::getUpdaterId, loginUserId)
                .set(PolicyFollow::getUpdateTime, new Date())
                .update();

        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchSaveBrokers(BrokerBatchSaveRequest brokerBatchSaveRequest) {
        // 校验参数
        if (StringUtils.isBlank(brokerBatchSaveRequest.getPolicyBizId())) {
            throw new BusinessException(ResultCode.PARAMS_ERROR.getCode(), "policyBizId不能为空");
        }

        String policyBizId = brokerBatchSaveRequest.getPolicyBizId();
        PolicyFollow policyFollow = getByPolicyBizId(policyBizId);
        if (policyFollow == null) {
            throw new BusinessException(ResultCode.NULL_ERROR.getCode(), "新单跟进记录不存在");
        }

        if (CollectionUtils.isEmpty(brokerBatchSaveRequest.getBrokerList())) {
            throw new BusinessException(ResultCode.PARAMS_ERROR.getCode(), "介绍人列表不能为空");
        }

        // 获取当前登录用户
        AuthUserDto currentLoginUser = SecurityUtil.getCurrentLoginUser();
        String loginUserId = currentLoginUser.getId().toString();

        // 删除该 policyBizId 下的所有现有介绍人
        policyBrokerService.lambdaUpdate()
                .eq(PolicyBroker::getPolicyBizId, policyBizId)
                .remove();

        // 批量插入新的介绍人记录
        List<PolicyBroker> brokerList = new ArrayList<>();
        for (BrokerBatchSaveRequest.BrokerInfo brokerInfo : brokerBatchSaveRequest.getBrokerList()) {
            PolicyBroker policyBroker = new PolicyBroker();
            policyBroker.setPolicyBizId(policyBizId);
            policyBroker.setPolicyNo(policyFollow.getPolicyNo());
            policyBroker.setBrokerName(brokerInfo.getBrokerName());
            policyBroker.setBrokerBizId(brokerInfo.getBrokerBizId());
            policyBroker.setGender(brokerInfo.getGender());
            policyBroker.setInternalCode(brokerInfo.getInternalCode());
            policyBroker.setTeam(brokerInfo.getTeam());
            policyBroker.setTeamBizId(brokerInfo.getTeamBizId());
            policyBroker.setBrokerRatio(brokerInfo.getBrokerRatio());
            policyBroker.setRemark(brokerInfo.getRemark());
            policyBroker.setIsDeleted(0);
            policyBroker.setCreatorId(loginUserId);
            policyBroker.setCreateTime(new Date());
            policyBroker.setUpdaterId(loginUserId);
            policyBroker.setUpdateTime(new Date());
            brokerList.add(policyBroker);
        }

        return policyBrokerService.saveBatch(brokerList);
    }

    @Override
    public Page<PolicyNumberResponseVO> queryPolicyNumbers(PolicyNosQueryRequest policyNosQueryRequest) {
        String policyNo = policyNosQueryRequest.getPolicyNo();

        // 创建分页对象
        Page<PolicyFollow> page = new Page<>(policyNosQueryRequest.getPageNo(), policyNosQueryRequest.getPageSize());

        // 构建查询条件
        QueryWrapper<PolicyFollow> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("policy_no", "insurance_company", "insurance_company_biz_id", "insured", "insured_biz_id");
        queryWrapper.like(ObjectUtils.isNotEmpty(policyNo), "policy_no", policyNo);
        queryWrapper.isNotNull("policy_no");

        // 执行分页查询
        Page<PolicyFollow> policyFollowPage = policyFollowService.page(page, queryWrapper);

        // 转换结果
        Page<PolicyNumberResponseVO> resultPage = new Page<>(policyFollowPage.getCurrent(), policyFollowPage.getSize(), policyFollowPage.getTotal());
        List<PolicyNumberResponseVO> voList = policyFollowPage.getRecords().stream()
                .map(this::convertToPolicyNumberResponseVO)
                .collect(Collectors.toList());
        resultPage.setRecords(voList);

        return resultPage;
    }

    @Override
    public List<PolicyFollow> queryList(List<String> policyNoList) {
        List<PolicyFollow> list = baseMapper.selectList(new LambdaQueryWrapper<PolicyFollow>()
                .in(!CollectionUtils.isEmpty(policyNoList), PolicyFollow::getPolicyNo, policyNoList)
        );
        return list;
    }

    /**
     * 转换为保单号查询响应视图
     *
     * @param policyFollow 新单跟进实体
     * @return 保单号查询响应视图
     */
    private PolicyNumberResponseVO convertToPolicyNumberResponseVO(PolicyFollow policyFollow) {
        if (policyFollow == null) {
            return null;
        }
        PolicyNumberResponseVO vo = new PolicyNumberResponseVO();
        vo.setPolicyNo(policyFollow.getPolicyNo());
        vo.setInsuranceCompany(policyFollow.getInsuranceCompany());
        vo.setInsuranceCompanyBizId(policyFollow.getInsuranceCompanyBizId());
        vo.setInsured(policyFollow.getInsured());
        vo.setInsuredBizId(policyFollow.getInsuredBizId());
        return vo;
    }

    /**
     * 根据保单生成预计入账记录
     *
     * @param policyFollow 保单跟进信息
     */
    private void generateExpectedCommission(PolicyFollow policyFollow, Policy policy) {
        if (policyFollow == null) {
            return;
        }

        // 获取必要的参数
        String policyNo = policyFollow.getPolicyNo();
        String productLaunchBizId = policyFollow.getProductLaunchBizId();
        String insuranceCompanyBizId = policyFollow.getInsuranceCompanyBizId();
        String reconciliationCompany = policy.getReconciliationCompany();
        String reconciliationCompanyCode = policy.getReconciliationCompanyCode();
        String reconciliationCompanyBizId = policy.getReconciliationCompanyBizId();

        // 调用预计入账服务生成记录
        commissionExpectedService.getExpectedCommissionByProductlaunchId(
                policy,
                productLaunchBizId,
                insuranceCompanyBizId,
                reconciliationCompany,
                reconciliationCompanyCode,
                reconciliationCompanyBizId
        );
    }

    /**
     * 获取单个保单产品信息
     *
     * @param productLaunchBizId 产品上架业务ID
     * @return 产品信息，如果未找到则返回 null
     */
    private PolicyProductInfo getPolicyProductInfo(String productLaunchBizId) {
        if (StringUtils.isBlank(productLaunchBizId)) {
            log.warn("产品上架业务ID为空，无法获取产品信息");
            return null;
        }

        try {
            // 调用 PolicyService 的批量查询方法，传入单个 ID
            Map<String, PolicyProductInfo> productInfoMap = policyService.getPolicyProductInfoMap(
                    Collections.singletonList(productLaunchBizId)
            );

            if (productInfoMap == null || productInfoMap.isEmpty()) {
                log.warn("未找到产品信息，productLaunchBizId: {}", productLaunchBizId);
                return null;
            }

            PolicyProductInfo productInfo = productInfoMap.get(productLaunchBizId);
            if (productInfo == null) {
                log.warn("产品信息为空，productLaunchBizId: {}", productLaunchBizId);
                return null;
            }
            if (ObjectUtils.isEmpty(productInfo.getReconciliationCompanyBizId())) {
                throw new BusinessException("产品上架信息未配置对账公司");
            }

            log.info("成功获取产品信息: productLaunchBizId={}, reconciliationCompanyBizId={}, reconciliationCompany={}",
                    productLaunchBizId,
                    productInfo.getReconciliationCompanyBizId(),
                    productInfo.getReconciliationCompany()
                    );

            return productInfo;
        } catch (Exception e) {
            log.error("获取产品信息失败，productLaunchBizId: {}, error: {}", productLaunchBizId, e.getMessage(), e);
            return null;
        }
    }
}

