package com.zhyc.module.produce.bodyManage.service.impl;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

import com.zhyc.common.annotation.DataScope;
import com.zhyc.common.utils.DateUtils;
import com.zhyc.common.utils.SecurityUtils;
import com.zhyc.common.utils.StringUtils;
import com.zhyc.module.base.domain.BasSheep;
import com.zhyc.module.base.service.IBasSheepService;
import com.zhyc.module.produce.bodyManage.domain.ScBreastRating;
import com.zhyc.module.produce.bodyManage.mapper.ScBreastRatingMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.zhyc.module.produce.bodyManage.mapper.ScBodyMeasureMapper;
import com.zhyc.module.produce.bodyManage.domain.ScBodyMeasure;
import com.zhyc.module.produce.bodyManage.service.IScBodyMeasureService;

/**
 * 体尺测量Service业务层处理
 *
 * @author ruoyi
 * @date 2025-07-27
 */
@Service
public class ScBodyMeasureServiceImpl implements IScBodyMeasureService
{
    @Autowired
    private ScBodyMeasureMapper scBodyMeasureMapper;

    @Autowired
    private IBasSheepService basSheepService;

    @Autowired
    private ScBreastRatingMapper scBreastRatingMapper;

    /**
     * 查询体尺测量
     *
     * @param id 体尺测量主键
     * @return 体尺测量
     */
    @Override
    public ScBodyMeasure selectScBodyMeasureById(Long id)
    {
        return scBodyMeasureMapper.selectScBodyMeasureById(id);
    }

    /**
     * 查询体尺测量列表
     *
     * @param scBodyMeasure 体尺测量
     * @return 体尺测量
     */
    @Override
    @DataScope(deptAlias = "sm", userAlias = "sm")
    public List<ScBodyMeasure> selectScBodyMeasureList(ScBodyMeasure scBodyMeasure) {
        return scBodyMeasureMapper.selectScBodyMeasureList(scBodyMeasure,
                scBodyMeasure.getManageTagsList());
    }

    @Override
    public List<String> searchEarNumbers(String query) {
        return scBodyMeasureMapper.searchEarNumbers(query.trim());
    }

    /**
     * 新增体尺测量
     * 追根溯源原则：记录测量时刻的所有数据快照，后续羊只信息变化不影响历史记录
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertScBodyMeasure(ScBodyMeasure scBodyMeasure) {
        // 1. 耳号验证并获取羊只信息
        String manageTags = scBodyMeasure.getManageTags();
        if (StringUtils.isNotBlank(manageTags)) {
            BasSheep sheep = basSheepService.selectBasSheepByManageTags(manageTags.trim());
            if (sheep == null) {
                throw new RuntimeException("耳号不存在，请检查输入");
            }
            scBodyMeasure.setSheepId(sheep.getId());

            // 2. 固化测量时刻的基础信息（追根溯源）
            fillMeasureTimeSnapshot(scBodyMeasure, sheep);
        }

        // 3. 设置创建信息
        scBodyMeasure.setCreateTime(DateUtils.getNowDate());
        scBodyMeasure.setCreateBy(SecurityUtils.getUsername());

        // 4. 保存体尺测量记录
        int rows = scBodyMeasureMapper.insertScBodyMeasure(scBodyMeasure);

        // 5. 同步更新羊只当前体重（实时状态，可以更新）
        if (rows > 0 && scBodyMeasure.getCurrentWeight() != null) {
            BasSheep updateSheep = new BasSheep();
            updateSheep.setId(scBodyMeasure.getSheepId());
            updateSheep.setCurrentWeight(scBodyMeasure.getCurrentWeight());
            basSheepService.updateBasSheep(updateSheep);
        }

        return rows;
    }

    /**
     * 填充测量时刻的数据快照（追根溯源）
     * 所有字段基于测量日期计算，固化存储，不受后续数据变化影响
     */
    private void fillMeasureTimeSnapshot(ScBodyMeasure measure, BasSheep sheep) {
        Date measureDate = measure.getMeasureDate();
        if (measureDate == null) {
            measureDate = new Date(); // 如果未指定，默认当前日期
            measure.setMeasureDate(measureDate);
        }

        // ========== 1. 月龄（测量日期 - 出生日期）==========
        if (sheep.getBirthday() != null) {
            int monthAge = calculateMonthAge(sheep.getBirthday(), measureDate);
            measure.setMonthAge(monthAge);
        }

        // ========== 2. 体况评分 & 乳房评分（羊只档案当前值）==========
        measure.setBodyScore(sheep.getBody());           // 测量时的体况评分
        measure.setBreastScore(sheep.getBreast());       // 测量时的乳房评分

        // ========== 3. 时间相关天数（基于测量日期计算，非当前日期）==========

        // 配后天数 = 测量日期 - 配种日期
        if (sheep.getMatingDate() != null) {
            int postMatingDay = calculateDaysDiff(sheep.getMatingDate(), measureDate);
            measure.setPostMatingDay(postMatingDay);
        }

        // 怀孕天数 = 测量日期 - 配种日期（如果已配种）
        if (sheep.getMatingDate() != null) {
            int gestationDay = calculateDaysDiff(sheep.getMatingDate(), measureDate);
            measure.setGestationDay(gestationDay);
        }

        // 泌乳天数 = 测量日期 - 产羔日期（如果已产羔）
        if (sheep.getLambingDate() != null) {
            int lactationDay = calculateDaysDiff(sheep.getLambingDate(), measureDate);
            measure.setLactationDay(lactationDay);
        }

        // ========== 4. 乳房详细指标（取测量日期前最新的乳房评分记录）==========
        fillBreastRatingSnapshot(measure);
    }

    /**
     * 填充乳房评分快照（测量时刻的最新记录）
     */
    private void fillBreastRatingSnapshot(ScBodyMeasure measure) {
        if (measure.getSheepId() == null || measure.getMeasureDate() == null) {
            return;
        }

        // 查询该羊只在测量日期前最新的乳房评分记录
        ScBreastRating latestRating = scBreastRatingMapper
                .selectLatestBySheepIdBeforeDate(measure.getSheepId(), measure.getMeasureDate());

        if (latestRating != null) {
            measure.setBreastDepth(latestRating.getDepth());           // 乳房深度
            measure.setBreastPosition(latestRating.getPosition());     // 乳头位置
            measure.setBreastLength(latestRating.getLength());         // 乳头长度
            measure.setBreastAdbere(latestRating.getAdbere());         // 乳房附着
            measure.setBreastSpacing(latestRating.getSpacing());       // 乳房间隔度
            // 注意：breastScore 取羊只档案的当前值，不取历史评分记录的score
        }
    }

    /**
     * 计算月龄（精确到月）
     */
    private int calculateMonthAge(Date birthday, Date measureDate) {
        Calendar birthCal = Calendar.getInstance();
        birthCal.setTime(birthday);

        Calendar measureCal = Calendar.getInstance();
        measureCal.setTime(measureDate);

        int yearDiff = measureCal.get(Calendar.YEAR) - birthCal.get(Calendar.YEAR);
        int monthDiff = measureCal.get(Calendar.MONTH) - birthCal.get(Calendar.MONTH);

        int monthAge = yearDiff * 12 + monthDiff;

        // 如果测量日期的"日"小于出生日期的"日"，则不满整月，减1
        if (measureCal.get(Calendar.DAY_OF_MONTH) < birthCal.get(Calendar.DAY_OF_MONTH)) {
            monthAge--;
        }

        return Math.max(0, monthAge); // 确保不为负数
    }

    /**
     * 计算两个日期相差天数
     */
    private int calculateDaysDiff(Date startDate, Date endDate) {
        long diffMillis = endDate.getTime() - startDate.getTime();
        return (int) (diffMillis / (1000 * 60 * 60 * 24));
    }

    /**
     * 修改体尺测量
     * 注意：修改时不改变已固化的快照数据（月龄、评分等），只修改体尺测量值本身
     */
    @Override
    public int updateScBodyMeasure(ScBodyMeasure scBodyMeasure) {
        String manageTags = scBodyMeasure.getManageTags();
        if (StringUtils.isNotBlank(manageTags)) {
            BasSheep sheep = basSheepService.selectBasSheepByManageTags(manageTags.trim());
            if (sheep == null) {
                throw new RuntimeException("耳号不存在，请检查输入");
            }
            scBodyMeasure.setSheepId(sheep.getId());
        }

        // 修改时不同步更新体重，避免历史记录被污染
        // 如需修改体重，应通过专门的功能或重新新增记录

        return scBodyMeasureMapper.updateScBodyMeasure(scBodyMeasure);
    }

    /**
     * 批量删除体尺测量
     *
     * @param ids 需要删除的体尺测量主键
     * @return 结果
     */
    @Override
    public int deleteScBodyMeasureByIds(Long[] ids)
    {
        return scBodyMeasureMapper.deleteScBodyMeasureByIds(ids);
    }

    /**
     * 删除体尺测量信息
     *
     * @param id 体尺测量主键
     * @return 结果
     */
    @Override
    public int deleteScBodyMeasureById(Long id)
    {
        return scBodyMeasureMapper.deleteScBodyMeasureById(id);
    }

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