from __future__ import annotations

import json

from jarvis_finance.services.portfolio_analysis_v1 import build_portfolio_analysis_v1
from jarvis_finance.services.portfolio_policy import confirm_policy, preview_policy
from jarvis_finance.storage.database import connect_memory
from jarvis_finance.storage.migrations import apply_migrations

NOW = "2026-08-27T10:00:00Z"


def policy_payload():
    return {
        "base_currency": "CHF", "effective_from": "2026-08-01", "horizon": "long",
        "objective": "Kapitalerhalt und Wachstum", "liquidity_reserve": None,
        "monthly_contribution": "0", "max_crypto_pct": "10",
        "allocations": [
            {"asset_class": "cash", "target_pct": "40", "lower_pct": "35", "upper_pct": "45"},
            {"asset_class": "equity", "target_pct": "50", "lower_pct": "45", "upper_pct": "55"},
            {"asset_class": "crypto", "target_pct": "5", "lower_pct": "0", "upper_pct": "10"},
            {"asset_class": "other", "target_pct": "5", "lower_pct": "0", "upper_pct": "10"},
        ],
    }


def modelled():
    components = [
        {"key": "postfinance", "label": "PostFinance", "current_value_chf": "350", "change_chf": "20"},
        {"key": "truewealth", "label": "True Wealth", "current_value_chf": "100", "change_chf": "10"},
        {"key": "crypto", "label": "Krypto", "current_value_chf": "50", "change_chf": "-5"},
        {"key": "bank_cash", "label": "Bankguthaben", "current_value_chf": "400", "change_chf": "0"},
        {"key": "other_assets", "label": "Weitere Anlagen", "current_value_chf": "20", "change_chf": "0"},
    ]
    return {"components": components}


def test_analysis_uses_requested_buckets_active_policy_and_metadata_without_buy_sell_advice():
    conn = connect_memory()
    apply_migrations(conn)
    payload = policy_payload()
    preview = preview_policy(conn, payload)
    confirm_policy(conn, {**payload, **preview, "confirm": True})
    conn.execute(
        "INSERT INTO platforms(platform_id,name,platform_type,created_at) VALUES('tw-platform','True Wealth','broker',?)",
        (NOW,),
    )
    conn.execute(
        """INSERT INTO accounts(
             account_id,platform_id,account_name,account_type,currency,performance_included,
             is_active,created_at,balance_mode,portfolio_bucket
           ) VALUES('tw-account','tw-platform','True Wealth Portfolio','brokerage','CHF',0,1,?,'snapshot','equity')""",
        (NOW,),
    )
    conn.execute(
        """INSERT INTO truewealth_portfolios(
             portfolio_id,account_id,source_reference_hash,label,portfolio_kind,base_currency,is_active,created_at
           ) VALUES('tw-portfolio','tw-account',?,'Portfolio','free_assets','CHF',1,?)""",
        ("a" * 64, NOW),
    )
    conn.execute(
        """INSERT INTO instruments(
             instrument_id,asset_class,name,currency,country,sector,is_active,created_at
           ) VALUES('stock','stock','Aktie','CHF','CH','Industrie',1,?),
                   ('etf','etf','ETF','USD','US','Breit',1,?)""",
        (NOW, NOW),
    )
    conn.execute(
        """INSERT INTO market_data_runs(
             run_id,as_of,input_fingerprint,status,started_at,completed_at
           ) VALUES('run','2026-08-27','fingerprint','complete',?,?)""",
        (NOW, NOW),
    )
    summary = {
        "positions": [
            {"account_id": "pf-account", "instrument_id": "stock", "name": "Aktie", "asset_class": "stock", "currency": "CHF", "value_chf": "100"},
            {"account_id": "pf-account", "instrument_id": "etf", "name": "ETF", "asset_class": "etf", "currency": "USD", "value_chf": "200"},
            {"account_id": "tw-account", "instrument_id": "stock", "name": "TW Aktie", "asset_class": "stock", "currency": "CHF", "value_chf": "100"},
        ]
    }
    conn.execute(
        """INSERT INTO portfolio_analysis_snapshots(
             analysis_snapshot_id,run_id,as_of,base_currency,total_value_chf,price_coverage_pct,
             fx_coverage_pct,benchmark_coverage_pct,quality_status,reason_codes_json,summary_json,created_at
           ) VALUES('analysis','run','2026-08-27','CHF','300','100','100','100','complete','[]',?,?)""",
        (json.dumps(summary), NOW),
    )
    conn.commit()

    result = build_portfolio_analysis_v1(conn, as_of="2026-08-27", modelled=modelled())

    rows = {row["key"]: row for row in result["allocation"]}
    assert {"cash", "stocks", "etf", "truewealth", "crypto", "other", "equity_policy_group"} <= set(rows)
    assert rows["stocks"]["current_value_chf"] == "100.00"
    assert rows["etf"]["current_value_chf"] == "200.00"
    assert rows["truewealth"]["current_value_chf"] == "100.00"
    assert rows["cash"]["status"] == "above_corridor"
    assert rows["equity_policy_group"]["status"] == "below_corridor"
    assert result["concentrations"]["top1_pct"] is not None
    assert result["dimensions"]["currency"]["rows"]
    assert result["dimensions"]["region"]["status"] == "partial"
    assert 1 <= len(result["hints"]) <= 5
    hint_text = " ".join(item["text"] for item in result["hints"])
    assert "Reduktion prüfen" in hint_text
    assert "Erhöhung prüfen" in hint_text
    assert "Buy" not in hint_text and "Sell" not in hint_text
    assert [row["value_chf"] for row in result["contributions"]] == ["20.00", "10.00", "-5.00"]
