package com.hotwj.platform.resourceManagement.vehicleManagement.utils;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 车辆业务计算工具类
 * 支持：年审检测 (Annual Inspection) & 二级维护 (Secondary Maintenance)
 */
public class VehicleUtils {

    /**
     * 计算车辆【年审】状态
     *
     * @param rules              qynjpz表规则
     * @param registrationDate   行驶证注册日期
     * @param lastInspectionDate 最近一次年审日期 (clxx_nstim)
     */
    public static InspectionResult calculateInspectionStatus(
            List<AnnualInspectionRule> rules,
            LocalDate registrationDate,
            LocalDate lastInspectionDate) {
        return coreCalculate(rules, registrationDate, lastInspectionDate);
    }

    /**
     * 计算车辆【二级维护】状态
     *
     * @param rules               qywhpz表规则
     * @param registrationDate    行驶证注册日期
     * @param lastMaintenanceDate 最近一次维护日期 (clxx_whsj)
     */
    public static InspectionResult calculateMaintenanceStatus(
            List<AnnualInspectionRule> rules,
            LocalDate registrationDate,
            LocalDate lastMaintenanceDate) {
        return coreCalculate(rules, registrationDate, lastMaintenanceDate);
    }

    /**
     * 核心计算逻辑 (由原 PHP 函数 clxx_ns 和 clxx_wh 抽象而来)
     */
    private static InspectionResult coreCalculate(
            List<AnnualInspectionRule> rules,
            LocalDate registrationDate,
            LocalDate lastBusinessDate) {

        // 1. 基础校验：静默返回 null，防止列表查询因单条数据缺失崩溃
        if (registrationDate == null || rules == null || rules.isEmpty()) {
            return null;
        }

        LocalDate today = LocalDate.now();

        // 2. 自动解析免检期：匹配次数为 0 的规则阈值 (PHP 中的 $wl_0_jg)
        int initialGracePeriodYears = rules.stream()
                .filter(r -> r.getInspectionTimes() == 0)
                .map(AnnualInspectionRule::getIntervalYearThreshold)
                .findFirst()
                .orElse(0);

        // 3. 确定计算锚点：若无办理记录，则以“注册日期 + 免检年数”为起点
        LocalDate effectiveLastDate = (lastBusinessDate != null)
                ? lastBusinessDate
                : registrationDate.plusYears(initialGracePeriodYears);

        // 4. 排序规则：确保按年限从小到大匹配 (PHP 中的 order by qywhpz_jgtim+0 asc)
        List<AnnualInspectionRule> sortedRules = rules.stream()
                .sorted(Comparator.comparingInt(AnnualInspectionRule::getIntervalYearThreshold))
                .collect(Collectors.toList());

        // 5. 计算车龄：向下取整 (不到生日不算一岁)
        long vehicleAgeYears = ChronoUnit.YEARS.between(registrationDate, today);

        // 6. 匹配区间并计算
        for (AnnualInspectionRule rule : sortedRules) {
            if (vehicleAgeYears < rule.getIntervalYearThreshold()) {

                int timesPerYear = rule.getInspectionTimes();
                InspectionResult result = new InspectionResult();
                result.setInspectionTimes(timesPerYear);

                // 次数为 0 代表该区间免检/无需维护 (PHP 中的 yj_dj=6)
                if (timesPerYear <= 0) {
                    result.setWarningLevel(6);
                    return result;
                }

                // 计算周期：12个月 / 每年次数 (PHP 中的 $one_tear / $qynjpz_cs)
                int cycleMonths = 12 / timesPerYear;
                LocalDate nextDeadline = effectiveLastDate.plusMonths(cycleMonths);
                result.setNextInspectionDate(nextDeadline);

                // 7. 判定状态
                if (today.isBefore(nextDeadline)) {
                    // 未到期
                    long remainingDays = ChronoUnit.DAYS.between(today, nextDeadline);
                    result.setRemainingDays((int) remainingDays);
                    result.setOverdueDays(0);
                    result.setWarningLevel(determineWarningLevel((int) remainingDays));
                } else {
                    // 已到期/已逾期
                    long overdueDays = ChronoUnit.DAYS.between(nextDeadline, today);
                    result.setRemainingDays(0);
                    result.setOverdueDays((int) overdueDays);
                    result.setWarningLevel(1); // 红色预警
                }
                return result;
            }
        }
        return null;
    }

    private static int determineWarningLevel(int remainingDays) {
        if (remainingDays <= 5) return 1;
        if (remainingDays <= 10) return 2;
        if (remainingDays <= 20) return 3;
        if (remainingDays <= 30) return 4;
        return 5;
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class AnnualInspectionRule {
        private int intervalYearThreshold;
        private int inspectionTimes;
    }

    @Data
    public static class InspectionResult {
        private int warningLevel;
        private int remainingDays;
        /**
         * 逾期天数
         */
        private int overdueDays;
        private int inspectionTimes;
        private LocalDate nextInspectionDate;

        public String getWarningLevelDesc() {
            switch (this.warningLevel) {
                case 1:
                    return "一级预警";
                case 2:
                    return "二级预警";
                case 3:
                    return "三级预警";
                case 4:
                    return "四级预警";
                case 5:
                    return "";
                case 6:
                    return "";
                default:
                    return "未知状态";
            }
        }

        @Override
        public String toString() {
            return String.format("等级:%d, 剩余:%d天, 逾期:%d天, 下次日期:%s",
                    warningLevel, remainingDays, overdueDays, nextInspectionDate);
        }
    }
}
