from __future__ import annotations

from src.ibkr.models import (
    AnalysisRecord,
    NormalizedPosition,
    ReconciliationItem,
    TradeBlockData,
)
from src.ibkr.portfolio_presentation import build_cash_summary, build_live_order_note
from src.ibkr.screening_freshness import ScreeningFreshnessSummary
from src.ibkr.ticker import Ticker
from src.web.ibkr_dashboard.serializers import (
    serialize_dashboard_snapshot,
    serialize_equity_drilldown,
)


def test_serialize_dashboard_snapshot_shapes_payload(sample_bundle):
    macro_alert = {"detected": True, "headline": "macro headline"}
    payload = serialize_dashboard_snapshot(
        sample_bundle,
        status="ready",
        fetched_at="2026-03-28T12:00:00Z",
        refreshing=True,
        macro_alert=macro_alert,
    )
    assert payload["status"] == "ready"
    assert (
        payload["portfolio"]["net_liquidation_usd"]
        == sample_bundle.portfolio.portfolio_value_usd
    )
    assert "sell_hard" in payload["actions"]
    assert "watchlist_candidate" in payload["actions"]
    assert payload["summary_counts"]["buys"] == 1
    assert payload["summary_counts"]["candidates"] == 1
    assert "ticker_yf" in payload["actions"]["sell_hard"][0]
    assert isinstance(payload["portfolio"]["settled_cash_usd"], int | float)
    assert payload["macro_alert"] == macro_alert
    assert payload["refreshing"] is True
    assert payload["actions"]["watchlist_candidate"][0]["ticker_yf"] == "BMW.DE"
    assert payload["overview"]["candidates"] == 1
    assert payload["freshness_overview"]["blocking_now"] == 1
    assert payload["actions"]["action_sections"][0]["key"] == "sell_recommendations"
    assert payload["actions"]["action_sections"][1]["key"] == "sell_related_reviews"
    assert (
        payload["actions"]["action_sections"][0]["items"][0]["sell_type_label"]
        == "FUNDAMENTAL FAILURE"
    )


def test_serialize_dashboard_snapshot_handles_empty_lists(sample_bundle):
    sample_bundle.live_orders = []
    payload = serialize_dashboard_snapshot(sample_bundle)
    assert payload["orders"] == []
    assert payload["freshness"]["candidate_blocked"] == []
    assert payload["macro_alert"] is None
    assert payload["screening_freshness"]["status"] == "missing"


def test_serialize_dashboard_snapshot_includes_screening_freshness(sample_bundle):
    sample_bundle.screening_freshness = ScreeningFreshnessSummary(
        status="stale",
        screening_date="2026-01-05",
        completed_at="2026-01-05T10:30:00Z",
        age_days=90,
        stale_after_days=90,
        candidate_count=245,
        buy_count=12,
    )
    payload = serialize_dashboard_snapshot(sample_bundle)
    assert payload["screening_freshness"]["status"] == "stale"
    assert payload["screening_freshness"]["screening_date"] == "2026-01-05"
    assert payload["screening_freshness"]["candidate_count"] == 245


def test_serialize_dashboard_snapshot_uses_shared_cash_summary(sample_bundle):
    payload = serialize_dashboard_snapshot(sample_bundle)
    shared = build_cash_summary(sample_bundle.items, sample_bundle.portfolio)

    assert (
        payload["cash_summary"]["pending_inflows_total_usd"]
        == shared.pending_inflows_total_usd
    )
    assert (
        payload["cash_summary"]["pending_inflows"][0]["ticker_yf"]
        == shared.pending_inflows[0].ticker_yf
    )


def test_serialize_dashboard_snapshot_canonicalizes_sector_weights(sample_bundle):
    sample_bundle.portfolio.sector_weights = {
        "Technology": 8.0,
        "Information Technology": 1.5,
        "Healthcare": 3.0,
        "Health Care": 1.0,
    }

    payload = serialize_dashboard_snapshot(sample_bundle)

    assert payload["portfolio"]["sector_weights"] == {
        "Information Technology": 9.5,
        "Health Care": 4.0,
    }


def test_serialize_dashboard_snapshot_uses_shared_live_order_annotations(sample_bundle):
    payload = serialize_dashboard_snapshot(sample_bundle)
    sell_item = next(item for item in sample_bundle.items if item.ticker.yf == "7203.T")

    assert payload["actions"]["sell_hard"][0][
        "live_order_note"
    ] == build_live_order_note(
        sell_item,
        sample_bundle.live_orders,
    )


def test_serialize_dashboard_snapshot_includes_profit_take_fields(sample_bundle):
    sample_bundle.items.append(
        ReconciliationItem(
            ticker=Ticker.from_yf("6758.T"),
            action="SELL",
            reason="Profit take",
            urgency="LOW",
            sell_type="PROFIT_TAKE",
            cost_basis_return_pct=42.5,
            profit_take_reasons=("capital_idle_cash_severe",),
            ibkr_position=NormalizedPosition(
                conid=1,
                ticker=Ticker.from_yf("6758.T"),
                quantity=100,
                avg_cost_local=1000,
                current_price_local=1425,
                tax_term="LONG_TERM",
            ),
        )
    )

    payload = serialize_dashboard_snapshot(sample_bundle)
    row = payload["actions"]["sell_profit_take"][0]

    assert row["sell_type"] == "PROFIT_TAKE"
    assert row["cost_basis_return_pct"] == 42.5
    assert row["profit_take_reasons"] == ["capital_idle_cash_severe"]


def test_serialize_dashboard_snapshot_includes_currency_repair_metadata(sample_bundle):
    sample_bundle.items[0].analysis = AnalysisRecord(
        ticker="7203.T",
        analysis_date="2026-03-01",
        verdict="BUY",
        currency="JPY",
        currency_source="repair_on_load",
        currency_repaired=True,
        currency_repair_reason="legacy_snapshot_usd_default",
        trade_block=TradeBlockData(),
    )

    payload = serialize_dashboard_snapshot(sample_bundle)
    analysis = payload["actions"]["sell_hard"][0]["analysis"]

    assert analysis["currency"] == "JPY"
    assert analysis["currency_source"] == "repair_on_load"
    assert analysis["currency_repaired"] is True
    assert analysis["currency_repair_reason"] == "legacy_snapshot_usd_default"


def test_serialize_equity_drilldown_includes_structured_and_markdown(sample_bundle):
    item = next(item for item in sample_bundle.items if item.ticker.yf == "MEGP.L")
    payload = serialize_equity_drilldown(
        item,
        live_orders=sample_bundle.live_orders,
        analysis_json={"prediction_snapshot": {"ticker": "MEGP.L"}},
        report_markdown_html="<p>report</p>",
        report_markdown_path="results/MEGP.L.md",
        article_markdown_html=None,
        article_markdown_path=None,
    )
    assert payload["structured"]["prediction_snapshot"]["ticker"] == "MEGP.L"
    assert payload["report_markdown_html"] == "<p>report</p>"
    assert payload["analysis"]["ticker"] == "MEGP.L"
    assert "file_path" not in payload["analysis"]
    assert payload["note"] is None
    assert payload["live_order_note"] is None
