package com.ruoyi.ccdi.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.ccdi.domain.CcdiBizIntermediary;
import com.ruoyi.ccdi.domain.CcdiEnterpriseBaseInfo;
import com.ruoyi.ccdi.domain.dto.*;
import com.ruoyi.ccdi.domain.excel.CcdiIntermediaryEntityExcel;
import com.ruoyi.ccdi.domain.excel.CcdiIntermediaryPersonExcel;
import com.ruoyi.ccdi.domain.vo.CcdiIntermediaryEntityDetailVO;
import com.ruoyi.ccdi.domain.vo.CcdiIntermediaryPersonDetailVO;
import com.ruoyi.ccdi.domain.vo.CcdiIntermediaryVO;
import com.ruoyi.ccdi.mapper.CcdiBizIntermediaryMapper;
import com.ruoyi.ccdi.mapper.CcdiEnterpriseBaseInfoMapper;
import com.ruoyi.ccdi.mapper.CcdiIntermediaryMapper;
import com.ruoyi.ccdi.service.ICcdiIntermediaryService;
import com.ruoyi.common.utils.StringUtils;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * 中介Service业务层处理
 *
 * @author ruoyi
 * @date 2026-02-04
 */
@Service
public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService {

    @Resource
    private CcdiBizIntermediaryMapper bizIntermediaryMapper;

    @Resource
    private CcdiEnterpriseBaseInfoMapper enterpriseBaseInfoMapper;

    @Resource
    private CcdiIntermediaryMapper intermediaryMapper;

    /**
     * 分页查询中介列表
     * 使用XML联合查询实现,支持个人中介和实体中介的灵活查询
     * 使用MyBatis Plus分页插件自动处理分页
     *
     * @param page     分页对象
     * @param queryDTO 查询条件
     * @return 中介VO分页结果
     */
    @Override
    public Page<CcdiIntermediaryVO> selectIntermediaryPage(Page<CcdiIntermediaryVO> page, CcdiIntermediaryQueryDTO queryDTO) {
        // 直接调用Mapper的联合查询方法，MyBatis Plus会自动处理分页
        return intermediaryMapper.selectIntermediaryList(page, queryDTO);
    }

    /**
     * 查询个人中介详情
     *
     * @param bizId 人员ID
     * @return 个人中介详情VO
     */
    @Override
    public CcdiIntermediaryPersonDetailVO selectIntermediaryPersonDetail(String bizId) {
        CcdiBizIntermediary person = bizIntermediaryMapper.selectById(bizId);
        if (person == null) {
            return null;
        }

        CcdiIntermediaryPersonDetailVO vo = new CcdiIntermediaryPersonDetailVO();
        BeanUtils.copyProperties(person, vo);
        // 设置中介类型为个人
        vo.setIntermediaryType("1");
        return vo;
    }

    /**
     * 查询实体中介详情
     *
     * @param socialCreditCode 统一社会信用代码
     * @return 实体中介详情VO
     */
    @Override
    public CcdiIntermediaryEntityDetailVO selectIntermediaryEntityDetail(String socialCreditCode) {
        CcdiEnterpriseBaseInfo entity = enterpriseBaseInfoMapper.selectById(socialCreditCode);
        if (entity == null) {
            return null;
        }

        CcdiIntermediaryEntityDetailVO vo = new CcdiIntermediaryEntityDetailVO();
        BeanUtils.copyProperties(entity, vo);
        // 设置中介类型为实体
        vo.setIntermediaryType("2");
        // 设置业务ID(使用socialCreditCode作为bizId,前端判断是否为新增模式)
        vo.setBizId(socialCreditCode);
        return vo;
    }

    /**
     * 新增个人中介
     *
     * @param addDTO 新增DTO
     * @return 结果
     */
    @Override
    @Transactional
    public int insertIntermediaryPerson(CcdiIntermediaryPersonAddDTO addDTO) {
        // 检查人员ID唯一性
        if (!checkPersonIdUnique(addDTO.getPersonId(), null)) {
            throw new RuntimeException("该证件号已存在");
        }

        CcdiBizIntermediary person = new CcdiBizIntermediary();
        BeanUtils.copyProperties(addDTO, person);
        person.setDataSource("MANUAL");

        return bizIntermediaryMapper.insert(person);
    }

    /**
     * 修改个人中介
     *
     * @param editDTO 编辑DTO
     * @return 结果
     */
    @Override
    @Transactional
    public int updateIntermediaryPerson(CcdiIntermediaryPersonEditDTO editDTO) {
        // 检查人员ID唯一性（排除自己）
        if (StringUtils.isNotEmpty(editDTO.getPersonId())) {
            if (!checkPersonIdUnique(editDTO.getPersonId(), editDTO.getBizId())) {
                throw new RuntimeException("该证件号已存在");
            }
        }

        CcdiBizIntermediary person = new CcdiBizIntermediary();
        BeanUtils.copyProperties(editDTO, person);

        return bizIntermediaryMapper.updateById(person);
    }

    /**
     * 新增实体中介
     *
     * @param addDTO 新增DTO
     * @return 结果
     */
    @Override
    @Transactional
    public int insertIntermediaryEntity(CcdiIntermediaryEntityAddDTO addDTO) {
        // 检查统一社会信用代码唯一性
        if (StringUtils.isNotEmpty(addDTO.getSocialCreditCode())) {
            if (!checkSocialCreditCodeUnique(addDTO.getSocialCreditCode(), null)) {
                throw new RuntimeException("该统一社会信用代码已存在");
            }
        }

        CcdiEnterpriseBaseInfo entity = new CcdiEnterpriseBaseInfo();
        BeanUtils.copyProperties(addDTO, entity);
        entity.setRiskLevel("1");
        entity.setEntSource("INTERMEDIARY");
        entity.setDataSource("MANUAL");

        return enterpriseBaseInfoMapper.insert(entity);
    }

    /**
     * 修改实体中介
     *
     * @param editDTO 编辑DTO
     * @return 结果
     */
    @Override
    @Transactional
    public int updateIntermediaryEntity(CcdiIntermediaryEntityEditDTO editDTO) {
        CcdiEnterpriseBaseInfo entity = new CcdiEnterpriseBaseInfo();
        BeanUtils.copyProperties(editDTO, entity);

        return enterpriseBaseInfoMapper.updateById(entity);
    }

    /**
     * 批量删除中介
     *
     * @param ids 需要删除的ID数组
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteIntermediaryByIds(String[] ids) {
        int count = 0;
        for (String id : ids) {
            // 判断是个人还是实体（个人ID长度较长，实体统一社会信用代码18位）
            if (id.length() > 18) {
                // 个人中介
                count += bizIntermediaryMapper.deleteById(id);
            } else {
                // 实体中介
                count += enterpriseBaseInfoMapper.deleteById(id);
            }
        }
        return count;
    }

    /**
     * 校验人员ID唯一性
     *
     * @param personId 人员ID
     * @param bizId    排除的人员ID
     * @return true=唯一, false=不唯一
     */
    @Override
    public boolean checkPersonIdUnique(String personId, String bizId) {
        LambdaQueryWrapper<CcdiBizIntermediary> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CcdiBizIntermediary::getPersonId, personId);
        if (StringUtils.isNotEmpty(bizId)) {
            wrapper.ne(CcdiBizIntermediary::getBizId, bizId);
        }
        return bizIntermediaryMapper.selectCount(wrapper) == 0;
    }

    /**
     * 校验统一社会信用代码唯一性
     *
     * @param socialCreditCode 统一社会信用代码
     * @param excludeId        排除的ID
     * @return true=唯一, false=不唯一
     */
    @Override
    public boolean checkSocialCreditCodeUnique(String socialCreditCode, String excludeId) {
        LambdaQueryWrapper<CcdiEnterpriseBaseInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CcdiEnterpriseBaseInfo::getSocialCreditCode, socialCreditCode);
        if (StringUtils.isNotEmpty(excludeId)) {
            wrapper.ne(CcdiEnterpriseBaseInfo::getSocialCreditCode, excludeId);
        }
        return enterpriseBaseInfoMapper.selectCount(wrapper) == 0;
    }

    /**
     * 导入个人中介数据（批量操作）
     * 优化：使用批量查询替代循环中的单条查询，减少数据库交互次数
     *
     * @param list          Excel实体列表
     * @param updateSupport 是否更新支持
     * @return 结果
     */
    @Override
    @Transactional
    public String importIntermediaryPerson(List<CcdiIntermediaryPersonExcel> list, boolean updateSupport) {
        if (StringUtils.isNull(list) || list.isEmpty()) {
            return "至少需要一条数据";
        }

        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();

        // 待插入和更新的列表
        List<CcdiBizIntermediary> insertList = new ArrayList<>();
        List<CcdiBizIntermediary> updateList = new ArrayList<>();
        List<String> personIds = new ArrayList<>();

        // 第一轮：收集所有personId
        for (CcdiIntermediaryPersonExcel excel : list) {
            if (StringUtils.isNotEmpty(excel.getPersonId())) {
                personIds.add(excel.getPersonId());
            }
        }

        // 第二轮：批量查询已存在的记录（一次查询替代N次查询）
        java.util.Map<String, String> personIdToBizIdMap = new java.util.HashMap<>();
        if (!personIds.isEmpty()) {
            LambdaQueryWrapper<CcdiBizIntermediary> wrapper = new LambdaQueryWrapper<>();
            wrapper.select(CcdiBizIntermediary::getBizId, CcdiBizIntermediary::getPersonId);
            wrapper.in(CcdiBizIntermediary::getPersonId, personIds);
            List<CcdiBizIntermediary> existingList = bizIntermediaryMapper.selectList(wrapper);

            // 建立personId到bizId的映射
            for (CcdiBizIntermediary existing : existingList) {
                personIdToBizIdMap.put(existing.getPersonId(), existing.getBizId());
            }
        }

        // 第三轮：数据验证和分类（使用Map进行快速判断，避免重复查询）
        for (int i = 0; i < list.size(); i++) {
            try {
                CcdiIntermediaryPersonExcel excel = list.get(i);

                // 验证数据
                if (StringUtils.isEmpty(excel.getName())) {
                    throw new RuntimeException("姓名不能为空");
                }
                if (StringUtils.isEmpty(excel.getPersonId())) {
                    throw new RuntimeException("证件号码不能为空");
                }

                // 转换为实体
                CcdiBizIntermediary person = new CcdiBizIntermediary();
                BeanUtils.copyProperties(excel, person);
                person.setPersonType("中介");
                person.setDataSource("IMPORT");

                // 使用Map快速判断是否存在
                String existingBizId = personIdToBizIdMap.get(excel.getPersonId());
                if (existingBizId != null) {
                    // 记录已存在
                    if (updateSupport) {
                        // 需要更新，设置bizId
                        person.setBizId(existingBizId);
                        updateList.add(person);
                    } else {
                        throw new RuntimeException("该证件号已存在");
                    }
                } else {
                    // 新数据，加入插入列表
                    insertList.add(person);
                }

                successNum++;
                successMsg.append("<br/>").append(successNum).append("、").append(excel.getName()).append(" 导入成功");
            } catch (Exception e) {
                failureNum++;
                failureMsg.append("<br/>").append(failureNum).append("、").append(list.get(i).getName()).append(" 导入失败：");
                failureMsg.append(e.getMessage());
            }
        }

        // 构建返回消息
        StringBuilder resultMsg = new StringBuilder();

        if (failureNum > 0) {
            resultMsg.append("很抱歉，导入失败！共 ").append(failureNum).append(" 条数据格式不正确，错误如下：");
            resultMsg.append(failureMsg);
        }

        // 第四轮：批量处理
        try {
            // 批量插入新记录
            if (!insertList.isEmpty()) {
                bizIntermediaryMapper.insertBatch(insertList);
            }

            // 批量更新已存在的记录
            if (!updateList.isEmpty()) {
                bizIntermediaryMapper.updateBatch(updateList);
            }

            // 只在有失败的情况下才返回成功信息，否则返回简洁的成功消息
            if (failureNum > 0) {
                resultMsg.append("<br/><br/>成功导入 ").append(successNum).append(" 条数据");
            } else {
                resultMsg.append("恭喜您，数据已全部导入成功！共 ").append(successNum).append(" 条");
            }
            return resultMsg.toString();
        } catch (Exception e) {
            throw new RuntimeException("批量操作失败：" + e.getMessage());
        }
    }

    /**
     * 导入实体中介数据（批量操作）
     * 优化：使用批量查询替代循环中的单条查询，减少数据库交互次数
     *
     * @param list          Excel实体列表
     * @param updateSupport 是否更新支持
     * @return 结果
     */
    @Override
    @Transactional
    public String importIntermediaryEntity(List<CcdiIntermediaryEntityExcel> list, boolean updateSupport) {
        if (StringUtils.isNull(list) || list.isEmpty()) {
            return "至少需要一条数据";
        }

        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();

        // 待插入和更新的列表
        List<CcdiEnterpriseBaseInfo> insertList = new ArrayList<>();
        List<CcdiEnterpriseBaseInfo> updateList = new ArrayList<>();
        List<String> socialCreditCodes = new ArrayList<>();

        // 第一轮：收集所有socialCreditCode
        for (CcdiIntermediaryEntityExcel excel : list) {
            if (StringUtils.isNotEmpty(excel.getSocialCreditCode())) {
                socialCreditCodes.add(excel.getSocialCreditCode());
            }
        }

        // 第二轮：批量查询已存在的记录（一次查询替代N次查询）
        java.util.Map<String, CcdiEnterpriseBaseInfo> existingEntityMap = new java.util.HashMap<>();
        if (!socialCreditCodes.isEmpty()) {
            LambdaQueryWrapper<CcdiEnterpriseBaseInfo> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(CcdiEnterpriseBaseInfo::getSocialCreditCode, socialCreditCodes);
            List<CcdiEnterpriseBaseInfo> existingList = enterpriseBaseInfoMapper.selectList(wrapper);

            // 建立socialCreditCode到实体的映射
            for (CcdiEnterpriseBaseInfo existing : existingList) {
                existingEntityMap.put(existing.getSocialCreditCode(), existing);
            }
        }

        // 第三轮：数据验证和分类（使用Map进行快速判断，避免重复查询）
        for (int i = 0; i < list.size(); i++) {
            try {
                CcdiIntermediaryEntityExcel excel = list.get(i);

                // 验证数据
                if (StringUtils.isEmpty(excel.getEnterpriseName())) {
                    throw new RuntimeException("机构名称不能为空");
                }

                // 转换为实体
                CcdiEnterpriseBaseInfo entity = new CcdiEnterpriseBaseInfo();
                BeanUtils.copyProperties(excel, entity);
                entity.setRiskLevel("1");
                entity.setEntSource("INTERMEDIARY");
                entity.setDataSource("IMPORT");

                // 使用Map快速判断是否存在
                if (StringUtils.isNotEmpty(excel.getSocialCreditCode())) {
                    CcdiEnterpriseBaseInfo existingEntity = existingEntityMap.get(excel.getSocialCreditCode());
                    if (existingEntity != null) {
                        // 记录已存在
                        if (updateSupport) {
                            // 需要更新，直接使用socialCreditCode作为主键
                            updateList.add(entity);
                        } else {
                            throw new RuntimeException("该统一社会信用代码已存在");
                        }
                    } else {
                        // 新数据，加入插入列表
                        insertList.add(entity);
                    }
                } else {
                    // 没有统一社会信用代码，直接加入插入列表
                    insertList.add(entity);
                }

                successNum++;
                successMsg.append("<br/>").append(successNum).append("、").append(excel.getEnterpriseName()).append(" 导入成功");
            } catch (Exception e) {
                failureNum++;
                failureMsg.append("<br/>").append(failureNum).append("、").append(list.get(i).getEnterpriseName()).append(" 导入失败：");
                failureMsg.append(e.getMessage());
            }
        }

        // 构建返回消息
        StringBuilder resultMsg = new StringBuilder();

        if (failureNum > 0) {
            resultMsg.append("很抱歉，导入失败！共 ").append(failureNum).append(" 条数据格式不正确，错误如下：");
            resultMsg.append(failureMsg);
        }

        // 第四轮：批量处理
        try {
            // 批量插入新记录
            if (!insertList.isEmpty()) {
                enterpriseBaseInfoMapper.insertBatch(insertList);
            }

            // 批量更新已存在的记录
            if (!updateList.isEmpty()) {
                enterpriseBaseInfoMapper.updateBatch(updateList);
            }

            // 只在有失败的情况下才返回成功信息，否则返回简洁的成功消息
            if (failureNum > 0) {
                resultMsg.append("<br/><br/>成功导入 ").append(successNum).append(" 条数据");
            } else {
                resultMsg.append("恭喜您，数据已全部导入成功！共 ").append(successNum).append(" 条");
            }
            return resultMsg.toString();
        } catch (Exception e) {
            throw new RuntimeException("批量操作失败：" + e.getMessage());
        }
    }
}
