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

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.web.modules.industryservice.domain.dto.BreedingIndustryYakSnapshot;
import com.ruoyi.web.modules.industryservice.domain.vo.BreedingIndustryAgeBandVo;
import com.ruoyi.web.modules.industryservice.domain.vo.BreedingIndustryDashboardVo;
import com.ruoyi.web.modules.industryservice.domain.vo.BreedingIndustryDegradationStatVo;
import com.ruoyi.web.modules.industryservice.domain.vo.BreedingIndustryGrasslandVo;
import com.ruoyi.web.modules.industryservice.domain.vo.BreedingIndustryInventoryChangeVo;
import com.ruoyi.web.modules.industryservice.domain.vo.BreedingIndustryOverviewVo;
import com.ruoyi.web.modules.industryservice.mapper.BreedingIndustryStatsMapper;
import com.ruoyi.web.modules.industryservice.service.IBreedingIndustryDashboardService;
import com.ruoyi.web.modules.industryservice.support.BreedingIndustryCalculator;
import com.ruoyi.web.modules.industryservice.support.BreedingIndustryPastureScope;
import com.ruoyi.web.modules.industryservice.support.BreedingIndustryRules;
import com.ruoyi.web.modules.industryservice.support.GrasslandRules;

@Service
public class BreedingIndustryDashboardServiceImpl implements IBreedingIndustryDashboardService
{
    private static final DateTimeFormatter STAT_DATE_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    private static final String[] DEGRADATION_LABELS = {
            "", "未退化", "轻度", "中度", "重度", "极重度"
    };

    @Autowired
    private BreedingIndustryStatsMapper breedingIndustryStatsMapper;

    @Autowired
    private BreedingIndustryPastureScope breedingIndustryPastureScope;

    @Override
    public BreedingIndustryDashboardVo loadDashboard(boolean forceRefresh)
    {
        try
        {
            LocalDate statDate = LocalDate.now(ZoneId.of(BreedingIndustryRules.ZONE_SHANGHAI));
            List<Long> allowedPastureIds = breedingIndustryPastureScope.resolveAllowedPastureIds();
            BreedingIndustryDashboardVo dashboard = new BreedingIndustryDashboardVo();
            dashboard.setStatDate(statDate.format(STAT_DATE_FMT));
            dashboard.setStatYear(statDate.getYear());

            BreedingIndustryOverviewVo overview = new BreedingIndustryOverviewVo();
            fillGrasslandOverview(overview);
            dashboard.setOverview(overview);

            BreedingIndustryInventoryChangeVo inventoryChange = new BreedingIndustryInventoryChangeVo();
            List<BreedingIndustryAgeBandVo> ageStructure = buildEmptyAgeStructure();
            if (allowedPastureIds.isEmpty())
            {
                overview.setInventoryTotal(0);
                overview.setAnnualOutbound(0);
                overview.setWarningYakCount(0);
                overview.setPastureCount(0);
                inventoryChange.setBullCount(0);
                inventoryChange.setCowCount(0);
                inventoryChange.setUnknownGenderCount(0);
                inventoryChange.setMonthlyTrend(Collections.emptyList());
            }
            else
            {
                Date yearStart = toDate(statDate.withDayOfYear(1));
                Date statDateEnd = toDateEndOfDay(statDate);
                Date statDateOnly = toDate(statDate);

                overview.setPastureCount(breedingIndustryStatsMapper.countPastureInScope(allowedPastureIds));
                overview.setInventoryTotal(breedingIndustryStatsMapper.countInventory(allowedPastureIds));
                overview.setAnnualOutbound(
                        breedingIndustryStatsMapper.countAnnualOutbound(allowedPastureIds, yearStart, statDateEnd));
                overview.setWarningYakCount(
                        breedingIndustryStatsMapper.countWarningYak(allowedPastureIds, yearStart, statDateEnd));

                List<BreedingIndustryYakSnapshot> snapshots =
                        breedingIndustryStatsMapper.selectYakSnapshotsInScope(allowedPastureIds);
                if (snapshots == null)
                {
                    snapshots = Collections.emptyList();
                }
                int bull = 0;
                int cow = 0;
                for (BreedingIndustryYakSnapshot snapshot : snapshots)
                {
                    if (!BreedingIndustryCalculator.countsAsCurrentInventory(snapshot))
                    {
                        continue;
                    }
                    String gender = BreedingIndustryCalculator.normalizeGender(snapshot.getGender());
                    if (BreedingIndustryRules.GENDER_BULL.equals(gender))
                    {
                        bull++;
                    }
                    else if (BreedingIndustryRules.GENDER_COW.equals(gender))
                    {
                        cow++;
                    }
                }
                int total = overview.getInventoryTotal();
                inventoryChange.setBullCount(bull);
                inventoryChange.setCowCount(cow);
                inventoryChange.setUnknownGenderCount(Math.max(0, total - bull - cow));
                inventoryChange.setMonthlyTrend(BreedingIndustryCalculator.buildMonthlyTrend(snapshots, statDate));

                Map<String, Integer> bandCounts = BreedingIndustryCalculator.countAgeBands(snapshots, statDate);
                ageStructure = BreedingIndustryCalculator.buildAgeStructure(bandCounts, total);
            }
            dashboard.setInventoryChange(inventoryChange);
            dashboard.setAgeStructure(ageStructure);
            dashboard.setGrassland(buildGrasslandVo(overview.getGrasslandCount()));
            return dashboard;
        }
        catch (Exception ex)
        {
            throw new ServiceException(BreedingIndustryRules.MSG_LOAD_FAILED);
        }
    }

    private void fillGrasslandOverview(BreedingIndustryOverviewVo overview)
    {
        int grasslandCount = breedingIndustryStatsMapper.countGrassland();
        overview.setGrasslandCount(grasslandCount);
        BigDecimal area = breedingIndustryStatsMapper.sumGrasslandAreaMu();
        overview.setGrasslandAreaMu(area != null ? area.setScale(2, RoundingMode.HALF_UP) : BigDecimal.ZERO);
    }

    private BreedingIndustryGrasslandVo buildGrasslandVo(int grasslandTotal)
    {
        LocalDate statDate = LocalDate.now(ZoneId.of(BreedingIndustryRules.ZONE_SHANGHAI));
        BreedingIndustryGrasslandVo vo = new BreedingIndustryGrasslandVo();
        vo.setAvailableCount(breedingIndustryStatsMapper.countAvailableGrassland());
        vo.setInUseCount(breedingIndustryStatsMapper.countInUseGrassland(toDate(statDate)));
        vo.setDegradationStats(buildDegradationStats(grasslandTotal));
        return vo;
    }

    private List<BreedingIndustryDegradationStatVo> buildDegradationStats(int grasslandTotal)
    {
        List<BreedingIndustryDegradationStatVo> grouped = breedingIndustryStatsMapper.selectDegradationGroupCounts();
        Map<Integer, Integer> countByLevel = new HashMap<>();
        if (grouped != null)
        {
            for (BreedingIndustryDegradationStatVo row : grouped)
            {
                countByLevel.put(row.getDegradationLevel(), row.getCount());
            }
        }
        List<BreedingIndustryDegradationStatVo> result = new ArrayList<>();
        for (int level = GrasslandRules.DEGRADATION_NONE; level <= GrasslandRules.DEGRADATION_EXTREME; level++)
        {
            int count = countByLevel.getOrDefault(level, 0);
            BreedingIndustryDegradationStatVo stat = new BreedingIndustryDegradationStatVo();
            stat.setDegradationLevel(level);
            stat.setDegradationLabel(DEGRADATION_LABELS[level]);
            stat.setCount(count);
            stat.setRatio(BreedingIndustryCalculator.ratioPercent(count, grasslandTotal));
            result.add(stat);
        }
        return result;
    }

    private static List<BreedingIndustryAgeBandVo> buildEmptyAgeStructure()
    {
        return BreedingIndustryCalculator.buildAgeStructure(Collections.emptyMap(), 0);
    }

    private static Date toDate(LocalDate localDate)
    {
        return Date.from(localDate.atStartOfDay(ZoneId.of(BreedingIndustryRules.ZONE_SHANGHAI)).toInstant());
    }

    private static Date toDateEndOfDay(LocalDate localDate)
    {
        return Date.from(localDate.atTime(23, 59, 59)
                .atZone(ZoneId.of(BreedingIndustryRules.ZONE_SHANGHAI)).toInstant());
    }
}
