"""续费检查服务

检查即将到期的资产，生成提醒消息并通过通知渠道发送。
"""

from datetime import date, timedelta

from sqlmodel import Session, select

from app.core.config import settings
from app.models.asset import Asset, AssetStatus
from app.services import notification_service

# 已注销的资产不参与续费提醒
_SKIP_STATUS = {AssetStatus.CANCELLED}


def get_expiring_assets(session: Session, threshold_days: int) -> list:
    """返回 threshold_days 天内到期的资产列表 [(asset, days), ...]，按剩余天数升序

    性能优化：日期范围与状态过滤均下推到 SQL 层。
    """
    today = date.today()
    deadline = today + timedelta(days=threshold_days)
    assets = session.exec(
        select(Asset).where(
            Asset.expiry_date.is_not(None),
            Asset.expiry_date >= today,
            Asset.expiry_date <= deadline,
            Asset.status.notin_(_SKIP_STATUS),
        )
    ).all()
    expiring = [(asset, (asset.expiry_date - today).days) for asset in assets]
    expiring.sort(key=lambda x: x[1])
    return expiring


def build_renewal_message(expiring: list, threshold_days: int) -> str:
    """生成续费提醒消息（纯文本，兼容 Telegram/邮件）"""
    if not expiring:
        return ""
    lines = [f"⏰ 资产续费提醒（{threshold_days} 天内到期，共 {len(expiring)} 项）", ""]
    for asset, days in expiring:
        tag = "（已过期）" if days == 0 else f"（{days} 天后）"
        lines.append(f"• {asset.name} [{asset.provider}] {tag} 到期 {asset.expiry_date}")
    return "\n".join(lines)


def check_renewals(session: Session, threshold_days: int = None, send: bool = True) -> dict:
    """检查续费并（可选）发送提醒

    threshold_days: 提醒阈值天数，默认取配置 RENEWAL_THRESHOLD_DAYS
    send: 是否实际发送通知（False 时仅返回预览）
    """
    if threshold_days is None:
        threshold_days = settings.RENEWAL_THRESHOLD_DAYS

    expiring = get_expiring_assets(session, threshold_days)
    message = build_renewal_message(expiring, threshold_days)

    result = {
        "threshold_days": threshold_days,
        "expiring_count": len(expiring),
        "expiring": [
            {
                "name": asset.name,
                "provider": asset.provider,
                "days": days,
                "expiry_date": str(asset.expiry_date),
            }
            for asset, days in expiring
        ],
        "message": message,
    }

    if send and message:
        result["notifications"] = notification_service.notify(message)
    else:
        result["notifications"] = []
    return result
