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

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.web.modules.industryservice.domain.BizYakHealthSourceRecord;
import com.ruoyi.web.modules.industryservice.domain.dto.YakDiseaseWarningDto;
import com.ruoyi.web.modules.industryservice.mapper.BizYakHealthSourceRecordMapper;
import com.ruoyi.web.modules.industryservice.support.YakDiseaseWarningAnalysisRules;

/**
 * 对健康源未分析记录执行集中判断并生成疾病预警。
 */
@Service
public class YakDiseaseWarningAnalyzer
{
    private static final SimpleDateFormat DAY_KEY = createDayKeyFormat();

    @Autowired
    private BizYakHealthSourceRecordMapper healthSourceRecordMapper;

    @Autowired
    private YakDiseaseWarningSyncTxService warningSyncTxService;

    @Transactional(rollbackFor = Exception.class)
    public int analyzeAndGenerate(Date syncTime)
    {
        int created = 0;
        created += analyzeQuarantine(syncTime);
        created += analyzeDiagnosis(syncTime);
        markBreedingAnalyzed();
        return created;
    }

    private int analyzeQuarantine(Date syncTime)
    {
        List<BizYakHealthSourceRecord> rows = healthSourceRecordMapper
                .selectUnanalyzedByType(YakDiseaseWarningAnalysisRules.RECORD_TYPE_QUARANTINE);
        return analyzeConcentration(rows, syncTime, true);
    }

    private int analyzeDiagnosis(Date syncTime)
    {
        List<BizYakHealthSourceRecord> rows = healthSourceRecordMapper
                .selectUnanalyzedByType(YakDiseaseWarningAnalysisRules.RECORD_TYPE_DIAGNOSIS);
        return analyzeConcentration(rows, syncTime, false);
    }

    private int analyzeConcentration(List<BizYakHealthSourceRecord> rows, Date syncTime, boolean quarantineMode)
    {
        if (rows == null || rows.isEmpty())
        {
            return 0;
        }
        Map<String, List<BizYakHealthSourceRecord>> groups = groupByRegionDay(rows);
        int created = 0;
        for (Map.Entry<String, List<BizYakHealthSourceRecord>> entry : groups.entrySet())
        {
            List<BizYakHealthSourceRecord> group = entry.getValue();
            List<BizYakHealthSourceRecord> hits = new ArrayList<>();
            if (quarantineMode)
            {
                for (BizYakHealthSourceRecord row : group)
                {
                    if (YakDiseaseWarningAnalysisRules.isAbnormalQuarantineResult(row.getQuarantineResult()))
                    {
                        hits.add(row);
                    }
                }
            }
            else
            {
                hits.addAll(group);
            }
            if (hits.size() >= YakDiseaseWarningAnalysisRules.CONCENTRATION_THRESHOLD)
            {
                YakDiseaseWarningDto dto = buildWarningDto(group, hits, syncTime, quarantineMode);
                if (warningSyncTxService.persistAlert(dto, syncTime))
                {
                    created++;
                }
            }
            markAnalyzed(group);
        }
        return created;
    }

    private void markBreedingAnalyzed()
    {
        List<BizYakHealthSourceRecord> rows = healthSourceRecordMapper
                .selectUnanalyzedByType(YakDiseaseWarningAnalysisRules.RECORD_TYPE_BREEDING);
        markAnalyzed(rows);
    }

    private void markAnalyzed(List<BizYakHealthSourceRecord> rows)
    {
        if (rows == null || rows.isEmpty())
        {
            return;
        }
        List<Long> ids = new ArrayList<>(rows.size());
        for (BizYakHealthSourceRecord row : rows)
        {
            ids.add(row.getId());
        }
        healthSourceRecordMapper.markAnalyzedByIds(ids);
    }

    private YakDiseaseWarningDto buildWarningDto(List<BizYakHealthSourceRecord> group,
            List<BizYakHealthSourceRecord> hits, Date syncTime, boolean quarantineMode)
    {
        BizYakHealthSourceRecord anchor = hits.get(0);
        String region = StringUtils.isNotEmpty(anchor.getRegionKey()) ? anchor.getRegionKey() : "未知地区";
        String day = dayKey(anchor.getRecordTime());
        YakDiseaseWarningDto dto = new YakDiseaseWarningDto();
        dto.setPastureName(anchor.getFarmName());
        dto.setAlertTime(latestTime(hits, syncTime));
        dto.setWarningType(quarantineMode ? YakDiseaseWarningAnalysisRules.WARNING_TYPE_QUARANTINE
                : YakDiseaseWarningAnalysisRules.WARNING_TYPE_DIAGNOSIS);
        dto.setAlertMessage(buildConcentrationMessage(quarantineMode, region, day, hits.size()));
        return dto;
    }

    private static String buildConcentrationMessage(boolean quarantineMode, String region, String day, int count)
    {
        String typeLabel = quarantineMode ? "检疫结果异常或阳性" : "发病";
        return day + " " + region + " 地区" + typeLabel + "记录集中（" + count + "条），触发健康预警。";
    }

    private static Map<String, List<BizYakHealthSourceRecord>> groupByRegionDay(List<BizYakHealthSourceRecord> rows)
    {
        Map<String, List<BizYakHealthSourceRecord>> groups = new LinkedHashMap<>();
        for (BizYakHealthSourceRecord row : rows)
        {
            String key = StringUtils.nvl(row.getRegionKey(), "") + "|" + dayKey(row.getRecordTime());
            groups.computeIfAbsent(key, k -> new ArrayList<>()).add(row);
        }
        return groups;
    }

    private static Date latestTime(List<BizYakHealthSourceRecord> hits, Date fallback)
    {
        Date latest = fallback;
        for (BizYakHealthSourceRecord row : hits)
        {
            if (row.getRecordTime() != null && (latest == null || row.getRecordTime().after(latest)))
            {
                latest = row.getRecordTime();
            }
        }
        return latest != null ? latest : fallback;
    }

    private static String dayKey(Date time)
    {
        if (time == null)
        {
            return "";
        }
        synchronized (DAY_KEY)
        {
            return DAY_KEY.format(time);
        }
    }

    private static SimpleDateFormat createDayKeyFormat()
    {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        df.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
        return df;
    }
}
