package com.zhyc.module.base.service.impl;

import com.zhyc.module.base.domain.BreedRamFile;
import com.zhyc.module.base.domain.SheepFile;
import com.zhyc.module.base.mapper.SheepFileMapper;
import com.zhyc.module.base.service.IBreedRamFileService;
import com.zhyc.module.base.service.ISheepFileService;
import org.springframework.beans.factory.annotation.Autowired;
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;

/**
 * 羊只档案Service业务层处理
 * * @author wyt
 * @date 2025-07-13
 */
@Service
public class SheepFileServiceImpl implements ISheepFileService {
    @Autowired
    private SheepFileMapper sheepFileMapper;

    @Autowired
    private IBreedRamFileService breedRamFileService;

    /**
     * 查询羊只档案
     */
    @Override
    public SheepFile selectSheepFileById(Long id) {
        return sheepFileMapper.selectSheepFileById(id);
    }

    /**
     * 查询羊只档案列表
     */
    @Override
    public List<SheepFile> selectSheepFileList(SheepFile sheepFile) {
        return sheepFileMapper.selectSheepFileList(sheepFile);
    }

    /**
     * 新增：模糊搜索耳号实现
     */
    @Override
    public List<String> searchEarNumbers(String query) {
        return sheepFileMapper.searchEarNumbers(query);
    }

    @Override
    public SheepFile selectBasSheepByManageTags(String tags) {
        return sheepFileMapper.selectSheepByManageTags(tags);
    }

    @Override
    public List<Map<String, Object>> countBySheepType() {
        return sheepFileMapper.countBySheepType();
    }

    @Override
    public List<Map<String, Object>> countByBreedStatus() {
        return sheepFileMapper.countByBreedStatus();
    }

    @Override
    public List<Map<String, Object>> countByVariety() {
        return sheepFileMapper.countByVariety();
    }

    @Override
    public List<Map<String, Object>> countParityOfLactation() {
        return sheepFileMapper.countParityOfLactation();
    }

    @Override
    public Long countInGroup() { return sheepFileMapper.countInGroup(); }

    /**
     * 获取指定字段的唯一值列表
     */
    @Override
    public List<String> getFieldValues(String fieldName) {
        // 第一步：安全性验证 - 防止SQL注入攻击
        if (!isValidFieldName(fieldName)) {
            throw new IllegalArgumentException("非法的字段名: " + fieldName + "，请检查字段名是否正确");
        }

        // 调用Mapper
        // 注意：这里假设 Mapper 中有 selectFieldValues 方法
        // 如果你的 Mapper XML 中 id 是 selectFieldValues，请确保 Mapper 接口一致
        return sheepFileMapper.selectFieldValues(fieldName);
    }

    /**
     * 核心修复：复杂条件查询
     * 必须调用 Mapper 中对应的 XML 方法 (selectSheepFileListByCondition)
     * 并且传递 sheepFile 对象以启用 <foreach> 列表查询
     */
    @Override
    public List<SheepFile> selectSheepFileListByCondition(Map<String, Object> params, SheepFile sheepFile) {
        // 1. 验证并处理自定义参数 (驼峰转下划线、安全检查)
        Map<String, Object> safeConditions = processConditions(params);

        // 2. 调用 Mapper
        // 这里必须使用与 XML 中 <select id="selectSheepFileListByCondition"> 对应的方法
        return sheepFileMapper.selectSheepFileListByCondition(safeConditions, sheepFile);
    }

    @Override
    @Transactional
    public int insertSheepFile(SheepFile sheepFile) {
        // int rows = sheepFileMapper.insertSheepFile(sheepFile);
        // if (rows > 0) { syncToBreedRamFile(sheepFile); }
        // return rows;
        return 0;
    }

    @Override
    @Transactional
    public int updateSheepFile(SheepFile sheepFile) {
        // int rows = sheepFileMapper.updateSheepFile(sheepFile);
        // if (rows > 0) { syncToBreedRamFile(sheepFile); }
        // return rows;
        return 0;
    }

    /**
     * 处理条件参数，确保安全
     */
    private Map<String, Object> processConditions(Map<String, Object> params) {
        if (params == null || params.isEmpty()) {
            return new HashMap<>();
        }

        Map<String, Object> safeParams = new HashMap<>();

        for (Map.Entry<String, Object> entry : params.entrySet()) {
            String fieldName = entry.getKey();
            Object value = entry.getValue();

            // 将前端字段名转换为数据库字段名 (例如: fatherManageTags -> father_manage_tags)
            // 这对于 XML 中的 ${key} = #{value} 至关重要
            String dbFieldName = convertToDbFieldName(fieldName);

            // 验证字段名是否安全
            if (isValidFieldName(dbFieldName)) {
                // 处理值
                Object safeValue = value;
                if (value != null) {
                    String strValue = value.toString();

                    // 特殊处理范围条件：确保数字值的安全性
                    if (strValue.startsWith("GT:") || strValue.startsWith("LT:") ||
                            strValue.startsWith("GE:") || strValue.startsWith("LE:")) {
                        String numPart = strValue.substring(3);
                        // 验证数字部分是否安全
                        if (isNumeric(numPart)) {
                            safeValue = strValue;
                        } else {
                            continue;
                        }
                    } else {
                        safeValue = strValue;
                    }
                }
                safeParams.put(dbFieldName, safeValue);
            }
        }

        return safeParams;
    }

    /**
     * 判断字符串是否为数字
     */
    private boolean isNumeric(String str) {
        if (str == null || str.isEmpty()) {
            return false;
        }
        try {
            Double.parseDouble(str);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    /**
     * 将前端字段名转换为数据库字段名
     */
    private String convertToDbFieldName(String fieldName) {
        // 将驼峰命名转换为下划线命名
        return fieldName.replaceAll("([a-z])([A-Z])", "$1_$2").toLowerCase();
    }


    /**
     * 扩展字段名白名单验证
     */
    private boolean isValidFieldName(String fieldName) {
        // 字段白名单
        String[] allowedFields = {
                "id", "bs_manage_tags", "electronic_tags", "dr_ranch", "sheepfold_name", "variety", "family",
                "name", "gender", "birthday", "day_age", "month_age", "parity", "birth_weight", "weaning_date",
                "status_id", "weaning_weight", "current_weight", "weaning_day_age", "weaning_daily_gain", "breed",
                "father_manage_tags", "mother_manage_tags", "receptor_manage_tags", "grandfather_manage_tags",
                "grandmother_manage_tags", "maternal_grandfather_manage_tags", "maternal_grandmother_manage_tags",
                "mating_date", "mating_type_id", "preg_date", "lambing_date", "lambing_day", "mating_day",
                "gestation_day", "expected_date", "post_lambing_day", "lactation_day", "anestrous_day",
                "mating_counts", "mating_total", "miscarriage_counts", "comment", "controlled", "body", "breast",
                "source", "source_date", "source_ranch", "update_by", "update_time", "create_by", "create_time"
        };

        for (String allowedField : allowedFields) {
            if (allowedField.equals(fieldName)) {
                return true;
            }
        }

        return false;
    }


    /**
     * 同步公羊数据到种公羊档案表
     */
    private void syncToBreedRamFile(SheepFile sheepFile) {
        try {
            BreedRamFile existingRam = breedRamFileService.selectBreedRamFileByOrdinaryEarNumber(
                    sheepFile.getBsManageTags()
            );

            if (existingRam != null) {
                BreedRamFile updateRam = convertToBreedRamFile(sheepFile);
                updateRam.setId(existingRam.getId());
                breedRamFileService.updateBreedRamFile(updateRam);
            } else {
                BreedRamFile newRam = convertToBreedRamFile(sheepFile);
                breedRamFileService.insertBreedRamFile(newRam);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private BreedRamFile convertToBreedRamFile(SheepFile sheepFile) {
        BreedRamFile breedRamFile = new BreedRamFile();

        breedRamFile.setOrdinaryEarNumber(sheepFile.getBsManageTags());
        breedRamFile.setRanchId(sheepFile.getRanchId());
        breedRamFile.setRanchName(sheepFile.getDrRanch());
        breedRamFile.setSheepfoldId(sheepFile.getSheepfoldId());
        breedRamFile.setSheepfoldName(sheepFile.getSheepfoldName());
        breedRamFile.setElectronicTags(sheepFile.getElectronicTags());
        breedRamFile.setVarietyId(sheepFile.getVarietyId());
        breedRamFile.setVariety(sheepFile.getVariety());
        breedRamFile.setSheepCategory(sheepFile.getName());
        breedRamFile.setBirthday(sheepFile.getBirthday());

        if (sheepFile.getBirthWeight() != null) breedRamFile.setBirthWeight(BigDecimal.valueOf(sheepFile.getBirthWeight()));
        breedRamFile.setWeaningDate(sheepFile.getWeaningDate());
        breedRamFile.setWeaningDayAge(sheepFile.getWeaningDayAge());
        if (sheepFile.getWeaningWeight() != null) breedRamFile.setWeaningWeight(BigDecimal.valueOf(sheepFile.getWeaningWeight()));
        if (sheepFile.getWeaningDailyGain() != null) breedRamFile.setWeaningDailyGain(BigDecimal.valueOf(sheepFile.getWeaningDailyGain()));
        if (sheepFile.getCurrentWeight() != null) breedRamFile.setCurrentWeight(BigDecimal.valueOf(sheepFile.getCurrentWeight()));

        breedRamFile.setFatherNumber(sheepFile.getFatherManageTags());
        breedRamFile.setMotherNumber(sheepFile.getMotherManageTags());
        breedRamFile.setGrandfatherNumber(sheepFile.getGrandfatherManageTags());
        breedRamFile.setGrandmotherNumber(sheepFile.getGrandmotherManageTags());
        breedRamFile.setMaternalGrandfatherNumber(sheepFile.getMaternalGrandfatherManageTags());
        breedRamFile.setMaternalGrandmotherNumber(sheepFile.getMaternalGrandmotherManageTags());

        breedRamFile.setCreateBy(sheepFile.getCreateBy());
        breedRamFile.setCreateTime(sheepFile.getCreateTime());
        breedRamFile.setUpdateBy(sheepFile.getUpdateBy());
        breedRamFile.setUpdateTime(sheepFile.getUpdateTime());
        breedRamFile.setIsDelete(sheepFile.getIsDelete());

        return breedRamFile;
    }
}