from __future__ import annotations

from oasyce.services.inbox import ConfirmationInbox
from oasyce.services.operations_exceptions import build_operations_exception_summary
from oasyce.services.portfolio_ledger import get_portfolio_ledger_store
from oasyce.services.scheduler import SchedulerConfig, get_scheduler
from oasyce.services.mandate_service import load_mandate, save_mandate


def test_exception_summary_reports_failed_actions_and_review_bottleneck(tmp_path):
    inbox = ConfirmationInbox(data_dir=str(tmp_path))
    inbox.add_pending_register("/tmp/a.csv", "A")
    inbox.add_pending_purchase("asset_1", 12.0, "too expensive")
    ledger = get_portfolio_ledger_store(str(tmp_path))
    ledger.record(
        action="register",
        status="failed",
        item_id="item-1",
        account_id="oasyce1owner",
        error="register failed",
    )

    summary = build_operations_exception_summary(data_dir=str(tmp_path), inbox=inbox)

    assert summary["counts"]["critical"] == 1
    assert summary["counts"]["warning"] >= 1
    kinds = {item["kind"] for item in summary["items"]}
    assert "failed_actions" in kinds
    assert "review_bottleneck" in kinds
    failed = next(item for item in summary["items"] if item["kind"] == "failed_actions")
    review = next(item for item in summary["items"] if item["kind"] == "review_bottleneck")
    assert failed["recommendation"]["action"] == "inspect_recent_operations"
    assert review["recommendation"]["command"] == "oas inbox list"


def test_exception_summary_reports_mandate_and_budget_pressure(tmp_path):
    inbox = ConfirmationInbox(data_dir=str(tmp_path))
    inbox.add_pending_register("/tmp/a.csv", "A")
    inbox.add_pending_purchase("asset_1", 25.0, "candidate")

    scheduler = get_scheduler(str(tmp_path))
    config = scheduler.get_config()
    config.auto_trade = True
    config.trade_max_spend = 10.0
    scheduler.update_config(config)

    mandate = load_mandate(str(tmp_path))
    updated = mandate.__class__(
        **{
            **mandate.to_dict(),
            "review_mode": "all_candidates",
            "trade_mode": "budgeted",
            "trade_max_spend": 20.0,
        }
    )
    save_mandate(updated, data_dir=str(tmp_path))

    summary = build_operations_exception_summary(
        data_dir=str(tmp_path), scheduler=scheduler, inbox=inbox
    )

    mandate_conflicts = [item for item in summary["items"] if item["kind"] == "mandate_conflict"]
    budget_pressure = next(item for item in summary["items"] if item["kind"] == "budget_pressure")

    assert any(item["meta"].get("review_mode") == "all_candidates" for item in mandate_conflicts)
    assert any(
        item["recommendation"]["action"] == "review_candidates"
        for item in mandate_conflicts
        if item["meta"].get("review_mode") == "all_candidates"
    )
    assert any(
        item["recommendation"]["action"] == "align_runtime_to_mandate"
        for item in mandate_conflicts
        if item["meta"].get("runtime_trade_max_spend") is not None
    )
    assert budget_pressure["meta"]["pending_over_budget"] == 1
    assert budget_pressure["recommendation"]["command"] == "oas inbox list --type purchase"
