from __future__ import annotations

from typing import Any, Dict, Iterable, Optional

from oasyce.services.inbox import ConfirmationInbox
from oasyce.services.portfolio_ledger import get_portfolio_ledger_store
from oasyce.services.runtime_identity import normalize_runtime_actor


def _round_amount(value: Any) -> float:
    try:
        return round(float(value or 0.0), 6)
    except (TypeError, ValueError):
        return 0.0


def _int(value: Any) -> int:
    try:
        return int(value or 0)
    except (TypeError, ValueError):
        return 0


def _empty_type_counts() -> Dict[str, int]:
    return {
        "register": 0,
        "purchase": 0,
        "deprecate": 0,
        "archive": 0,
    }


def _empty_delegate_row(*, principal_id: str, delegate_id: str) -> Dict[str, Any]:
    return {
        "principal_id": principal_id,
        "delegate_id": delegate_id,
        "pending_review": 0,
        "execution_ready": 0,
        "failed_execution": 0,
        "pending_purchase_oas": 0.0,
        "execution_ready_purchase_oas": 0.0,
        "open_purchase_exposure_oas": 0.0,
        "allocated_budget_oas": 0.0,
        "budget_gap_oas": 0.0,
        "executions": 0,
        "succeeded": 0,
        "failed": 0,
        "spent_oas": 0.0,
        "earned_oas": 0.0,
        "net_oas": 0.0,
        "assets_created": 0,
        "purchases": 0,
        "last_timestamp": 0,
        "agent_counts": {},
        "top_agents": [],
        "recommendation": {},
    }


def _queue_actor(
    item: Dict[str, Any], fallback_actor: Optional[Dict[str, Any]]
) -> Optional[Dict[str, Any]]:
    coordination = dict(item.get("coordination") or {})
    item_status = str(item.get("status") or "").strip()
    execution_status = str(item.get("execution_status") or "").strip()
    if execution_status:
        keys = ("executed_by", "resolved_by", "recommended_by", "discovered_by")
    elif item_status == "approved":
        keys = ("resolved_by", "recommended_by", "discovered_by")
    else:
        keys = ("recommended_by", "discovered_by", "resolved_by")
    for key in keys:
        actor = normalize_runtime_actor(coordination.get(key))
        if actor:
            return actor
    return fallback_actor


def _queue_type_counts(items: Iterable[Dict[str, Any]]) -> Dict[str, int]:
    counts = _empty_type_counts()
    for item in items:
        item_type = str(item.get("item_type") or "").strip()
        if item_type in counts:
            counts[item_type] += 1
    return counts


def _budget_share(
    *,
    requested_budget_oas: float,
    total_requested_budget_oas: float,
    allocatable_budget_oas: float,
) -> float:
    requested = _round_amount(requested_budget_oas)
    total_requested = _round_amount(total_requested_budget_oas)
    allocatable = _round_amount(allocatable_budget_oas)
    if requested <= 0 or allocatable <= 0 or total_requested <= 0:
        return 0.0
    if total_requested <= allocatable:
        return requested
    return _round_amount(allocatable * (requested / total_requested))


def _delegate_recommendation(
    row: Dict[str, Any], *, mandate_review_mode: str = "", trade_mode: str = ""
) -> Dict[str, Any]:
    if _int(row.get("failed_execution")) > 0:
        return {
            "action": "inspect_failed_execution",
            "target_section": "operations",
            "command": "oas agent status",
            "reason": "execution failures need operator attention first",
        }
    if _int(row.get("pending_review")) > 0:
        return {
            "action": "review_candidates",
            "target_section": "candidates",
            "command": "open Candidates and clear the pending queue",
            "reason": "candidate review is blocking shared progress",
        }
    if _int(row.get("execution_ready")) > 0:
        if trade_mode == "budgeted" and _round_amount(row.get("budget_gap_oas")) > 0:
            return {
                "action": "rebalance_budget",
                "target_section": "policy",
                "command": "oas mandate status",
                "reason": "ready purchases exceed the current budget share",
            }
        return {
            "action": "run_ready_queue",
            "target_section": "operations",
            "command": "oas agent run",
            "reason": "approved work is ready to execute",
        }
    if mandate_review_mode == "all_candidates":
        return {
            "action": "hold_for_review",
            "target_section": "candidates",
            "command": "open Candidates",
            "reason": "the current mandate requires explicit review",
        }
    return {
        "action": "monitor_results",
        "target_section": "operations",
        "command": "oas agent status",
        "reason": "this delegate has no urgent queue pressure",
    }


def _desk_recommendation(
    *,
    review_count: int,
    execution_ready_count: int,
    failed_execution_count: int,
    budget_gap_oas: float,
    trade_mode: str,
    mandate_review_mode: str,
) -> Dict[str, Any]:
    if failed_execution_count > 0:
        return {
            "action": "inspect_failed_execution",
            "target_section": "operations",
            "command": "oas agent status",
            "reason": "recent failures take priority over new work",
        }
    if review_count > 0:
        return {
            "action": "review_candidates",
            "target_section": "candidates",
            "command": "open Candidates and review the pending queue",
            "reason": "candidate review is the current bottleneck",
        }
    if execution_ready_count > 0 and trade_mode == "budgeted" and budget_gap_oas > 0:
        return {
            "action": "rebalance_budget",
            "target_section": "policy",
            "command": "oas mandate status",
            "reason": "approved work is waiting on budget headroom",
        }
    if execution_ready_count > 0:
        return {
            "action": "run_ready_queue",
            "target_section": "operations",
            "command": "oas agent run",
            "reason": "approved work is ready to execute",
        }
    if mandate_review_mode == "all_candidates":
        return {
            "action": "hold_for_review",
            "target_section": "candidates",
            "command": "open Candidates",
            "reason": "the mandate requires review before autonomous execution",
        }
    return {
        "action": "monitor_results",
        "target_section": "operations",
        "command": "oas agent status",
        "reason": "the shared desk is currently clear",
    }


def build_shared_desk_summary(
    *,
    data_dir: Optional[str] = None,
    inbox: Optional[ConfirmationInbox] = None,
    runtime_identity: Optional[Dict[str, Any]] = None,
    mandate: Optional[Dict[str, Any]] = None,
    ledger_summary: Optional[Dict[str, Any]] = None,
    delegate_limit: int = 6,
) -> Dict[str, Any]:
    inbox = inbox or ConfirmationInbox(data_dir=data_dir)
    runtime_identity = dict(runtime_identity or {})
    mandate = dict(mandate or {})
    ledger_summary = dict(ledger_summary or get_portfolio_ledger_store(data_dir).summary())

    principal = dict(runtime_identity.get("principal") or {})
    account = dict(runtime_identity.get("account") or {})
    principal_id = str(principal.get("id") or account.get("id") or "").strip()
    account_id = str(account.get("id") or "").strip()
    fallback_actor = normalize_runtime_actor(runtime_identity)

    items = [item.to_dict() for item in inbox.list_all()]
    review_items = [item for item in items if str(item.get("status") or "") == "pending"]
    execution_ready_items = [
        item
        for item in items
        if str(item.get("status") or "") == "approved"
        and not str(item.get("execution_status") or "").strip()
    ]
    failed_execution_items = [
        item
        for item in items
        if str(item.get("status") or "") == "approved"
        and str(item.get("execution_status") or "").strip() == "failed"
    ]

    pending_purchase_oas = _round_amount(
        sum(
            float(item.get("price") or 0.0)
            for item in review_items
            if item.get("item_type") == "purchase"
        )
    )
    execution_ready_purchase_oas = _round_amount(
        sum(
            float(item.get("price") or 0.0)
            for item in execution_ready_items
            if item.get("item_type") == "purchase"
        )
    )
    open_purchase_exposure_oas = _round_amount(pending_purchase_oas + execution_ready_purchase_oas)
    trade_mode = str(mandate.get("trade_mode") or "").strip()
    mandate_review_mode = str(mandate.get("review_mode") or "").strip()
    trade_budget = _round_amount(mandate.get("trade_max_spend"))
    allocatable_budget_oas = trade_budget if trade_mode == "budgeted" else 0.0
    budget_gap_oas = _round_amount(max(open_purchase_exposure_oas - allocatable_budget_oas, 0.0))
    budget_headroom = _round_amount(allocatable_budget_oas - open_purchase_exposure_oas)

    contribution_rows = {
        str(row.get("delegate_id") or "").strip(): dict(row)
        for row in list((ledger_summary.get("contributions") or {}).get("delegates") or [])
        if str(row.get("delegate_id") or "").strip()
    }
    delegate_rows: Dict[str, Dict[str, Any]] = {}

    def ensure_delegate_row(delegate_id: str) -> Dict[str, Any]:
        row = delegate_rows.get(delegate_id)
        if row is not None:
            return row
        contribution = dict(contribution_rows.get(delegate_id) or {})
        row = _empty_delegate_row(principal_id=principal_id, delegate_id=delegate_id)
        row["executions"] = _int(contribution.get("executions"))
        row["succeeded"] = _int(contribution.get("succeeded"))
        row["failed"] = _int(contribution.get("failed"))
        row["spent_oas"] = _round_amount(contribution.get("spent_oas"))
        row["earned_oas"] = _round_amount(contribution.get("earned_oas"))
        row["net_oas"] = _round_amount(contribution.get("net_oas"))
        row["assets_created"] = _int(contribution.get("assets_created"))
        row["purchases"] = _int(contribution.get("purchases"))
        row["last_timestamp"] = _int(contribution.get("last_timestamp"))
        row["agent_counts"] = dict(contribution.get("agent_counts") or {})
        row["top_agents"] = [
            {"agent_id": str(agent_id), "count": _int(count)}
            for agent_id, count in list(row["agent_counts"].items())[:3]
        ]
        delegate_rows[delegate_id] = row
        return row

    def apply_queue_item(
        item: Dict[str, Any], *, queue_key: str, budget_key: Optional[str] = None
    ) -> None:
        actor = _queue_actor(item, fallback_actor)
        if not actor:
            return
        delegate_id = str(
            (actor.get("delegate") or {}).get("id") or actor.get("device_id") or ""
        ).strip()
        if not delegate_id:
            return
        row = ensure_delegate_row(delegate_id)
        row[queue_key] = _int(row.get(queue_key)) + 1
        if budget_key and str(item.get("item_type") or "") == "purchase":
            amount = _round_amount(item.get("price"))
            row[budget_key] = _round_amount(float(row.get(budget_key) or 0.0) + amount)

    for item in review_items:
        apply_queue_item(item, queue_key="pending_review", budget_key="pending_purchase_oas")
    for item in execution_ready_items:
        apply_queue_item(
            item,
            queue_key="execution_ready",
            budget_key="execution_ready_purchase_oas",
        )
    for item in failed_execution_items:
        apply_queue_item(item, queue_key="failed_execution")

    for row in delegate_rows.values():
        row["open_purchase_exposure_oas"] = _round_amount(
            float(row.get("pending_purchase_oas") or 0.0)
            + float(row.get("execution_ready_purchase_oas") or 0.0)
        )
        row["allocated_budget_oas"] = _budget_share(
            requested_budget_oas=float(row.get("open_purchase_exposure_oas") or 0.0),
            total_requested_budget_oas=open_purchase_exposure_oas,
            allocatable_budget_oas=allocatable_budget_oas,
        )
        row["budget_gap_oas"] = _round_amount(
            max(
                float(row.get("open_purchase_exposure_oas") or 0.0)
                - float(row.get("allocated_budget_oas") or 0.0),
                0.0,
            )
        )
        row["recommendation"] = _delegate_recommendation(
            row,
            mandate_review_mode=mandate_review_mode,
            trade_mode=trade_mode,
        )

    sorted_rows = sorted(
        delegate_rows.values(),
        key=lambda row: (
            -_int(row.get("pending_review")),
            -_int(row.get("execution_ready")),
            -_int(row.get("executions")),
            str(row.get("delegate_id") or ""),
        ),
    )[:delegate_limit]

    return {
        "principal_id": principal_id,
        "account_id": account_id,
        "profile": str(mandate.get("profile") or "").strip(),
        "objective": str(mandate.get("objective") or "").strip(),
        "queues": {
            "review": {
                "total": len(review_items),
                "by_type": _queue_type_counts(review_items),
            },
            "execution_ready": {
                "total": len(execution_ready_items),
                "by_type": _queue_type_counts(execution_ready_items),
            },
            "failed_execution": {
                "total": len(failed_execution_items),
                "by_type": _queue_type_counts(failed_execution_items),
            },
        },
        "budget": {
            "trade_mode": trade_mode,
            "trade_max_spend": trade_budget,
            "allocatable_budget_oas": _round_amount(allocatable_budget_oas),
            "pending_purchase_oas": pending_purchase_oas,
            "execution_ready_purchase_oas": execution_ready_purchase_oas,
            "open_purchase_exposure_oas": open_purchase_exposure_oas,
            "budget_headroom_oas": budget_headroom,
            "budget_gap_oas": budget_gap_oas,
        },
        "delegates": sorted_rows,
        "recommendation": _desk_recommendation(
            review_count=len(review_items),
            execution_ready_count=len(execution_ready_items),
            failed_execution_count=len(failed_execution_items),
            budget_gap_oas=budget_gap_oas,
            trade_mode=trade_mode,
            mandate_review_mode=mandate_review_mode,
        ),
    }
