package com.ruoyi.web.modules.industryservice.service.impl;

import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.web.modules.industryservice.domain.*;
import com.ruoyi.web.modules.industryservice.domain.vo.YakAssetDetailVo;
import com.ruoyi.web.modules.industryservice.domain.vo.YakAssetGrowthChartPointVo;
import com.ruoyi.web.modules.industryservice.domain.vo.YakAssetGrowthChartVo;
import com.ruoyi.web.modules.industryservice.domain.vo.YakAssetSyncResultVo;
import com.ruoyi.web.modules.industryservice.mapper.*;
import com.ruoyi.web.modules.industryservice.service.IBizYakAssetService;
import com.ruoyi.web.modules.industryservice.service.YakAssetSyncService;
import com.ruoyi.web.modules.industryservice.support.YakAssetRules;
import com.ruoyi.web.modules.industryservice.support.YakAssetValidation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;

@Service
public class BizYakAssetServiceImpl implements IBizYakAssetService
{
    @Autowired
    private BizYakAssetMapper bizYakAssetMapper;

    @Autowired
    private BizYakPhysioSeriesMapper physioSeriesMapper;

    @Autowired
    private BizYakGrowthRecordMapper growthRecordMapper;

    @Autowired
    private BizYakReproductionRecordMapper reproductionRecordMapper;

    @Autowired
    private BizYakFeedingRecordMapper feedingRecordMapper;

    @Autowired
    private BizYakPenRelMapper penRelMapper;

    @Autowired
    private BizYakBatchRelMapper batchRelMapper;

    @Autowired
    private YakAssetSyncService yakAssetSyncService;

    @Override
    public List<BizYakAsset> selectBizYakAssetList(BizYakAsset query)
    {
        if (query == null)
        {
            query = new BizYakAsset();
        }
        query.setKeyword(YakAssetValidation.trimKeyword(query.getKeyword()));
        YakAssetValidation.validateAssetStatus(query.getAssetStatus());
        return bizYakAssetMapper.selectBizYakAssetList(query);
    }

    @Override
    public YakAssetDetailVo selectDetailById(Long id)
    {
        BizYakAsset asset = requireActiveAsset(id);
        return buildDetail(asset);
    }

    @Override
    public YakAssetDetailVo selectDetailByYakNo(String yakNo)
    {
        if (StringUtils.isEmpty(yakNo))
        {
            throw new ServiceException("牦牛编号不能为空");
        }
        BizYakAsset asset = bizYakAssetMapper.selectBizYakAssetByYakNo(yakNo.trim());
        if (asset == null)
        {
            throw new ServiceException("档案不存在或已删除");
        }
        return buildDetail(asset);
    }

    @Override
    public List<BizYakPhysioSeries> selectPhysioChart(Long id, Integer days)
    {
        BizYakAsset asset = requireActiveAsset(id);
        int d = days == null ? YakAssetRules.DEFAULT_PHYSIO_DAYS : days;
        YakAssetValidation.validatePhysioDays(d);
        return physioSeriesMapper.selectChartByYakAssetId(asset.getId(), d);
    }

    @Override
    public YakAssetGrowthChartVo selectGrowthChart(Long id, String metric)
    {
        BizYakAsset asset = requireActiveAsset(id);
        String m = StringUtils.isEmpty(metric) ? YakAssetRules.METRIC_WEIGHT : metric.trim().toLowerCase();
        YakAssetValidation.validateGrowthMetric(m);
        List<BizYakGrowthRecord> rows = growthRecordMapper.selectByYakAssetId(asset.getId());
        YakAssetGrowthChartVo chart = new YakAssetGrowthChartVo();
        for (BizYakGrowthRecord row : rows)
        {
            BigDecimal value = resolveGrowthValue(row, m);
            if (value == null)
            {
                continue;
            }
            YakAssetGrowthChartPointVo point = new YakAssetGrowthChartPointVo();
            point.setDayAge(row.getDayAge());
            point.setValue(value);
            point.setCollectTime(row.getCollectTime());
            if (row.getDataKind() != null && row.getDataKind() == YakAssetRules.DATA_KIND_FORECAST)
            {
                chart.getForecast().add(point);
            }
            else
            {
                chart.getActual().add(point);
            }
        }
        return chart;
    }

    @Override
    public YakAssetSyncResultVo syncFromThirdParty()
    {
        return yakAssetSyncService.syncFromThirdParty();
    }

    private YakAssetDetailVo buildDetail(BizYakAsset asset)
    {
        Long yakAssetId = asset.getId();
        YakAssetDetailVo vo = new YakAssetDetailVo();
        vo.setAsset(asset);
        vo.setPhysioSeries(physioSeriesMapper.selectByYakAssetId(yakAssetId));
        vo.setGrowthRecords(growthRecordMapper.selectByYakAssetId(yakAssetId));
        vo.setReproductionRecords(reproductionRecordMapper.selectByYakAssetId(yakAssetId));
        vo.setFeedingRecords(feedingRecordMapper.selectByYakAssetId(yakAssetId));
        String yakNo = asset.getYakNo();
        List<BizYakPenRel> pens = penRelMapper.selectByYakAssetId(yakAssetId);
        for (BizYakPenRel pen : pens)
        {
            pen.setYakNo(yakNo);
        }
        vo.setPenRecords(pens);
        List<BizYakBatchRel> batches = batchRelMapper.selectByYakAssetId(yakAssetId);
        for (BizYakBatchRel batch : batches)
        {
            batch.setYakNo(yakNo);
        }
        vo.setBatchRecords(batches);
        return vo;
    }

    private BizYakAsset requireActiveAsset(Long id)
    {
        if (id == null)
        {
            throw new ServiceException("主键不能为空");
        }
        BizYakAsset asset = bizYakAssetMapper.selectBizYakAssetById(id);
        if (asset == null)
        {
            throw new ServiceException("档案不存在或已删除");
        }
        return asset;
    }

    private static BigDecimal resolveGrowthValue(BizYakGrowthRecord row, String metric)
    {
        switch (metric)
        {
            case YakAssetRules.METRIC_HEIGHT:
                return row.getHeightCm();
            case YakAssetRules.METRIC_CHEST:
                return row.getChestCm();
            case YakAssetRules.METRIC_LENGTH:
                return row.getLengthCm();
            case YakAssetRules.METRIC_WEIGHT:
            default:
                return row.getWeightKg();
        }
    }
}
