package com.usky.vpp.util;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.usky.vpp.domain.VppContract;

import java.time.LocalDate;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * 合同状态工具：根据生效/到期日期自动解析生命周期状态
 */
public final class VppContractStatusHelper {

    public static final int DRAFT = 0;
    public static final int AUDITING = 1;
    public static final int PENDING = 2;
    public static final int EFFECTIVE = 3;
    public static final int REJECTED = 4;
    public static final int EXPIRED = 5;
    public static final int TERMINATED = 6;
    /** 查询专用：即将到期（近三个月内过期，非落库状态） */
    public static final int UPCOMING_EXPIRE = 7;

    private static final Set<Integer> MANUAL_STATUSES = new HashSet<>(Arrays.asList(
            DRAFT, AUDITING, REJECTED, TERMINATED
    ));

    private VppContractStatusHelper() {
    }

    /**
     * 根据生效/到期日期解析合同状态；草稿、审核中、已驳回、已终止保持原状态不变。
     */
    public static Integer resolve(Integer storedStatus, LocalDate effectiveDate, LocalDate expireDate) {
        if (storedStatus != null && MANUAL_STATUSES.contains(storedStatus)) {
            return storedStatus;
        }
        return resolveByDates(effectiveDate, expireDate, storedStatus);
    }

    /**
     * 创建/更新时根据日期计算应写入的状态；未提供日期时回退为待生效。
     */
    public static Integer resolveForPersist(Integer requestedStatus, LocalDate effectiveDate, LocalDate expireDate) {
        if (requestedStatus != null && MANUAL_STATUSES.contains(requestedStatus)) {
            return requestedStatus;
        }
        Integer resolved = resolveByDates(effectiveDate, expireDate, requestedStatus);
        return resolved != null ? resolved : PENDING;
    }

    private static Integer resolveByDates(LocalDate effectiveDate, LocalDate expireDate, Integer fallback) {
        LocalDate today = LocalDate.now();
        if (expireDate != null && today.isAfter(expireDate)) {
            return EXPIRED;
        }
        if (effectiveDate != null) {
            return today.isBefore(effectiveDate) ? PENDING : EFFECTIVE;
        }
        return fallback;
    }

    /**
     * 分页筛选：将生命周期状态（待生效/已生效/已到期/即将到期）转换为日期条件。
     * <p>其中 {@link #UPCOMING_EXPIRE} 仅用于查询，不会写入数据库。</p>
     */
    public static void applyStatusFilter(LambdaQueryWrapper<VppContract> wrapper, Integer contractStatus) {
        if (contractStatus == null) {
            return;
        }
        LocalDate today = LocalDate.now();
        if (contractStatus == PENDING) {
            wrapper.and(w -> w.in(VppContract::getContractStatus, PENDING, EFFECTIVE, EXPIRED)
                    .gt(VppContract::getEffectiveDate, today)
                    .and(inner -> inner.isNull(VppContract::getExpireDate)
                            .or().ge(VppContract::getExpireDate, today)));
            return;
        }
        if (contractStatus == EFFECTIVE) {
            wrapper.and(w -> w.in(VppContract::getContractStatus, PENDING, EFFECTIVE, EXPIRED)
                    .le(VppContract::getEffectiveDate, today)
                    .and(inner -> inner.isNull(VppContract::getExpireDate)
                            .or().ge(VppContract::getExpireDate, today)));
            return;
        }
        if (contractStatus == EXPIRED) {
            wrapper.and(w -> w.in(VppContract::getContractStatus, PENDING, EFFECTIVE, EXPIRED)
                    .lt(VppContract::getExpireDate, today));
            return;
        }
        if (contractStatus == UPCOMING_EXPIRE) {
            LocalDate upcomingDeadline = today.plusMonths(3);
            wrapper.and(w -> w.in(VppContract::getContractStatus, PENDING, EFFECTIVE, EXPIRED)
                    .ge(VppContract::getExpireDate, today)
                    .le(VppContract::getExpireDate, upcomingDeadline));
            return;
        }
        wrapper.eq(VppContract::getContractStatus, contractStatus);
    }
}
