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

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.info.collection.domain.CcdiAssetInfo;
import com.ruoyi.info.collection.domain.CcdiStaffFmyRelation;
import com.ruoyi.info.collection.domain.dto.CcdiStaffFmyRelationAddDTO;
import com.ruoyi.info.collection.domain.dto.CcdiStaffFmyRelationEditDTO;
import com.ruoyi.info.collection.domain.dto.CcdiStaffFmyRelationQueryDTO;
import com.ruoyi.info.collection.domain.excel.CcdiAssetInfoExcel;
import com.ruoyi.info.collection.domain.excel.CcdiStaffFmyRelationExcel;
import com.ruoyi.info.collection.domain.vo.CcdiAssetInfoVO;
import com.ruoyi.info.collection.domain.vo.CcdiStaffFmyRelationVO;
import com.ruoyi.info.collection.domain.vo.StaffFmyRelationImportSubmitResultVO;
import com.ruoyi.info.collection.mapper.CcdiStaffEnterpriseRelationMapper;
import com.ruoyi.info.collection.mapper.CcdiStaffFmyRelationMapper;
import com.ruoyi.info.collection.service.ICcdiAssetInfoImportService;
import com.ruoyi.info.collection.service.ICcdiAssetInfoService;
import com.ruoyi.info.collection.service.ICcdiStaffFmyRelationImportService;
import com.ruoyi.info.collection.service.ICcdiStaffFmyRelationService;
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.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 员工亲属关系 服务层处理
 *
 * @author ruoyi
 * @date 2026-02-09
 */
@Service
public class CcdiStaffFmyRelationServiceImpl implements ICcdiStaffFmyRelationService {

    @Resource
    private CcdiStaffFmyRelationMapper relationMapper;

    @Resource
    private ICcdiStaffFmyRelationImportService relationImportService;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    private ICcdiAssetInfoService assetInfoService;

    @Resource
    private ICcdiAssetInfoImportService assetInfoImportService;

    @Resource
    private CcdiStaffEnterpriseRelationMapper staffEnterpriseRelationMapper;

    @Resource
    private CcdiDualSheetImportOrchestrationService dualSheetImportOrchestrationService;

    /**
     * 查询员工亲属关系列表
     *
     * @param queryDTO 查询条件
     * @return 员工亲属关系VO集合
     */
    @Override
    public java.util.List<CcdiStaffFmyRelationVO> selectRelationList(CcdiStaffFmyRelationQueryDTO queryDTO) {
        Page<CcdiStaffFmyRelationVO> page = new Page<>(1, Integer.MAX_VALUE);
        Page<CcdiStaffFmyRelationVO> resultPage = relationMapper.selectRelationPage(page, queryDTO);
        return resultPage.getRecords();
    }

    /**
     * 分页查询员工亲属关系列表
     *
     * @param page     分页对象
     * @param queryDTO 查询条件
     * @return 员工亲属关系VO分页结果
     */
    @Override
    public Page<CcdiStaffFmyRelationVO> selectRelationPage(Page<CcdiStaffFmyRelationVO> page, CcdiStaffFmyRelationQueryDTO queryDTO) {
        return relationMapper.selectRelationPage(page, queryDTO);
    }

    /**
     * 查询员工亲属关系列表（用于导出）
     *
     * @param queryDTO 查询条件
     * @return 员工亲属关系Excel实体集合
     */
    @Override
    public java.util.List<CcdiStaffFmyRelationExcel> selectRelationListForExport(CcdiStaffFmyRelationQueryDTO queryDTO) {
        return relationMapper.selectRelationListForExport(queryDTO).stream().map(vo -> {
            CcdiStaffFmyRelationExcel excel = new CcdiStaffFmyRelationExcel();
            BeanUtils.copyProperties(vo, excel);
            return excel;
        }).collect(Collectors.toList());
    }

    /**
     * 查询员工亲属关系详情
     *
     * @param id 主键ID
     * @return 员工亲属关系VO
     */
    @Override
    public CcdiStaffFmyRelationVO selectRelationById(Long id) {
        CcdiStaffFmyRelationVO relationVO = relationMapper.selectRelationById(id);
        if (relationVO == null) {
            return null;
        }
        if (StringUtils.isNotEmpty(relationVO.getPersonId()) && StringUtils.isNotEmpty(relationVO.getRelationCertNo())) {
            List<CcdiAssetInfoVO> assetInfoList = assetInfoService
                    .selectByFamilyIdAndPersonId(relationVO.getPersonId(), relationVO.getRelationCertNo())
                    .stream()
                    .map(this::toAssetInfoVO)
                    .toList();
            relationVO.setAssetInfoList(assetInfoList);
        }
        return relationVO;
    }

    /**
     * 新增员工亲属关系
     *
     * @param addDTO 新增DTO
     * @return 结果
     */
    @Override
    @Transactional
    public int insertRelation(CcdiStaffFmyRelationAddDTO addDTO) {
        validateAnnualIncome(addDTO.getAnnualIncome(), "家庭成员年收入");
        CcdiStaffFmyRelation relation = new CcdiStaffFmyRelation();
        BeanUtils.copyProperties(addDTO, relation);

        // 设置默认值
        relation.setIsEmpFamily(true);
        relation.setIsCustFamily(false);
        relation.setDataSource("MANUAL");
        if (relation.getStatus() == null) {
            relation.setStatus(1);
        }

        int result = relationMapper.insert(relation);
        assetInfoService.replaceByFamilyIdAndPersonId(addDTO.getPersonId(), addDTO.getRelationCertNo(), addDTO.getAssetInfoList());
        return result;
    }

    /**
     * 修改员工亲属关系
     *
     * @param editDTO 编辑DTO
     * @return 结果
     */
    @Override
    @Transactional
    public int updateRelation(CcdiStaffFmyRelationEditDTO editDTO) {
        validateAnnualIncome(editDTO.getAnnualIncome(), "家庭成员年收入");
        CcdiStaffFmyRelation existing = relationMapper.selectById(editDTO.getId());
        if (existing == null) {
            throw new RuntimeException("员工亲属关系不存在");
        }
        if (!StringUtils.equals(existing.getRelationCertType(), editDTO.getRelationCertType())
                || !StringUtils.equals(existing.getRelationCertNo(), editDTO.getRelationCertNo())) {
            throw new RuntimeException("关系人证件类型/证件号码不允许修改");
        }

        CcdiStaffFmyRelation relation = new CcdiStaffFmyRelation();
        BeanUtils.copyProperties(editDTO, relation);
        int result = relationMapper.updateById(relation);
        if (Integer.valueOf(1).equals(existing.getStatus()) && Integer.valueOf(0).equals(editDTO.getStatus())) {
            staffEnterpriseRelationMapper.invalidateByFamilyCertNo(existing.getRelationCertNo());
        }
        assetInfoService.replaceByFamilyIdAndPersonId(editDTO.getPersonId(), editDTO.getRelationCertNo(), editDTO.getAssetInfoList());
        return result;
    }

    /**
     * 批量删除员工亲属关系
     *
     * @param ids 需要删除的主键ID
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteRelationByIds(Long[] ids) {
        List<Long> idList = java.util.List.of(ids);
        List<CcdiStaffFmyRelation> relationList = relationMapper.selectBatchIds(idList);
        for (CcdiStaffFmyRelation relation : relationList) {
            if (StringUtils.isEmpty(relation.getPersonId()) || StringUtils.isEmpty(relation.getRelationCertNo())) {
                continue;
            }
            assetInfoService.deleteByFamilyIdAndPersonId(relation.getPersonId(), relation.getRelationCertNo());
        }
        return relationMapper.deleteBatchIds(idList);
    }

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

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

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

        initializeImportStatus("import:staffFmyRelation:", taskId, excelList.size());

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

        return taskId;
    }

    @Override
    @Transactional
    public StaffFmyRelationImportSubmitResultVO importRelationWithAssets(List<CcdiStaffFmyRelationExcel> relationList,
                                                                         List<CcdiAssetInfoExcel> assetList) {
        boolean hasRelationRows = relationList != null && !relationList.isEmpty();
        boolean hasAssetRows = assetList != null && !assetList.isEmpty();
        if (!hasRelationRows && !hasAssetRows) {
            throw new RuntimeException("至少需要一条数据");
        }

        StaffFmyRelationImportSubmitResultVO result = new StaffFmyRelationImportSubmitResultVO();
        result.setMessage(buildImportSubmitMessage(hasRelationRows, hasAssetRows));

        if (hasRelationRows && !hasAssetRows) {
            result.setRelationTaskId(importRelation(relationList));
            return result;
        }
        if (!hasRelationRows) {
            result.setAssetTaskId(assetInfoImportService.importAssetInfo(assetList));
            return result;
        }

        String relationTaskId = UUID.randomUUID().toString();
        String assetTaskId = UUID.randomUUID().toString();
        initializeImportStatus("import:staffFmyRelation:", relationTaskId, relationList.size());
        initializeImportStatus("import:assetInfo:", assetTaskId, assetList.size());

        result.setRelationTaskId(relationTaskId);
        result.setAssetTaskId(assetTaskId);
        dualSheetImportOrchestrationService.importRelationWithAssetsAsync(
                relationList,
                relationTaskId,
                assetList,
                assetTaskId,
                currentUserName()
        );
        return result;
    }

    private void initializeImportStatus(String keyPrefix, String taskId, int totalCount) {
        Map<String, Object> statusData = new HashMap<>();
        statusData.put("taskId", taskId);
        statusData.put("status", "PROCESSING");
        statusData.put("totalCount", totalCount);
        statusData.put("successCount", 0);
        statusData.put("failureCount", 0);
        statusData.put("progress", 0);
        statusData.put("startTime", System.currentTimeMillis());
        statusData.put("message", "正在处理...");

        String statusKey = keyPrefix + taskId;
        redisTemplate.opsForHash().putAll(statusKey, statusData);
        redisTemplate.expire(statusKey, 7, TimeUnit.DAYS);
    }

    private String buildImportSubmitMessage(boolean hasRelationRows, boolean hasAssetRows) {
        if (hasRelationRows && hasAssetRows) {
            return "已提交员工亲属关系和亲属资产信息导入任务";
        }
        if (hasRelationRows) {
            return "已提交员工亲属关系导入任务";
        }
        return "已提交亲属资产信息导入任务";
    }

    private String currentUserName() {
        try {
            return SecurityUtils.getUsername();
        } catch (Exception e) {
            return "system";
        }
    }

    private CcdiAssetInfoVO toAssetInfoVO(CcdiAssetInfo assetInfo) {
        CcdiAssetInfoVO assetInfoVO = new CcdiAssetInfoVO();
        BeanUtils.copyProperties(assetInfo, assetInfoVO);
        return assetInfoVO;
    }

    private void validateAnnualIncome(BigDecimal annualIncome, String fieldLabel) {
        if (annualIncome == null) {
            return;
        }
        if (annualIncome.compareTo(BigDecimal.ZERO) < 0) {
            throw new RuntimeException(fieldLabel + "不能为负数");
        }
        if (annualIncome.scale() > 2) {
            throw new RuntimeException(fieldLabel + "最多保留2位小数");
        }
    }
}
