from __future__ import annotations

from dataclasses import asdict, dataclass
from typing import Any

from router.query_classifier import RouteDecisionFlags


@dataclass
class StoreSufficiencyResult:
    canonical_sufficient: bool
    feature_sufficient: bool
    risk_sufficient: bool
    freshness_ok: bool
    aggregate_level_ok: bool
    ranking_ready: bool
    explanation_ready: bool
    reason_codes: list[str]

    def to_dict(self) -> dict[str, Any]:
        return asdict(self)


def _to_float(value: Any, default: float = 0.0) -> float:
    try:
        return float(value)
    except (TypeError, ValueError):
        return default


def check_store_sufficiency(
    question_shape: RouteDecisionFlags,
    store_metadata: dict[str, Any],
) -> StoreSufficiencyResult:
    reason_codes: list[str] = []

    freshness_threshold_hours = _to_float(store_metadata.get("freshness_threshold_hours", 6.0), default=6.0)
    refresh_age = _to_float(store_metadata.get("refresh_age_hours", 0.0), default=0.0)
    feature_age = _to_float(store_metadata.get("feature_age_hours", refresh_age), default=refresh_age)
    risk_age = _to_float(store_metadata.get("risk_age_hours", refresh_age), default=refresh_age)

    canonical_semantic_coverage = _to_float(store_metadata.get("canonical_semantic_coverage", 0.0), default=0.0)
    canonical_relation_types = int(store_metadata.get("canonical_relation_types", 0))
    canonical_links_total = int(store_metadata.get("canonical_links_total", 0))
    canonical_entities_total = int(store_metadata.get("canonical_entities_total", 0))

    feature_ready = bool(store_metadata.get("feature_ready", False))
    risk_ready = bool(store_metadata.get("risk_ready", False))
    ranking_ready = bool(store_metadata.get("ranking_ready", False))
    aggregate_ready = bool(store_metadata.get("aggregate_ready", False))

    freshness_ok = refresh_age <= freshness_threshold_hours
    if question_shape.freshness_sensitive and not freshness_ok:
        reason_codes.append("refresh_stale")

    canonical_sufficient = (
        canonical_entities_total > 0
        and canonical_links_total > 0
        and canonical_semantic_coverage >= 0.85
        and canonical_relation_types >= 10
        and (freshness_ok or not question_shape.freshness_sensitive)
    )
    if not canonical_sufficient:
        reason_codes.append("canonical_not_sufficient")

    feature_sufficient = feature_ready and (
        feature_age <= freshness_threshold_hours or not question_shape.freshness_sensitive
    )
    if not feature_sufficient and question_shape.needs_anomaly_summary:
        reason_codes.append("feature_not_sufficient")

    risk_sufficient = risk_ready and (
        risk_age <= freshness_threshold_hours or not question_shape.freshness_sensitive
    )
    if not risk_sufficient and (question_shape.needs_anomaly_summary or question_shape.needs_ranking):
        reason_codes.append("risk_not_sufficient")

    if question_shape.needs_ranking:
        if not ranking_ready:
            reason_codes.append("ranking_not_ready")
    aggregate_level_ok = aggregate_ready and (
        (not question_shape.needs_ranking or ranking_ready)
    ) and question_shape.precomputed_aggregate_available
    if not aggregate_level_ok and (
        question_shape.needs_full_period_aggregation
        or question_shape.needs_ranking
        or question_shape.needs_anomaly_summary
    ):
        reason_codes.append("aggregate_not_sufficient")

    explanation_ready = (
        canonical_sufficient
        and canonical_semantic_coverage >= 0.90
        and canonical_relation_types >= 20
        and not question_shape.needs_runtime_truth
        and not (question_shape.needs_cross_entity_join and question_shape.needs_causal_chain)
    )
    if not explanation_ready and (question_shape.needs_causal_chain or question_shape.needs_cross_entity_join):
        reason_codes.append("explanation_not_ready")

    return StoreSufficiencyResult(
        canonical_sufficient=canonical_sufficient,
        feature_sufficient=feature_sufficient,
        risk_sufficient=risk_sufficient,
        freshness_ok=freshness_ok,
        aggregate_level_ok=aggregate_level_ok,
        ranking_ready=ranking_ready,
        explanation_ready=explanation_ready,
        reason_codes=reason_codes,
    )

