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

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.info.collection.domain.CcdiCustEnterpriseRelation;
import com.ruoyi.info.collection.domain.CcdiEnterpriseBaseInfo;
import com.ruoyi.info.collection.domain.CcdiIntermediaryEnterpriseRelation;
import com.ruoyi.info.collection.domain.CcdiStaffEnterpriseRelation;
import com.ruoyi.info.collection.domain.dto.CcdiEnterpriseBaseInfoAddDTO;
import com.ruoyi.info.collection.domain.dto.CcdiEnterpriseBaseInfoEditDTO;
import com.ruoyi.info.collection.domain.dto.CcdiEnterpriseBaseInfoQueryDTO;
import com.ruoyi.info.collection.domain.excel.CcdiEnterpriseBaseInfoExcel;
import com.ruoyi.info.collection.domain.vo.CcdiEnterpriseBaseInfoVO;
import com.ruoyi.info.collection.enums.DataSource;
import com.ruoyi.info.collection.enums.EnterpriseRiskLevel;
import com.ruoyi.info.collection.enums.EnterpriseSource;
import com.ruoyi.info.collection.mapper.CcdiEnterpriseBaseInfoMapper;
import com.ruoyi.info.collection.mapper.CcdiCustEnterpriseRelationMapper;
import com.ruoyi.info.collection.mapper.CcdiIntermediaryEnterpriseRelationMapper;
import com.ruoyi.info.collection.mapper.CcdiStaffEnterpriseRelationMapper;
import com.ruoyi.info.collection.service.ICcdiEnterpriseBaseInfoImportService;
import com.ruoyi.info.collection.service.ICcdiEnterpriseBaseInfoService;
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.List;
import java.util.Map;
import java.util.StringJoiner;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 实体库管理 Service 实现
 *
 * @author ruoyi
 * @date 2026-04-17
 */
@Service
public class CcdiEnterpriseBaseInfoServiceImpl implements ICcdiEnterpriseBaseInfoService {

    @Resource
    private CcdiEnterpriseBaseInfoMapper enterpriseBaseInfoMapper;

    @Resource
    private CcdiStaffEnterpriseRelationMapper staffEnterpriseRelationMapper;

    @Resource
    private CcdiCustEnterpriseRelationMapper custEnterpriseRelationMapper;

    @Resource
    private CcdiIntermediaryEnterpriseRelationMapper intermediaryEnterpriseRelationMapper;

    @Resource
    private ICcdiEnterpriseBaseInfoImportService enterpriseBaseInfoImportService;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public Page<CcdiEnterpriseBaseInfoVO> selectEnterpriseBaseInfoPage(Page<CcdiEnterpriseBaseInfoVO> page,
                                                                       CcdiEnterpriseBaseInfoQueryDTO queryDTO) {
        return enterpriseBaseInfoMapper.selectEnterpriseBaseInfoPage(page, queryDTO);
    }

    @Override
    public CcdiEnterpriseBaseInfoVO selectEnterpriseBaseInfoById(String socialCreditCode) {
        CcdiEnterpriseBaseInfo entity = enterpriseBaseInfoMapper.selectById(socialCreditCode);
        if (entity == null) {
            return null;
        }
        CcdiEnterpriseBaseInfoVO vo = new CcdiEnterpriseBaseInfoVO();
        BeanUtils.copyProperties(entity, vo);
        return vo;
    }

    @Override
    @Transactional
    public int insertEnterpriseBaseInfo(CcdiEnterpriseBaseInfoAddDTO addDTO) {
        if (enterpriseBaseInfoMapper.selectById(addDTO.getSocialCreditCode()) != null) {
            throw new RuntimeException("该统一社会信用代码已存在");
        }
        validateRiskLevelAndEnterpriseSource(addDTO.getRiskLevel(), addDTO.getEntSource());

        CcdiEnterpriseBaseInfo entity = new CcdiEnterpriseBaseInfo();
        BeanUtils.copyProperties(addDTO, entity);
        entity.setStatus(trimToNull(addDTO.getStatus()));
        entity.setDataSource(DataSource.MANUAL.getCode());
        return enterpriseBaseInfoMapper.insert(entity);
    }

    @Override
    @Transactional
    public int updateEnterpriseBaseInfo(CcdiEnterpriseBaseInfoEditDTO editDTO) {
        CcdiEnterpriseBaseInfo existing = enterpriseBaseInfoMapper.selectById(editDTO.getSocialCreditCode());
        if (existing == null) {
            throw new RuntimeException("实体库记录不存在");
        }
        validateEnumFields(editDTO.getStatus(), editDTO.getRiskLevel(), editDTO.getEntSource(), editDTO.getDataSource());

        CcdiEnterpriseBaseInfo entity = new CcdiEnterpriseBaseInfo();
        BeanUtils.copyProperties(editDTO, entity);
        entity.setStatus(trimToNull(editDTO.getStatus()));
        entity.setDataSource(existing.getDataSource());
        return enterpriseBaseInfoMapper.updateById(entity);
    }

    @Override
    @Transactional
    public int deleteEnterpriseBaseInfoByIds(String[] socialCreditCodes) {
        if (socialCreditCodes == null || socialCreditCodes.length == 0) {
            return 0;
        }
        for (String socialCreditCode : socialCreditCodes) {
            validateDeleteRelations(socialCreditCode);
        }
        return enterpriseBaseInfoMapper.deleteBatchIds(List.of(socialCreditCodes));
    }

    @Override
    public List<CcdiEnterpriseBaseInfoExcel> selectEnterpriseBaseInfoListForExport(CcdiEnterpriseBaseInfoQueryDTO queryDTO) {
        LambdaQueryWrapper<CcdiEnterpriseBaseInfo> wrapper = buildQueryWrapper(queryDTO);
        return enterpriseBaseInfoMapper.selectList(wrapper).stream().map(entity -> {
            CcdiEnterpriseBaseInfoExcel excel = new CcdiEnterpriseBaseInfoExcel();
            BeanUtils.copyProperties(entity, excel);
            return excel;
        }).toList();
    }

    @Override
    @Transactional
    public String importEnterpriseBaseInfo(List<CcdiEnterpriseBaseInfoExcel> excelList) {
        String taskId = UUID.randomUUID().toString();
        String statusKey = "import:enterpriseBaseInfo:" + 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", System.currentTimeMillis());
        statusData.put("message", "正在处理...");

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

        enterpriseBaseInfoImportService.importEnterpriseBaseInfoAsync(excelList, taskId, SecurityUtils.getUsername());
        return taskId;
    }

    private LambdaQueryWrapper<CcdiEnterpriseBaseInfo> buildQueryWrapper(CcdiEnterpriseBaseInfoQueryDTO queryDTO) {
        LambdaQueryWrapper<CcdiEnterpriseBaseInfo> wrapper = new LambdaQueryWrapper<>();
        if (queryDTO == null) {
            return wrapper.orderByDesc(CcdiEnterpriseBaseInfo::getCreateTime);
        }
        wrapper.like(StringUtils.isNotEmpty(queryDTO.getEnterpriseName()),
                CcdiEnterpriseBaseInfo::getEnterpriseName, queryDTO.getEnterpriseName());
        wrapper.eq(StringUtils.isNotEmpty(queryDTO.getSocialCreditCode()),
                CcdiEnterpriseBaseInfo::getSocialCreditCode, queryDTO.getSocialCreditCode());
        wrapper.eq(StringUtils.isNotEmpty(queryDTO.getEnterpriseType()),
                CcdiEnterpriseBaseInfo::getEnterpriseType, queryDTO.getEnterpriseType());
        wrapper.eq(StringUtils.isNotEmpty(queryDTO.getEnterpriseNature()),
                CcdiEnterpriseBaseInfo::getEnterpriseNature, queryDTO.getEnterpriseNature());
        wrapper.like(StringUtils.isNotEmpty(queryDTO.getIndustryClass()),
                CcdiEnterpriseBaseInfo::getIndustryClass, queryDTO.getIndustryClass());
        wrapper.eq(StringUtils.isNotEmpty(queryDTO.getStatus()),
                CcdiEnterpriseBaseInfo::getStatus, queryDTO.getStatus());
        wrapper.eq(StringUtils.isNotEmpty(queryDTO.getRiskLevel()),
                CcdiEnterpriseBaseInfo::getRiskLevel, queryDTO.getRiskLevel());
        wrapper.eq(StringUtils.isNotEmpty(queryDTO.getEntSource()),
                CcdiEnterpriseBaseInfo::getEntSource, queryDTO.getEntSource());
        return wrapper.orderByDesc(CcdiEnterpriseBaseInfo::getCreateTime);
    }

    private void validateEnumFields(String status, String riskLevel, String entSource, String dataSource) {
        validateRiskLevelAndEnterpriseSource(riskLevel, entSource);
        if (StringUtils.isNotEmpty(status) && StringUtils.trim(status).length() > 50) {
            throw new RuntimeException("经营状态长度不能超过50个字符");
        }
        if (!containsDataSource(dataSource)) {
            throw new RuntimeException("数据来源不在允许范围内");
        }
    }

    private void validateRiskLevelAndEnterpriseSource(String riskLevel, String entSource) {
        if (!EnterpriseRiskLevel.contains(riskLevel)) {
            throw new RuntimeException("风险等级不在允许范围内");
        }
        if (!EnterpriseSource.contains(entSource)) {
            throw new RuntimeException("企业来源不在允许范围内");
        }
    }

    private boolean containsDataSource(String code) {
        for (DataSource source : DataSource.values()) {
            if (source.getCode().equals(code)) {
                return true;
            }
        }
        return false;
    }

    private String trimToNull(String value) {
        if (StringUtils.isEmpty(value)) {
            return null;
        }
        return value.trim();
    }

    private void validateDeleteRelations(String socialCreditCode) {
        StringJoiner relationTypes = new StringJoiner("、");
        if (staffEnterpriseRelationMapper.selectCount(new LambdaQueryWrapper<CcdiStaffEnterpriseRelation>()
                .eq(CcdiStaffEnterpriseRelation::getSocialCreditCode, socialCreditCode)) > 0) {
            relationTypes.add("员工");
        }
        if (custEnterpriseRelationMapper.selectCount(new LambdaQueryWrapper<CcdiCustEnterpriseRelation>()
                .eq(CcdiCustEnterpriseRelation::getSocialCreditCode, socialCreditCode)) > 0) {
            relationTypes.add("信贷客户");
        }
        if (intermediaryEnterpriseRelationMapper.selectCount(new LambdaQueryWrapper<CcdiIntermediaryEnterpriseRelation>()
                .eq(CcdiIntermediaryEnterpriseRelation::getSocialCreditCode, socialCreditCode)) > 0) {
            relationTypes.add("中介");
        }
        if (relationTypes.length() > 0) {
            throw new RuntimeException("统一社会信用代码[" + socialCreditCode + "]已关联" + relationTypes + "，删除失败");
        }
    }
}
