from __future__ import annotations

import secrets
from datetime import date, datetime
from typing import Any

from backend.bootstrap.config import validate_text
from backend.database.repositories import AlertRepository


class AlertService:
    def __init__(self, repository: AlertRepository) -> None:
        self.repository = repository

    def create_manual(self, user_id: int, payload: dict[str, Any]) -> int:
        title = validate_text(payload.get("title"), "提醒标题", 80, required=True)
        content = validate_text(payload.get("content"), "提醒内容", 500)
        code = validate_text(payload.get("code"), "股票代码", 12)
        available_date = self.calendar_date(
            str(payload.get("remind_date") or date.today().isoformat())
        )
        return self.repository.save_alert(
            user_id=user_id,
            kind="manual",
            title=title,
            content=content,
            available_date=available_date,
            code=code,
            dedupe_key=f"manual:{secrets.token_hex(12)}",
        )

    def sync_strategy_tracking(self, user_id: int, tracking: dict[str, Any]) -> int:
        synced = 0
        today = date.today().strftime("%Y%m%d")
        for batch in tracking.get("batches") or []:
            items = batch.get("items") or []
            summary = batch.get("summary") or {}
            if not items:
                continue
            run_id = int(batch.get("run_id") or 0)
            strategy_name = str(batch.get("strategy_name") or "选股策略")
            observed = int(summary.get("observed") or 0)
            completed = int(summary.get("completed") or 0)
            if observed:
                win_rate = summary.get("t1_win_rate")
                suffix = f"，当前红盘率 {win_rate:.1f}%" if win_rate is not None else ""
                self.repository.save_alert(
                    user_id, "strategy_t1", f"{strategy_name} 已有 T+1 反馈",
                    f"{observed}/{len(items)} 只标的已有首日表现{suffix}。",
                    today, "", f"strategy:{run_id}:t1",
                )
                synced += 1
            if completed == len(items):
                average = summary.get("average_t5")
                suffix = f"，平均收益 {average:+.2f}%" if average is not None else ""
                self.repository.save_alert(
                    user_id, "strategy_t5", f"{strategy_name} 五日跟踪完成",
                    f"本批 {len(items)} 只标的已完成 T+5 跟踪{suffix}。",
                    today, "", f"strategy:{run_id}:t5",
                )
                synced += 1
        return synced

    def list_alerts(
        self, user_id: int, status: str = "all", as_of: str = ""
    ) -> dict[str, Any]:
        if status not in {"all", "unread"}:
            raise ValueError("提醒筛选不支持。")
        compact_date = self.calendar_date(as_of or date.today().isoformat())
        items = self.repository.list_alerts(user_id, compact_date, status == "unread")
        for item in items:
            item["due"] = str(item.get("available_date") or "") <= compact_date
        return {
            "items": items,
            "unread_count": self.repository.count_unread_alerts(user_id, compact_date),
            "as_of": compact_date,
        }

    def mark_read(self, user_id: int, alert_id: int) -> bool:
        return self.repository.mark_alert_read(user_id, alert_id)

    def mark_all_read(self, user_id: int, as_of: str) -> int:
        return self.repository.mark_all_alerts_read(user_id, as_of)

    def delete(self, user_id: int, alert_id: int) -> bool:
        return self.repository.delete_alert(user_id, alert_id)

    @staticmethod
    def calendar_date(value: str) -> str:
        compact = value.replace("-", "").strip()
        try:
            parsed = datetime.strptime(compact, "%Y%m%d")
        except ValueError as exc:
            raise ValueError("提醒日期格式应为 YYYY-MM-DD。") from exc
        return parsed.strftime("%Y%m%d")
