from __future__ import annotations

from pathlib import Path

from jarvis_finance.dashboard import data as dashboard_data
from jarvis_finance.dashboard import main as dashboard_main
from jarvis_finance.dashboard.pages import page_00_command_center, page_04_crypto, page_05_wallets, page_08_reports
from jarvis_finance.dashboard.views import page_03_equities_etfs, page_17_position_add
from jarvis_finance.storage.database import connect_memory
from jarvis_finance.storage.migrations import apply_migrations
from test_dashboard_ux_sprint2 import FakeStreamlit, setup_multi_wallet_crypto_conn, TECHNICAL_FIELDS


def _visible_text(st: FakeStreamlit) -> str:
    parts: list[str] = []
    for _name, args, kwargs in st.calls:
        parts.extend(str(arg) for arg in args)
        parts.extend(str(value) for value in kwargs.values())
    return "\n".join(parts)


def test_user_mode_navigation_is_radically_reduced_and_streamlit_autopages_absent() -> None:
    assert dashboard_main.get_user_navigation_titles() == ["Command Center", "Portfolio", "Crypto", "Wallets", "Position hinzufügen", "Reports"]
    assert "Watchlist" not in dashboard_main.get_user_navigation_titles()
    assert "Equities/ETFs" not in dashboard_main.get_user_navigation_titles()
    assert sorted(Path("src/jarvis_finance/dashboard/pages").glob("[0-9][0-9]_*.py")) == []


def test_position_add_page_is_visible_wizard_and_does_not_call_provider_on_render() -> None:
    conn = connect_memory()
    apply_migrations(conn)
    st = FakeStreamlit()
    page_17_position_add.render(st, conn)
    text = _visible_text(st)
    assert "Position hinzufügen" in text
    assert "1. Assetklasse wählen" in text
    assert "2. Instrument suchen" in text
    assert "Lokal suchen" in text
    assert "Online suchen" in text
    assert "Manuell anlegen" in text
    assert "Position speichern" in text
    assert "catalog_entry_id" not in text
    assert "instrument_id" not in text
    assert "source_id" not in text


def test_portfolio_empty_state_has_add_button_and_routes_to_wizard() -> None:
    conn = connect_memory()
    apply_migrations(conn)
    st = FakeStreamlit(button_presses={"Position hinzufügen"})
    page_03_equities_etfs.render(st, conn)
    text = _visible_text(st)
    assert "Noch keine Cash-, Aktien- oder ETF-Positionen im User Mode vorhanden." in text
    assert "Position hinzufügen" in text
    assert st.session_state.get("jarvis_requested_page") == "Position hinzufügen"


def test_provider_status_visible_without_secrets_or_crash(monkeypatch, tmp_path) -> None:
    monkeypatch.delenv("OPENFIGI_API_KEY", raising=False)
    monkeypatch.delenv("JARVIS_OPENFIGI_API_KEY", raising=False)
    monkeypatch.delenv("FINNHUB_API_KEY", raising=False)
    monkeypatch.delenv("JARVIS_FINNHUB_API_KEY", raising=False)
    monkeypatch.delenv("FMP_API_KEY", raising=False)
    monkeypatch.delenv("JARVIS_FMP_API_KEY", raising=False)
    monkeypatch.setenv("JARVIS_FINANCE_RUNTIME_DIR", str(tmp_path))
    conn = connect_memory()
    apply_migrations(conn)
    st = FakeStreamlit()
    page_17_position_add.render(st, conn)
    text = _visible_text(st)
    assert "Provider-Status" in text
    assert "OpenFIGI" in text
    assert "API-Key fehlt" in text
    assert "~/jarvis_runtime/finance-system/secrets/.env" in text
    assert "OPENFIGI_API_KEY" in text
    assert "runtime-file-key" not in text


def test_command_center_is_quiet_and_has_max_three_clean_hints() -> None:
    conn = setup_multi_wallet_crypto_conn()
    conn.execute(
        "INSERT INTO alerts(alert_id, priority, category, entity_type, entity_id, rule_id, message, status, created_at, last_seen_at, occurrence_count, dedup_key, fingerprint) VALUES ('a1','warnung','market','crypto_asset','asset-btc','missing_crypto_price','asset_id raw should not leak','active','now','now',1,'d1','f1')"
    )
    st = FakeStreamlit()
    page_00_command_center.render(st, conn)
    text = _visible_text(st)
    assert "Was ist wichtig?" in text
    important_lines = [args[0] for name, args, _ in st.calls if name == "markdown" and args and str(args[0]).startswith("**Wichtig:**")]
    assert len(important_lines) <= 3
    forbidden = TECHNICAL_FIELDS | {"asset-btc", "rule_id", "entity_id", "productive initial crypto snapshot import"}
    assert all(item not in text for item in forbidden)
    assert "Top 5 Crypto-Positionen" in text


def test_crypto_page_uses_compact_position_columns_and_detail_panel() -> None:
    conn = setup_multi_wallet_crypto_conn()
    st = FakeStreamlit()
    page_04_crypto.render(st, conn)
    text = _visible_text(st)
    assert "Position auswählen" in text
    assert "Coin Detail" in text
    table_rows = [args[0] for name, args, _ in st.calls if name == "dataframe" and args and isinstance(args[0], list)]
    compact_rows = next(rows for rows in table_rows if rows and "gesamtwert_chf" in rows[0])
    assert set(compact_rows[0]) == {"coin", "symbol", "gesamtmenge", "gesamtwert_chf", "anteil", "wallets", "status"}
    assert "kurs_chf" not in compact_rows[0]


def test_crypto_detail_actions_open_inline_forms_immediately_in_edit_mode() -> None:
    conn = setup_multi_wallet_crypto_conn()
    expected = {
        "Bestand hinzufügen": "Bestand hinzufügen — Formular",
        "Bestand korrigieren": "Korrigieren — Formular",
        "Transfer": "Transfer — Formular",
        "Bestand auf 0 setzen": "Auf 0 setzen — Bestätigung",
        "Audit / Verlauf anzeigen": "Verlauf für ausgewählten Coin",
    }
    for button, marker in expected.items():
        st = FakeStreamlit(button_presses={button})
        st.session_state["jarvis_edit_mode"] = True
        page_04_crypto.render(st, conn)
        assert marker in _visible_text(st)
        assert "Öffnen Sie Admin/Debug" not in _visible_text(st)


def test_read_only_disables_writes_but_keeps_verlauf_available() -> None:
    conn = setup_multi_wallet_crypto_conn()
    st = FakeStreamlit()
    st.session_state["jarvis_edit_mode"] = False
    page_04_crypto.render(st, conn)
    buttons = [(args[0], kwargs) for name, args, kwargs in st.calls if name == "button" and args]
    assert next(kwargs for label, kwargs in buttons if label == "Bestand hinzufügen").get("disabled") is True
    assert next(kwargs for label, kwargs in buttons if label == "Audit / Verlauf anzeigen").get("disabled") is False


def test_wallet_page_is_compact_and_hides_technical_fields() -> None:
    conn = setup_multi_wallet_crypto_conn()
    st = FakeStreamlit()
    page_05_wallets.render(st, conn)
    text = _visible_text(st)
    assert "Wallet auswählen" in text
    assert "Coins in diesem Wallet" in text
    assert all(item not in text for item in TECHNICAL_FIELDS)
    table_rows = [args[0] for name, args, _ in st.calls if name == "dataframe" and args and isinstance(args[0], list)]
    wallet_rows = next(rows for rows in table_rows if rows and "wallet_name" in rows[0])
    assert set(wallet_rows[0]) == {"wallet_name", "wallet_type", "total_value_chf", "coin_count", "status"}


def test_reports_page_stays_minimal_and_crypto_report_action_works(tmp_path: Path) -> None:
    conn = setup_multi_wallet_crypto_conn()
    st = FakeStreamlit(button_presses={"Crypto-Report erzeugen"})
    st.session_state["jarvis_reports_runtime_dir"] = str(tmp_path)
    page_08_reports.render(st, conn)
    text = _visible_text(st)
    assert "Crypto-Report erzeugen" in text
    assert "Portfolio-Report erzeugen" in text
    assert any(name == "success" for name, _args, _kwargs in st.calls)


def test_equity_etf_not_prominently_shown_as_zero_when_unvalued() -> None:
    conn = setup_multi_wallet_crypto_conn()
    summary = dashboard_data.get_command_center_summary(conn)
    assert dashboard_data.equity_etf_user_label(summary) == "noch nicht bewertet"
    st = FakeStreamlit()
    page_00_command_center.render(st, conn)
    text = _visible_text(st)
    assert "Aktien/ETF: Bewertung unvollständig" in text
    assert "Aktien/ETF", "CHF 0.00" not in text
