package com.ruoyi.info.collection.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.info.collection.domain.CcdiCustEnterpriseRelation;
import com.ruoyi.info.collection.domain.dto.CcdiCustEnterpriseRelationAddDTO;
import com.ruoyi.info.collection.domain.dto.CcdiCustEnterpriseRelationEditDTO;
import com.ruoyi.info.collection.domain.dto.CcdiCustEnterpriseRelationQueryDTO;
import com.ruoyi.info.collection.domain.excel.CcdiCustEnterpriseRelationExcel;
import com.ruoyi.info.collection.domain.vo.CcdiCustEnterpriseRelationVO;
import com.ruoyi.info.collection.enums.DataSource;
import com.ruoyi.info.collection.enums.EnterpriseSource;
import com.ruoyi.info.collection.mapper.CcdiCustEnterpriseRelationMapper;
import com.ruoyi.info.collection.service.ICcdiCustEnterpriseRelationImportService;
import com.ruoyi.info.collection.service.ICcdiCustEnterpriseRelationService;
import com.ruoyi.info.collection.service.support.EnterpriseAutoFillService;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 信贷客户实体关联信息 服务层处理
 *
 * @author ruoyi
 * @date 2026-02-12
 */
@Service
public class CcdiCustEnterpriseRelationServiceImpl implements ICcdiCustEnterpriseRelationService {

    @Resource
    private CcdiCustEnterpriseRelationMapper relationMapper;

    @Resource
    private ICcdiCustEnterpriseRelationImportService relationImportService;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    private EnterpriseAutoFillService enterpriseAutoFillService;

    /**
     * 查询信贷客户实体关联列表
     *
     * @param queryDTO 查询条件
     * @return 信贷客户实体关联VO集合
     */
    @Override
    public java.util.List<CcdiCustEnterpriseRelationVO> selectRelationList(CcdiCustEnterpriseRelationQueryDTO queryDTO) {
        Page<CcdiCustEnterpriseRelationVO> page = new Page<>(1, Integer.MAX_VALUE);
        Page<CcdiCustEnterpriseRelationVO> resultPage = relationMapper.selectRelationPage(page, queryDTO);
        return resultPage.getRecords();
    }

    /**
     * 分页查询信贷客户实体关联列表
     *
     * @param page     分页对象
     * @param queryDTO 查询条件
     * @return 信贷客户实体关联VO分页结果
     */
    @Override
    public Page<CcdiCustEnterpriseRelationVO> selectRelationPage(Page<CcdiCustEnterpriseRelationVO> page, CcdiCustEnterpriseRelationQueryDTO queryDTO) {
        return relationMapper.selectRelationPage(page, queryDTO);
    }

    /**
     * 查询信贷客户实体关联列表（用于导出）
     *
     * @param queryDTO 查询条件
     * @return 信贷客户实体关联Excel实体集合
     */
    @Override
    public java.util.List<CcdiCustEnterpriseRelationExcel> selectRelationListForExport(CcdiCustEnterpriseRelationQueryDTO queryDTO) {
        Page<CcdiCustEnterpriseRelationVO> page = new Page<>(1, Integer.MAX_VALUE);
        Page<CcdiCustEnterpriseRelationVO> resultPage = relationMapper.selectRelationPage(page, queryDTO);

        return resultPage.getRecords().stream().map(vo -> {
            CcdiCustEnterpriseRelationExcel excel = new CcdiCustEnterpriseRelationExcel();
            BeanUtils.copyProperties(vo, excel);
            return excel;
        }).collect(Collectors.toList());
    }

    /**
     * 查询信贷客户实体关联详情
     *
     * @param id 主键ID
     * @return 信贷客户实体关联VO
     */
    @Override
    public CcdiCustEnterpriseRelationVO selectRelationById(Long id) {
        return relationMapper.selectRelationById(id);
    }

    /**
     * 新增信贷客户实体关联
     *
     * @param addDTO 新增DTO
     * @return 结果
     */
    @Override
    @Transactional
    public int insertRelation(CcdiCustEnterpriseRelationAddDTO addDTO) {
        // 检查身份证号+统一社会信用代码唯一性
        if (relationMapper.existsByPersonIdAndSocialCreditCode(addDTO.getPersonId(), addDTO.getSocialCreditCode())) {
            throw new RuntimeException("该身份证号和统一社会信用代码组合已存在");
        }

        CcdiCustEnterpriseRelation relation = new CcdiCustEnterpriseRelation();
        BeanUtils.copyProperties(addDTO, relation);

        // 设置默认值
        // 新增时强制设置状态为有效
        relation.setStatus(1);

        // 信贷客户实体关联的身份标识默认值
        if (relation.getIsEmployee() == null) {
            relation.setIsEmployee(0);
        }
        if (relation.getIsEmpFamily() == null) {
            relation.setIsEmpFamily(0);
        }
        if (relation.getIsCustomer() == null) {
            relation.setIsCustomer(0);
        }
        if (relation.getIsCustFamily() == null) {
            relation.setIsCustFamily(1);  // 信贷客户关联人标识为1
        }
        if (StringUtils.isEmpty(relation.getDataSource())) {
            relation.setDataSource("MANUAL");
        }

        enterpriseAutoFillService.ensureExists(new EnterpriseAutoFillService.EnterpriseFillItem(
                addDTO.getSocialCreditCode(),
                addDTO.getEnterpriseName(),
                EnterpriseSource.CREDIT_CUSTOMER.getCode(),
                DataSource.MANUAL.getCode(),
                SecurityUtils.getUsername()
        ));

        int result = relationMapper.insert(relation);

        return result;
    }

    /**
     * 修改信贷客户实体关联
     *
     * @param editDTO 编辑DTO
     * @return 结果
     */
    @Override
    @Transactional
    public int updateRelation(CcdiCustEnterpriseRelationEditDTO editDTO) {
        // 使用LambdaUpdateWrapper只更新非null字段，保护系统字段不被覆盖
        LambdaUpdateWrapper<CcdiCustEnterpriseRelation> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(CcdiCustEnterpriseRelation::getId, editDTO.getId());

        // 只更新前端可编辑的字段
        updateWrapper.set(editDTO.getRelationPersonPost() != null, CcdiCustEnterpriseRelation::getRelationPersonPost, editDTO.getRelationPersonPost());
        updateWrapper.set(editDTO.getEnterpriseName() != null, CcdiCustEnterpriseRelation::getEnterpriseName, editDTO.getEnterpriseName());
        updateWrapper.set(editDTO.getStatus() != null, CcdiCustEnterpriseRelation::getStatus, editDTO.getStatus());
        updateWrapper.set(editDTO.getRemark() != null, CcdiCustEnterpriseRelation::getRemark, editDTO.getRemark());

        // 注意：以下字段不可修改
        // - personId（身份证号，业务主键）
        // - socialCreditCode（统一社会信用代码，业务主键）
        // - dataSource（数据来源，系统字段）
        // - isEmployee（是否为员工，系统字段）
        // - isEmpFamily（是否为员工家属，系统字段）
        // - isCustomer（是否为客户，系统字段）
        // - isCustFamily（是否为客户家属，系统字段）

        int result = relationMapper.update(null, updateWrapper);

        return result;
    }

    /**
     * 批量删除信贷客户实体关联
     *
     * @param ids 需要删除的主键ID
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteRelationByIds(Long[] ids) {
        return relationMapper.deleteBatchIds(java.util.List.of(ids));
    }

    /**
     * 导入信贷客户实体关联数据（异步）
     *
     * @param excelList Excel实体列表
     * @return 任务ID
     */
    @Override
    @Transactional
    public String importRelation(java.util.List<CcdiCustEnterpriseRelationExcel> excelList) {
        if (StringUtils.isNull(excelList) || excelList.isEmpty()) {
            throw new RuntimeException("至少需要一条数据");
        }

        // 生成任务ID
        String taskId = UUID.randomUUID().toString();
        long startTime = System.currentTimeMillis();

        // 获取当前用户名
        String userName = SecurityUtils.getUsername();

        // 初始化Redis状态
        String statusKey = "import:custEnterpriseRelation:" + taskId;
        Map<String, Object> statusData = new HashMap<>();
        statusData.put("taskId", taskId);
        statusData.put("status", "PROCESSING");
        statusData.put("totalCount", excelList.size());
        statusData.put("successCount", 0);
        statusData.put("failureCount", 0);
        statusData.put("progress", 0);
        statusData.put("startTime", startTime);
        statusData.put("message", "正在处理...");

        redisTemplate.opsForHash().putAll(statusKey, statusData);
        redisTemplate.expire(statusKey, 7, TimeUnit.DAYS);

        // 调用异步导入服务
        relationImportService.importRelationAsync(excelList, taskId, userName);

        return taskId;
    }
}
