from __future__ import annotations

from datetime import date, datetime, time
from typing import Any
from zoneinfo import ZoneInfo

from backend.data.contracts import ProviderResult

SHANGHAI = ZoneInfo("Asia/Shanghai")


def auction_phase(requested: str, trade_date: str, clock: datetime) -> str:
    if requested != clock.date().isoformat() or trade_date != clock.date().isoformat():
        return "archive"
    local = clock.time().replace(tzinfo=None)
    if local < time(9, 15):
        return "pending"
    if local < time(9, 25):
        return "observing"
    if local < time(9, 30):
        return "selection"
    return "finalized"


def decorate(
    payload: dict[str, Any],
    requested: str,
    phase: str,
    carried_forward: bool,
    message: str,
    current_available: bool = True,
) -> dict[str, Any]:
    return {
        **payload,
        "requested_date": requested,
        "phase": phase,
        "carried_forward": carried_forward,
        "message": message or str(payload.get("message") or ""),
        "current_available": current_available,
    }


def standard(payload: dict[str, Any], requested: str, message: str = "") -> dict[str, Any]:
    trade_date = str(payload.get("trade_date") or "")
    return {
        **payload,
        "requested_date": requested,
        "carried_forward": trade_date != requested,
        "message": message or str(payload.get("message") or ""),
    }


def empty_standard(requested: str, trade_date: str, message: str) -> dict[str, Any]:
    return {
        "requested_date": requested,
        "trade_date": trade_date,
        "observed_at": None,
        "state": None,
        "carried_forward": trade_date != requested,
        "message": message,
        "summary": {},
        "items": [],
        "combined": [],
        "ths": [],
        "dc": [],
    }


def empty_auction(
    requested: str, trade_date: str, phase: str, message: str
) -> dict[str, Any]:
    return {
        **empty_standard(requested, trade_date, message),
        "phase": phase,
        "current_available": False,
        "expectations": {"超预期": 0, "符合预期": 0, "低于预期": 0},
        "themes": {"carry": [], "new_themes": []},
        "amount_history": [],
        "focus_rows": [],
        "one_price_rows": [],
        "rows": [],
        "watchlist_rows": [],
        "watchlist_ready": False,
    }


def result(value: Any) -> ProviderResult | None:
    return value if isinstance(value, ProviderResult) else None


def rows(value: Any) -> tuple[dict[str, Any], ...]:
    provider_result = result(value)
    return provider_result.rows if provider_result else ()


def serialized_rows(value: Any) -> list[dict[str, Any]] | None:
    provider_result = result(value)
    return [dict(row) for row in provider_result.rows] if provider_result else None


def tuple_or_none(value: Any) -> tuple[dict[str, Any], ...] | None:
    if value is None:
        return None
    return tuple(dict(row) for row in value)


def valid_date(value: str) -> str:
    try:
        return date.fromisoformat(value).isoformat()
    except ValueError as exc:
        raise ValueError("日期格式无效") from exc


def clock(value: datetime | None) -> datetime:
    current = value or datetime.now(SHANGHAI)
    return (
        current.replace(tzinfo=SHANGHAI)
        if current.tzinfo is None
        else current.astimezone(SHANGHAI)
    )


def number(value: Any, default: float = 0.0) -> float:
    try:
        parsed = float(value)
        return parsed if parsed == parsed else default
    except (TypeError, ValueError):
        return default
