package com.jwipc.sys.logic.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jwipc.constant.DelFlag;
import com.jwipc.exception.DaoException;
import com.jwipc.page.PageUtil;
import com.jwipc.page.PageView;
import com.jwipc.security.LoginUtil;
import com.jwipc.supplier.entity.SupplierField;
import com.jwipc.supplier.entity.SupplierTemplate;
import com.jwipc.supplier.entity.SupplierTemplateField;
import com.jwipc.supplier.model.po.SupplierTemplateFieldPO;
import com.jwipc.supplier.model.po.SupplierTemplateFieldAliasPO;
import com.jwipc.supplier.service.ISupplierFieldService;
import com.jwipc.supplier.service.ISupplierTemplateFieldRelationService;
import com.jwipc.supplier.service.ISupplierTemplateFieldService;
import com.jwipc.supplier.service.ISupplierTemplateService;
import com.jwipc.sys.convert.ValidationRuleSettingConvert;
import com.jwipc.sys.dto.*;
import com.jwipc.sys.entity.AllowedCharacterType;
import com.jwipc.sys.entity.TRegexCharacterRelation;
import com.jwipc.sys.entity.TRegexRule;
import com.jwipc.sys.logic.ValidationRuleSettingLogic;
import com.jwipc.sys.model.po.TRegexRulePO;
import com.jwipc.sys.model.query.TRegexRuleQuery;
import com.jwipc.sys.service.ITAllowedCharacterTypeService;
import com.jwipc.sys.service.ITRegexCharacterRelationService;
import com.jwipc.sys.service.ITRegexRuleService;
import com.jwipc.util.EncryptUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  表单校验规则配置-逻辑实现类
 * </p>
 *
 * @author Chen Tianshi
 * @since 2025/8/26 15:27
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class ValidationRuleSettingLogicImpl implements ValidationRuleSettingLogic {

    private final ITAllowedCharacterTypeService allowedCharacterTypeService;
    private final ITRegexRuleService tRegexRulesService;
    private final ITRegexCharacterRelationService iTRegexCharacterRelationService;
    private final ValidationRuleSettingConvert validationRuleSettingConvert;
    private final ISupplierFieldService supplierFieldService;
    private final ISupplierTemplateService supplierTemplateService;
    private final ISupplierTemplateFieldService supplierTemplateFieldService;
    private final ISupplierTemplateFieldRelationService supplierTemplateFieldRelationService;

    private final static String VALIDATE_STR = "validateStr";
    private final static String FIELD_ID = "fieldId";
    private final static String FIELD_NAME = "fieldName";

    @Override
    public ValidationRuleSettingDomListDTO getAllAllowedCharacterType(Long regexRuleId) {
        List<AllowedCharacterType> allList = allowedCharacterTypeService.list();
        List<AllowedCharacterTypeCheckedDTO> characterTypeCheckedDTOList = validationRuleSettingConvert.characterEntityList2CheckedList(allList);
        if (regexRuleId != null) {
            // 编辑的情况，获取勾选的字符
            // 获取字符配置信息
            LambdaQueryWrapper<TRegexCharacterRelation> relationWrapper = new LambdaQueryWrapper<>();
            relationWrapper.eq(TRegexCharacterRelation::getRegexRuleId, regexRuleId);
            List<TRegexCharacterRelation> relationList = iTRegexCharacterRelationService.list(relationWrapper);
            // 提取relationList中所有的characterTypeId
            Set<Long> relationCharacterIds = relationList.stream()
                    .map(TRegexCharacterRelation::getCharacterTypeId) // 根据实际类名调整方法名
                    .collect(Collectors.toSet());
            // 遍历DTO列表并设置checkedFlag
            characterTypeCheckedDTOList.forEach(dto -> {
                if (relationCharacterIds.contains(dto.getId())) {
                    dto.setCheckedFLg("1"); // 存在关联关系，设置为1
                } else {
                    dto.setCheckedFLg("0"); // 不存在关联关系，设置为0（可选）
                }
            });
        }
        List<AllowedCharacterTypeCheckedDTO> characterList = characterTypeCheckedDTOList.stream()
                .filter(item -> "character".equals(item.getCharacterType()))
                .collect(Collectors.toList());
        List<AllowedCharacterTypeCheckedDTO> symbolList = characterTypeCheckedDTOList.stream()
                .filter(item -> "symbol".equals(item.getCharacterType()))
                .collect(Collectors.toList());

        ValidationRuleSettingDomListDTO result = new ValidationRuleSettingDomListDTO();
        result.setCharacterList(characterList);
        result.setSymbolList(symbolList);
        return result;
    }

    @Override
    public List<ValidationRuleSettingFieldSelectDTO> getFieldSelectList() {
        List<SupplierTemplateFieldAliasPO> fieldSelectList = supplierTemplateFieldRelationService.getFieldSelectList();
        return validationRuleSettingConvert.fieldSelectPo2DTO(fieldSelectList);
    }

    @Override
    public TRegexRule getById(Long regexRuleId) {
        return tRegexRulesService.getById(regexRuleId);
    }

    @Override
    public PageView list(TRegexRuleQuery query) {
        final Page<TRegexRule> dbPage = PageUtil.toPage(query);
        List<TRegexRulePO> list = tRegexRulesService.queryByPage(dbPage, query);
        return PageUtil.getPV(validationRuleSettingConvert.po2PageListDTO(list), dbPage.getTotal());
    }

    @Override
    public void insertOrUpdate(ValidationRuleSettingInsetUpdateDTO insetUpdateDTO) {
        // 1.插入主表
        TRegexRule tRegexRule = validationRuleSettingConvert.insertUpdateDto2Entity(insetUpdateDTO);
        tRegexRule.setCreateId(LoginUtil.getUserId());
        tRegexRule.setCreateTime(LocalDateTime.now());
        tRegexRule.setUpdateId(LoginUtil.getUserId());
        tRegexRule.setUpdateTime(LocalDateTime.now());
        try {
            if (Objects.isNull(insetUpdateDTO.getId())) {
                tRegexRulesService.saveOrUpdate(tRegexRule);
            } else {
                tRegexRulesService.updateById(tRegexRule);
            }
        } catch (DuplicateKeyException e) {
            throw new DaoException(insetUpdateDTO.getFieldName() + "-" + ("CNY".equals(insetUpdateDTO.getCurrencyType())? "人民币" : "非人民币") + "的配置信息已经存在，请确认");
        }

        // 2. 先删除所有旧关系
        LambdaQueryWrapper<TRegexCharacterRelation> deleteWrapper = new LambdaQueryWrapper<>();
        deleteWrapper.eq(TRegexCharacterRelation::getRegexRuleId, tRegexRule.getId());
        iTRegexCharacterRelationService.remove(deleteWrapper);
        // 3. 批量插入新关系
        List<TRegexCharacterRelation> relations = insetUpdateDTO.getCharacterIdList().stream()
                .map(characterId -> {
                    TRegexCharacterRelation relation = new TRegexCharacterRelation();
                    relation.setRegexRuleId(tRegexRule.getId());
                    relation.setCharacterTypeId(characterId);
                    relation.setCreateTime(LocalDateTime.now());
                    return relation;
                })
                .collect(Collectors.toList());

        // 批量插入
        iTRegexCharacterRelationService.saveBatch(relations);
        // 更新业务扩展字段表里的校验规则
        if ("BASE".equals(insetUpdateDTO.getFieldType())) {
            // 更新业务扩展字段表-动态校验规则
            SupplierTemplateField supplierTemplateField = supplierTemplateFieldService.getById(insetUpdateDTO.getFieldId());
            String diyValidateStr = supplierTemplateField.getFieldName();
            supplierTemplateField.setDiyValidateStr(diyValidateStr);
            supplierTemplateFieldService.saveOrUpdate(supplierTemplateField);
            // 更新供应商邀请-动态校验规则
            LambdaUpdateWrapper<SupplierField> updateValidationWrapper = new LambdaUpdateWrapper<>();
            updateValidationWrapper.set(SupplierField::getDiyValidateStr, diyValidateStr)
                .eq(SupplierField::getFieldCode, diyValidateStr);
            supplierFieldService.update(updateValidationWrapper);
        }
    }

    @Override
    public void deleteRule(List<Long> regexRuleIds) {
        List<TRegexRule> targetList = tRegexRulesService.listByIds(regexRuleIds);
        // 删除规则
        tRegexRulesService.removeBatchByIds(regexRuleIds);
        // 清空动态校验规则
        List<Long> idList = Lists.newArrayList();
        List<String> fieldCodeList = Lists.newArrayList();
        for (TRegexRule item : targetList) {
            if (!Objects.isNull(item.getFieldId())) {
                idList.add(item.getFieldId());
                SupplierTemplateField supplierTemplateField = supplierTemplateFieldService.getById(item.getFieldId());
                fieldCodeList.add(supplierTemplateField.getFieldName());
            }
        }
        Set<Long> idSet = new HashSet<>(idList);
        Set<String> fieldCodeSet = new HashSet<>(fieldCodeList);
        LambdaUpdateWrapper<SupplierTemplateField> supplierTemplateFieldLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        supplierTemplateFieldLambdaUpdateWrapper.set(SupplierTemplateField::getDiyValidateStr, null)
                .in(SupplierTemplateField::getId, idSet);
        supplierTemplateFieldService.update(supplierTemplateFieldLambdaUpdateWrapper);
        LambdaUpdateWrapper<SupplierField> supplierFieldLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        supplierFieldLambdaUpdateWrapper.set(SupplierField::getDiyValidateStr, null)
                .in(SupplierField::getFieldCode, fieldCodeSet);
        supplierFieldService.update(supplierFieldLambdaUpdateWrapper);
    }

    @Override
    public void updateRuleStatus(String regexRuleIds, String status) {
        final List<Long> idList = JSONArray.parseArray(regexRuleIds, Long.class);
        List<TRegexRule> updateList = Lists.newArrayList();
        for (Long id : idList) {
            TRegexRule rule = new TRegexRule();
            rule.setId(id);
            rule.setStatus(status);
            updateList.add(rule);
        }
        tRegexRulesService.updateBatchById(updateList);
    }

    @Override
    public List<ValidationRuleSettingInfoDTO> getFieldValidationById(Long fieldId) {
        LambdaQueryWrapper<TRegexRule> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TRegexRule::getFieldId, fieldId);
        queryWrapper.eq(TRegexRule::getStatus, "1");
        List<TRegexRule> tRegexRuleList = tRegexRulesService.list(queryWrapper);
        List<ValidationRuleSettingInfoDTO> infoList = Lists.newArrayList();
        if (CollectionUtil.isNotEmpty(tRegexRuleList)) {
            tRegexRuleList.forEach(tRegexRule -> {
                String pattern = getRegex(tRegexRule.getId());
                if (pattern != null) {
                    ValidationRuleSettingInfoDTO info = new ValidationRuleSettingInfoDTO();
                    info.setCurrencyType(tRegexRule.getCurrencyType());
                    info.setPattern(pattern);
                    info.setValidationMsg(tRegexRule.getValidationMsg());
                    info.setMinLength(tRegexRule.getMinLength());
                    info.setMaxLength(tRegexRule.getMaxLength());
                    info.setFixedLength(tRegexRule.getFixedLength());
                    infoList.add(info);
                }
            });
        }
        return infoList;
    }

    @Override
    public List<ValidationRuleSettingInfoDTO> getAllValidationByTemplateId(String templateId, Integer type) {
        //type等于0，表示此链接是用于生成供应商邀请链接
        if (templateId != null && type.equals(0)) {
            try {
                //需要判断是否是数字，如果是不需要解码
                if (StrUtil.isNotEmpty(templateId) && !StrUtil.isNumeric(templateId)) {
                    templateId = EncryptUtils.decrypt(templateId);
                }
                //如果模板传0，则用默认的default模板
                if ("0".equals(templateId)) {
                    final SupplierTemplate moduleTemplate = getDefaultTemplate();
                    templateId = String.valueOf(moduleTemplate.getId());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 先拿到模板项目下的字段
        List<SupplierTemplateFieldPO> moduleTemplateFieldFormMapList =
                supplierTemplateFieldRelationService.selectByTemplate(
                        templateId,
                        DelFlag.NORMAL.getStatus());
        List<Map<String, Object>> mapList = Lists.newArrayList();
        for (SupplierTemplateFieldPO supplierTemplateFieldPO : moduleTemplateFieldFormMapList) {
            Map<String, Object> map = new HashMap<>();
            map.put(VALIDATE_STR, supplierTemplateFieldPO.getDiyValidateStr());
            Long fieldId = (long) supplierTemplateFieldPO.getFieldId();
            map.put(FIELD_ID, fieldId);
            map.put(FIELD_NAME, supplierTemplateFieldPO.getFieldName());
            mapList.add(map);
        }
        return getAllValidationRule(mapList);
    }

    @Override
    public List<ValidationRuleSettingInfoDTO> getAllValidationBySupplierId(Long supplierId) {
        List<SupplierField> supplierFields = supplierFieldService.list(
                new LambdaQueryWrapper<SupplierField>().eq(SupplierField::getSupplierId, supplierId));
        Set<String> fieldCodes = supplierFields.stream().map(SupplierField::getFieldCode).collect(Collectors.toSet());
        //需要查询到字段表的remark
        final List<SupplierTemplateField> list = supplierTemplateFieldService.list(
                new LambdaQueryWrapper<SupplierTemplateField>().in(SupplierTemplateField::getFieldName, fieldCodes));
        List<Map<String, Object>> mapList = Lists.newArrayList();
        for (SupplierTemplateField supplierTemplateField : list) {
            Map<String, Object> map = new HashMap<>();
            map.put(VALIDATE_STR, supplierTemplateField.getDiyValidateStr());
            map.put(FIELD_ID, supplierTemplateField.getId());
            map.put(FIELD_NAME, supplierTemplateField.getFieldName());
            mapList.add(map);
        }

        return getAllValidationRule(mapList);
    }

    /**
     * 获取校验规则
     * @param listMap 包含：校验规则名称、字段ID、字段名的列表
     * @return 校验规则
     */
    private List<ValidationRuleSettingInfoDTO> getAllValidationRule(List<Map<String, Object>> listMap) {
        if (CollectionUtil.isEmpty(listMap)) return null;
        List<ValidationRuleSettingInfoDTO> resultList = Lists.newArrayList();

        LambdaQueryWrapper<TRegexRule> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TRegexRule::getStatus, "1");
        List<TRegexRule> tRegexRuleList = tRegexRulesService.list(queryWrapper);
        if (CollectionUtil.isNotEmpty(tRegexRuleList)) {
            tRegexRuleList.forEach(tRegexRule -> {
                // 查询基础字段的校验规则
                if (!Objects.isNull(tRegexRule.getFieldId())) {
                    for (Map<String, Object> map : listMap) {
                        String validateStr = Objects.isNull(map.get(VALIDATE_STR)) ? null : map.get(VALIDATE_STR).toString();
                        if (StringUtils.isNotEmpty(validateStr)) {
                            if (Objects.equals(map.get(FIELD_ID), tRegexRule.getFieldId())) {
                                String pattern = getRegex(tRegexRule.getId());
                                if (pattern != null) {
                                    ValidationRuleSettingInfoDTO info = new ValidationRuleSettingInfoDTO();
                                    info.setFieldName(map.get(FIELD_NAME).toString());
                                    info.setCurrencyType(tRegexRule.getCurrencyType());
                                    info.setPattern(pattern);
                                    info.setValidationMsg(tRegexRule.getValidationMsg());
                                    info.setMinLength(tRegexRule.getMinLength());
                                    info.setMaxLength(tRegexRule.getMaxLength());
                                    info.setFixedLength(tRegexRule.getFixedLength());
                                    resultList.add(info);
                                }
                            }
                        }
                    }
                }
                // 查询供应商银行字段的校验规则
                if (StringUtils.isNotEmpty(tRegexRule.getFieldId2())) {
                    String pattern = getRegex(tRegexRule.getId());
                    if (pattern != null) {
                        ValidationRuleSettingInfoDTO info = new ValidationRuleSettingInfoDTO();
                        info.setFieldName(tRegexRule.getFieldId2());
                        info.setCurrencyType(tRegexRule.getCurrencyType());
                        info.setPattern(pattern);
                        info.setValidationMsg(tRegexRule.getValidationMsg());
                        info.setMinLength(tRegexRule.getMinLength());
                        info.setMaxLength(tRegexRule.getMaxLength());
                        info.setFixedLength(tRegexRule.getFixedLength());
                        resultList.add(info);
                    }
                }
            });
        }
        return resultList;
    }

    private SupplierTemplate getDefaultTemplate() {
        final SupplierTemplate moduleTemplate = supplierTemplateService.getOne(
                new LambdaQueryWrapper<SupplierTemplate>().eq(SupplierTemplate::getTemplateCode, "default"), false);
        if (Objects.isNull(moduleTemplate)) {
            return null;
        }
        return moduleTemplate;
    }

    /**
     * 获取正则字符串
     * @param regexRuleId 规则ID
     * @return 正则字符串
     */
    private String getRegex(Long regexRuleId) {
        if (regexRuleId == null) return null;
        List<String> patternList = iTRegexCharacterRelationService.getPattern(regexRuleId);
        if (CollectionUtil.isEmpty(patternList)) return null;
        return String.join("", patternList);
    }
}
