from __future__ import annotations

from typing import Any, Dict, List, Optional

from oasyce.services.asset_lifecycle import get_asset_lifecycle_store
from oasyce.services.inbox import ConfirmationInbox
from oasyce.services.mandate_service import mandate_payload
from oasyce.services.portfolio_ledger import get_portfolio_ledger_store
from oasyce.services.scheduler import get_scheduler


def _severity_counts(items: List[Dict[str, Any]]) -> Dict[str, int]:
    counts = {"critical": 0, "warning": 0, "info": 0}
    for item in items:
        severity = str(item.get("severity") or "").strip().lower()
        if severity in counts:
            counts[severity] += 1
    counts["total"] = len(items)
    return counts


def _recommendation(
    action: str,
    *,
    command: Optional[str] = None,
    target_section: Optional[str] = None,
    profile: Optional[str] = None,
) -> Dict[str, Any]:
    payload: Dict[str, Any] = {"action": action}
    if command:
        payload["command"] = command
    if target_section:
        payload["target_section"] = target_section
    if profile:
        payload["profile"] = profile
    return payload


def build_operations_exception_summary(
    *,
    data_dir: Optional[str] = None,
    scheduler: Any = None,
    inbox: Optional[ConfirmationInbox] = None,
    lifecycle_summary: Optional[Dict[str, Any]] = None,
    ledger_summary: Optional[Dict[str, Any]] = None,
    mandate: Optional[Dict[str, Any]] = None,
) -> Dict[str, Any]:
    scheduler = scheduler or get_scheduler(data_dir)
    inbox = inbox or ConfirmationInbox(data_dir=data_dir)
    config = scheduler.get_config()
    lifecycle_summary = lifecycle_summary or get_asset_lifecycle_store(data_dir).summary()
    ledger_summary = ledger_summary or get_portfolio_ledger_store(data_dir).summary()
    mandate = mandate or dict((mandate_payload(data_dir).get("current") or {}))

    items: List[Dict[str, Any]] = []

    pending_items = inbox.list_pending()
    pending_registers = [item for item in pending_items if item.item_type == "register"]
    pending_purchases = [item for item in pending_items if item.item_type == "purchase"]
    oldest_pending_minutes = None
    if pending_items:
        oldest = min(int(item.created_at or 0) for item in pending_items)
        if oldest > 0:
            import time

            oldest_pending_minutes = max(0, int((time.time() - oldest) // 60))

    recent_failures = [
        entry
        for entry in list(ledger_summary.get("recent") or [])
        if str(entry.get("status") or "") == "failed"
    ]
    if recent_failures:
        items.append(
            {
                "kind": "failed_actions",
                "severity": "critical",
                "count": len(recent_failures),
                "meta": {
                    "recent": [
                        {
                            "action": entry.get("action"),
                            "item_id": entry.get("item_id"),
                            "error": entry.get("error"),
                            "asset_id": entry.get("asset_id"),
                            "file_path": entry.get("file_path"),
                        }
                        for entry in recent_failures[:3]
                    ]
                },
                "recommendation": _recommendation(
                    "inspect_recent_operations",
                    command="oas agent status",
                    target_section="operations",
                ),
            }
        )

    if pending_items:
        severity = (
            "warning" if len(pending_items) >= 3 or (oldest_pending_minutes or 0) >= 60 else "info"
        )
        items.append(
            {
                "kind": "review_bottleneck",
                "severity": severity,
                "count": len(pending_items),
                "meta": {
                    "pending_registers": len(pending_registers),
                    "pending_purchases": len(pending_purchases),
                    "oldest_pending_minutes": oldest_pending_minutes or 0,
                },
                "recommendation": _recommendation(
                    "review_inbox",
                    command="oas inbox list",
                    target_section="candidates",
                ),
            }
        )

    policy_counts = dict(lifecycle_summary.get("policy_counts") or {})
    mandate_requires_review = int(policy_counts.get("mandate_requires_review") or 0)
    if str(mandate.get("review_mode") or "") == "all_candidates" and (
        mandate_requires_review > 0 or len(pending_registers) > 0
    ):
        items.append(
            {
                "kind": "mandate_conflict",
                "severity": "warning",
                "count": max(mandate_requires_review, len(pending_registers)),
                "meta": {
                    "review_mode": mandate.get("review_mode"),
                    "draft_count": mandate_requires_review,
                    "pending_registers": len(pending_registers),
                },
                "recommendation": _recommendation(
                    "review_candidates",
                    command="oas inbox list --type register",
                    target_section="candidates",
                ),
            }
        )

    runtime_conflict = bool(config.auto_trade) != (
        str(mandate.get("trade_mode") or "") == "budgeted"
    ) or float(config.trade_max_spend) != float(mandate.get("trade_max_spend") or 0.0)
    if runtime_conflict:
        current_profile = str(mandate.get("profile") or "").strip()
        items.append(
            {
                "kind": "mandate_conflict",
                "severity": "warning",
                "count": 1,
                "meta": {
                    "runtime_auto_trade": bool(config.auto_trade),
                    "mandate_trade_mode": str(mandate.get("trade_mode") or ""),
                    "runtime_trade_max_spend": float(config.trade_max_spend),
                    "mandate_trade_max_spend": float(mandate.get("trade_max_spend") or 0.0),
                },
                "recommendation": _recommendation(
                    "align_runtime_to_mandate",
                    command=(
                        f"oas mandate apply-profile {current_profile}"
                        if current_profile
                        else "oas mandate status"
                    ),
                    target_section="policy",
                    profile=current_profile or None,
                ),
            }
        )

    over_budget_purchases = [
        item
        for item in pending_purchases
        if float(item.price or 0.0) > float(config.trade_max_spend or 0.0) > 0.0
    ]
    budget_related_failures = [
        entry
        for entry in recent_failures
        if str(entry.get("action") or "") == "purchase"
        and any(
            token in str(entry.get("error") or "").lower()
            for token in ("budget", "insufficient", "balance", "fund")
        )
    ]
    if over_budget_purchases or budget_related_failures:
        items.append(
            {
                "kind": "budget_pressure",
                "severity": "warning",
                "count": len(over_budget_purchases) + len(budget_related_failures),
                "meta": {
                    "trade_max_spend": float(config.trade_max_spend or 0.0),
                    "pending_over_budget": len(over_budget_purchases),
                    "recent_budget_failures": len(budget_related_failures),
                },
                "recommendation": _recommendation(
                    "review_purchase_candidates",
                    command="oas inbox list --type purchase",
                    target_section="candidates",
                ),
            }
        )

    return {
        "counts": _severity_counts(items),
        "items": items,
    }
