package com.yd.csf.service.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
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.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yd.common.enums.ResultCode;
import com.yd.common.exception.BusinessException;
import com.yd.common.result.Result;
import com.yd.csf.feign.dto.appointment.ApiProductPlanAdditionalInfoDto;
import com.yd.csf.feign.dto.appointment.ApiProductPlanMainInfoDto;
import com.yd.csf.service.dto.*;
import com.yd.csf.service.model.Policy;
import com.yd.csf.service.model.PolicyAdditional;
import com.yd.csf.service.model.PolicyFollow;
import com.yd.csf.service.service.PolicyAdditionalService;
import com.yd.csf.service.service.PolicyFollowService;
import com.yd.csf.service.service.PolicyService;
import com.yd.csf.service.dao.PolicyMapper;
import com.yd.csf.service.vo.PolicyVO;
import com.yd.product.feign.client.relprojectproductlaunch.ApiRelProjectProductLaunchFeignClient;
import com.yd.product.feign.request.relprojectproductlaunch.ApiRelProjectProductLaunchPageRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.ZoneId;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author Zhang Jianan
 * @description 针对表【policy(保单表)】的数据库操作Service实现
 * @createDate 2025-09-18 15:07:25
 */
@Service
@Slf4j
public class PolicyServiceImpl extends ServiceImpl<PolicyMapper, Policy>
        implements PolicyService {

    @Resource
    private PolicyAdditionalService policyAdditionalService;
    @Resource
    private PolicyFollowService policyFollowService;
    @Resource
    private ApiRelProjectProductLaunchFeignClient apiRelProjectProductLaunchFeignClient;

    @Override
    public QueryWrapper<Policy> getQueryWrapper(PolicyQueryRequest policyQueryRequest) {
        QueryWrapper<Policy> queryWrapper = new QueryWrapper<>();
        if (policyQueryRequest == null) {
            return queryWrapper;
        }
        String status = policyQueryRequest.getStatus();
        String policyNo = policyQueryRequest.getPolicyNo();
        String customerName = policyQueryRequest.getCustomerName();
        String customerBizId = policyQueryRequest.getCustomerBizId();
        String insurer = policyQueryRequest.getInsurer();
        String productName = policyQueryRequest.getProductName();
        String issueDateStart = policyQueryRequest.getIssueDateStart();
        String issueDateEnd = policyQueryRequest.getIssueDateEnd();

        queryWrapper.eq(StringUtils.isNotBlank(status), "status", status);
        queryWrapper.eq(StringUtils.isNotBlank(policyNo), "policy_no", policyNo);
        queryWrapper.eq(StringUtils.isNotBlank(customerName), "customer_name", customerName);
        queryWrapper.eq(StringUtils.isNotBlank(customerBizId), "customer_biz_id", customerBizId);
        queryWrapper.eq(StringUtils.isNotBlank(insurer), "insurer", insurer);
        queryWrapper.eq(StringUtils.isNotBlank(productName), "product_name", productName);
        queryWrapper.ge(StringUtils.isNotBlank(issueDateStart), "issue_date", issueDateStart);
        queryWrapper.le(StringUtils.isNotBlank(issueDateEnd), "issue_date", issueDateEnd);

        // 默认排序
        queryWrapper.orderByDesc("id");

        return queryWrapper;
    }

    @Override
    public Page<PolicyVO> getPolicyVOPage(Page<Policy> policyPage) {
        List<Policy> policyList = policyPage.getRecords();
        Page<PolicyVO> policyVOPage = new Page<>(policyPage.getCurrent(), policyPage.getSize(), policyPage.getTotal());
        if (CollUtil.isEmpty(policyList)) {
            return policyVOPage;
        }

        // 填充信息
        List<PolicyVO> policyVOList = policyList.stream().map(policy -> {
            PolicyVO policyVO = PolicyVO.objToVo(policy);
            return policyVO;
        }).collect(Collectors.toList());
        policyVOPage.setRecords(policyVOList);
        return policyVOPage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updatePolicy(PolicyUpdateRequest policyUpdateRequest) {
        ApiProductPlanMainInfoDto dto = policyUpdateRequest.getApiProductPlanMainInfoDto();
        if (dto == null) {
            throw new BusinessException("产品计划对象不能为空");
        }
        String policyBizId = policyUpdateRequest.getPolicyBizId();
        if (StringUtils.isBlank(policyBizId)) {
            throw new BusinessException(ResultCode.PARAMS_ERROR.getCode(), "policyBizId不能为空");
        }

        Policy policy = this.getOne(new QueryWrapper<Policy>().eq("policy_biz_id", policyBizId));
        if (policy == null) {
            throw new BusinessException(ResultCode.NULL_ERROR.getCode(), "保单不存在");
        }

        // 手动映射字段，处理类型转换
        Date now = new Date();

        // 保单基本信息
        policy.setPolicyBizId(policyBizId);
        policy.setProductLaunchBizId(dto.getProductLaunchBizId());
        policy.setProductName(dto.getProductLaunchMainName());
        policy.setInsuranceCompany(dto.getCompanyName());
        policy.setInsuranceCompanyBizId(dto.getCompanyId());
        policy.setReconciliationCompany(dto.getReconciliationCompanyName());
        policy.setReconciliationCompanyBizId(dto.getReconciliationCompanyId());
        policy.setCurrency(dto.getPolicyCurrency());
        policy.setProductCate(dto.getInsuranceTypeId());
        policy.setPaymentTerm(dto.getIssueNumber());
        // 保障年期
        policy.setGuaranteePeriod(dto.getGuaranteePeriod());
        // 保额
        policy.setSumInsured(parseBigDecimal(dto.getSumInsured()));
        // 期交保费
        BigDecimal eachIssuePremium = parseBigDecimal(dto.getEachIssuePremium());
        if (eachIssuePremium == null) {
            throw new BusinessException("每期保费不能为空");
        }
        policy.setPaymentPremium(eachIssuePremium);
        // 总保费计算
        policy.setTotalPaymentPremium(calculateTotalPaymentPremium(dto));
        // 保单征费
        policy.setPolicyLevy(parseString(dto.getPolicyLevy()));
        // 是否预缴
        policy.setIsPrepaid(parseInteger(dto.getIsPrepay()));
        // 预缴年期
        policy.setPrepaidTerm(parseInteger(dto.getPrepaymentPeriod()));
        // 是否回溯
        policy.setIsBacktrack(parseInteger(dto.getIsTraceable()));
        // 首期付款方式
        policy.setInitialPaymentMethod(dto.getInitialPaymentMethod());
        // 续期付款方式
        policy.setRenewalPaymentMethod(dto.getRenewalPaymentMethod());
        // 红利分配方式
        policy.setDividendDistributionMethod(dto.getDividendDistributionMethod());
        policy.setUpdateTime(now);
        this.updateById(policy);

        // 更新 PolicyFollow
        PolicyFollow policyFollow = policyFollowService.queryOneByPolicyBizId(policyBizId);
        if (policyFollow == null) {
            throw new BusinessException("新单跟进信息不存在");
        }

        //PolicyFollow 字段
        policyFollow.setProductLaunchBizId(dto.getProductLaunchBizId());
        policyFollow.setProductName(dto.getProductLaunchMainName());
        policyFollow.setInsuranceCompany(dto.getCompanyName());
        policyFollow.setInsuranceCompanyBizId(dto.getCompanyId());
        policyFollow.setReconciliationCompany(dto.getReconciliationCompanyName());
        policyFollow.setReconciliationCompanyBizId(dto.getReconciliationCompanyId());
        policyFollow.setReconciliationCompanyCode(null);
        policyFollow.setProductCate(dto.getInsuranceTypeName());
        policyFollow.setCategoryCode(dto.getInsuranceTypeCode());
        policyFollow.setInsuranceCategoryBizId(dto.getInsuranceTypeId());
        policyFollow.setIssueNumber(dto.getIssueNumber());
        policyFollow.setGuaranteePeriod(parseInteger(dto.getGuaranteePeriod()));
        policyFollow.setSumInsured(parseBigDecimal(dto.getSumInsured()));
        policyFollow.setPaymentFrequency(dto.getPaymentFrequency());
        policyFollow.setEachIssuePremium(eachIssuePremium);
        policyFollow.setIsPrepay(parseInteger(dto.getIsPrepay()));
        policyFollow.setIsTraceable(parseInteger(dto.getIsTraceable()));
        policyFollow.setPrepaidTerm(parseInteger(dto.getPrepaymentPeriod()));
        policyFollow.setPolicyCurrency(dto.getPolicyCurrency());
        policyFollow.setInitialPaymentMethod(dto.getInitialPaymentMethod());
        policyFollow.setRenewalPaymentMethod(dto.getRenewalPaymentMethod());
        policyFollow.setDividendDistributionMethod(dto.getDividendDistributionMethod());
        policyFollow.setPolicyLevy(parseString(dto.getPolicyLevy()));

        // 回溯日期处理
        if (dto.getBacktrackDate() != null) {
            policyFollow.setRetroactiveDate(Date.from(dto.getBacktrackDate().atZone(ZoneId.systemDefault()).toInstant()));
        } else {
            policyFollow.setRetroactiveDate(null);
        }

        policyFollow.setUpdateTime(now);
        policyFollowService.updateById(policyFollow);

        return true;
    }

    // 类型转换辅助方法
    private BigDecimal parseBigDecimal(Object obj) {
        if (obj == null) return null;
        if (obj instanceof BigDecimal) return (BigDecimal) obj;
        if (obj instanceof String) {
            String str = ((String) obj).trim();
            if (str.isEmpty()) return null;
            try {
                return new BigDecimal(str);
            } catch (NumberFormatException e) {
                log.warn("解析 BigDecimal 失败: {}", str);
                return null;
            }
        }
        if (obj instanceof Number) {
            return BigDecimal.valueOf(((Number) obj).doubleValue());
        }
        return null;
    }

    private Integer parseInteger(Object obj) {
        if (obj == null) return null;
        if (obj instanceof Integer) return (Integer) obj;
        if (obj instanceof String) {
            String str = ((String) obj).trim();
            if (str.isEmpty()) return null;
            try {
                return Integer.valueOf(str);
            } catch (NumberFormatException e) {
                log.warn("解析 Integer 失败: {}", str);
                return null;
            }
        }
        if (obj instanceof Number) {
            return ((Number) obj).intValue();
        }
        return null;
    }

    private String parseString(Object obj) {
        if (obj == null) return null;
        if (obj instanceof String) {
            String str = ((String) obj).trim();
            return str.isEmpty() ? null : str;
        }
        return obj.toString();
    }

    private BigDecimal calculateTotalPaymentPremium(ApiProductPlanMainInfoDto dto) {
        // 校验每期保费（必填）
        BigDecimal eachIssuePremium = dto.getEachIssuePremium();
        if (eachIssuePremium == null) {
            throw new BusinessException("每期保费不能为空");
        }

        String issueNumberStr = dto.getIssueNumber();
        BigDecimal issueNumber;

        // 供款期数为空时，默认按 1 期处理
        if (StringUtils.isBlank(issueNumberStr)) {
            issueNumber = new BigDecimal("1");
        } else {
            // 安全转换为 BigDecimal
            try {
                issueNumber = new BigDecimal(issueNumberStr.trim());
            } catch (NumberFormatException e) {
                throw new BusinessException("供款期数格式不正确，请填写数字");
            }
            // 业务逻辑校验：期数必须为正整数
            if (issueNumber.compareTo(BigDecimal.ZERO) <= 0) {
                throw new BusinessException("供款期数必须大于0");
            }
            // 检查是否为整数（去除小数部分后与原值比较）
            if (issueNumber.stripTrailingZeros().scale() > 0) {
                throw new BusinessException("供款期数必须为整数");
            }
        }

        // 计算总保费并保留4位小数
        return eachIssuePremium.multiply(issueNumber)
                .setScale(4, RoundingMode.HALF_UP);
    }


    /**
     * 查询列表
     *
     * @param dto
     * @return
     */
    @Override
    public List<Policy> queryList(QueryPolicyDto dto) {
        List<Policy> list = baseMapper.selectList(new LambdaQueryWrapper<Policy>()
                .in(!CollectionUtils.isEmpty(dto.getPolicyNoList()), Policy::getPolicyNo, dto.getPolicyNoList())
        );
        return list;
    }

    /**
     * 根据保单号查询单个对象
     *
     * @param policyNo
     * @return
     */
    @Override
    public Policy queryOne(String policyNo) {
        return this.getOne(new LambdaQueryWrapper<Policy>().eq(Policy::getPolicyNo, policyNo).last(" limit 1 "));
    }

    @Override
    public List<QueryPolicyAndBrokerDto> queryPolicyBrokerList(String policyNo) {
        return baseMapper.queryPolicyBrokerList(policyNo);
    }

    @Override
    public List<PolicyProductInfo> getPolicyProductInfo(List<String> productLaunchBizIdList) {
        ApiRelProjectProductLaunchPageRequest pageRequest = new ApiRelProjectProductLaunchPageRequest();
        pageRequest.setProductLaunchBizIdList(productLaunchBizIdList);
        pageRequest.setPageNo(1);
        pageRequest.setPageSize(1000);

        log.info("查询保单产品信息请求参数: {}", JSONUtil.toJsonStr(pageRequest));

        // 修改为使用Result<Object>来接收
        Result result = apiRelProjectProductLaunchFeignClient.page(pageRequest);
        if (result == null || ObjectUtils.isEmpty(result.getData())) {
            return CollUtil.newArrayList();
        }
        try {
            // 直接使用Map来处理数据，避免复杂的类型转换
            Object data = result.getData();
            List<PolicyProductInfo> policyProductInfoList = new ArrayList<>();

            // 将数据转换为JSONObject进行解析
            JSONObject jsonObject = JSONUtil.parseObj(data);

            // 获取records数组
            JSONArray recordsArray = jsonObject.getJSONArray("records");
            if (recordsArray != null) {
                for (int i = 0; i < recordsArray.size(); i++) {
                    JSONObject record = recordsArray.getJSONObject(i);

                    PolicyProductInfo productInfo = new PolicyProductInfo();
                    productInfo.setProductLaunchBizId(record.getStr("productLaunchBizId"));
                    productInfo.setProductName(record.getStr("productName"));
                    productInfo.setTitle(record.getStr("title"));
                    productInfo.setShortTitle(record.getStr("shortTitle"));
                    productInfo.setStatus(record.getStr("status"));

                    // 解析自定义属性
                    JSONArray attributeSettingArray = record.getJSONArray("apiAttributeSettingDtoList");
                    if (attributeSettingArray != null) {
                        getInfoFromJsonArray(attributeSettingArray, productInfo);
                    }

                    policyProductInfoList.add(productInfo);
                }
            }

            log.info("解析后的保单产品信息: {}", JSONUtil.toJsonStr(policyProductInfoList));
            return policyProductInfoList;
        } catch (Exception e) {
            log.error("解析Feign返回数据失败: {}", e.getMessage(), e);
            return CollUtil.newArrayList();
        }
    }

    @Override
    public Map<String, PolicyProductInfo> getPolicyProductInfoMap(Collection<String> productLaunchBizIdList) {
        // 校验参数
        if (CollectionUtils.isEmpty(productLaunchBizIdList)) {
            return Collections.emptyMap();
        }

        List<PolicyProductInfo> policyProductInfoList = getPolicyProductInfo(new ArrayList<>(productLaunchBizIdList));

        return policyProductInfoList.stream()
                .collect(Collectors.toMap(PolicyProductInfo::getProductLaunchBizId, Function.identity(), (oldValue, newValue) -> newValue));
    }

    /**
     * 从JSON数组中解析自定义属性
     */
    private void getInfoFromJsonArray(JSONArray attributeSettingArray, PolicyProductInfo productInfo) {
        if (attributeSettingArray == null || attributeSettingArray.isEmpty()) {
            return;
        }

        for (int i = 0; i < attributeSettingArray.size(); i++) {
            JSONObject attribute = attributeSettingArray.getJSONObject(i);
            String name = attribute.getStr("name");
            String value = attribute.getStr("value");

            // 根据属性名称设置对应的字段
            switch (name) {
                case "保险公司":
                    productInfo.setInsuranceCompany(value);
                    productInfo.setInsuranceCompanyBizId(attribute.getStr("fieldValueBizId"));
                    break;
                case "对账公司":
                    productInfo.setReconciliationCompany(value);
                    productInfo.setReconciliationCompanyBizId(attribute.getStr("fieldValueBizId"));
                    // 尝试获取对账公司编码（如果 API 响应中有 fieldValueCode 字段）
                    String reconciliationCompanyCode = attribute.getStr("fieldValueCode");
                    if (StringUtils.isBlank(reconciliationCompanyCode)) {
                        // 如果没有 fieldValueCode，尝试从其他字段获取
                        reconciliationCompanyCode = attribute.getStr("code");
                    }
                    productInfo.setReconciliationCompanyCode(reconciliationCompanyCode);
                    break;
                case "产品计划类型":
                    productInfo.setProductPlanType(value);
                    break;
                case "是否区分吸烟":
                    productInfo.setIsSmokingDistinguish(value);
                    break;
                default:
                    // 其他自定义属性
                    break;
            }
        }
    }
}





