from __future__ import annotations

from datetime import date

from jarvis_finance.crypto.manage import (
    add_crypto_position,
    adjust_crypto_position,
    current_wallet_asset_quantity,
    transfer_crypto_position,
    get_crypto_management_options,
)
from jarvis_finance.crypto.wallets import create_wallet, update_wallet, VALID_WALLET_TYPES
from jarvis_finance.dashboard.components.tables import show_table
from jarvis_finance.dashboard import data

PAGE_TITLE = "Crypto Manage"
ACTIONS = [
    "Coin hinzufügen",
    "Bestand korrigieren",
    "Transfer zwischen Wallets",
    "Bestand entfernen / auf 0 setzen",
    "Neues Wallet",
    "Verlauf ansehen",
]


def _wallet_options(options):
    return {f"{w['wallet_name']} ({w['wallet_type']})": w["wallet_id"] for w in options["wallets"]}


def _asset_options(options):
    return {f"{a['coin_name']} / {a['symbol']}": a["asset_id"] for a in options["assets"]}


def _holding_options(options):
    return {f"{h['coin_name']} / {h['symbol']} @ {h['wallet_name']} — {h['quantity']}": (h["asset_id"], h["wallet_id"]) for h in options["holdings"]}


def _set_action(st, action: str) -> None:
    try:
        st.session_state["crypto_manage_action"] = action
    except Exception:
        pass


def _get_action(st) -> str | None:
    try:
        return st.session_state.get("crypto_manage_action")
    except Exception:
        return None


def _render_action_cards(st) -> None:
    st.subheader("Was möchten Sie tun?")
    cols = st.columns(3)
    descriptions = {
        "Coin hinzufügen": "Neue oder bestehende Coin-Position auditierbar erfassen.",
        "Bestand korrigieren": "Aktuellen Wallet-Bestand per manual_adjustment korrigieren.",
        "Transfer zwischen Wallets": "Coin zwischen Wallets verschieben; Quelle und Ziel bleiben nachvollziehbar.",
        "Bestand entfernen / auf 0 setzen": "Nichts löschen: Bestand auditierbar auf 0 setzen.",
        "Neues Wallet": "Wallet-Container ohne Pflicht-Adresse anlegen.",
        "Verlauf ansehen": "Transaktionen und Audit-Trail prüfen.",
    }
    for idx, action in enumerate(ACTIONS):
        with cols[idx % 3]:
            st.markdown(f"### {action}")
            st.caption(descriptions[action])
            if st.button(action, key=f"crypto_manage_action_{idx}"):
                _set_action(st, action)


def _render_wizard_header(st, action: str) -> None:
    st.markdown(f"## {action}")
    st.caption("Schrittfolge: 1 Was? → 2 Wo? → 3 Menge/Datum → 4 Review → 5 Bestätigen")


def render(st, conn) -> None:
    st.title("Crypto Manage")
    st.caption("Action Cards statt Formular-Wüste. Formulare erscheinen erst nach Aktionsauswahl; alle Änderungen bleiben auditierbar.")
    options = get_crypto_management_options(conn)
    wallet_labels = _wallet_options(options)
    asset_labels = _asset_options(options)
    holding_labels = _holding_options(options)

    _render_action_cards(st)
    action = _get_action(st)
    if not action:
        st.info("Wählen Sie eine Aktion aus. Bis dahin wird nichts geändert und kein Formular geöffnet.")
        return

    _render_wizard_header(st, action)

    if action == "Coin hinzufügen":
        coin_name = st.text_input("Schritt 1 — Coin-Name")
        symbol = st.text_input("Schritt 1 — Symbol")
        coingecko_id = st.text_input("Schritt 1 — CoinGecko-ID optional")
        wallet_label = st.selectbox("Schritt 2 — Wallet", list(wallet_labels)) if wallet_labels else None
        qty = st.text_input("Schritt 3 — Menge als Decimal/Text")
        effective = st.date_input("Schritt 3 — Datum", value=date.today())
        op_type = st.selectbox("Schritt 3 — Typ", ["initial_snapshot_addition", "manual_adjustment"])
        note = st.text_area("Schritt 4 — Review-Notiz")
        st.write({"Coin": coin_name, "Symbol": symbol, "Wallet": wallet_label, "Menge": qty, "Typ": op_type, "Datum": str(effective)})
        confirm = st.checkbox("Schritt 5 — Review bestätigt: Coin hinzufügen")
        if st.button("Bestätigen und speichern"):
            try:
                result = add_crypto_position(conn, coin_name=coin_name, symbol=symbol, coingecko_id=coingecko_id or None, wallet_id=wallet_labels[wallet_label], quantity_text=qty, effective_date=str(effective), operation_type=op_type, note=note, confirm=confirm)
                st.success(f"Gespeichert und auditiert: {result.transaction_id or result.holding_id}")
            except Exception as exc:
                st.error(str(exc))

    elif action == "Bestand korrigieren":
        holding_label = st.selectbox("Schritt 1/2 — Coin + Wallet", list(holding_labels)) if holding_labels else None
        if holding_label:
            asset_id, wallet_id = holding_labels[holding_label]
            current = current_wallet_asset_quantity(conn, wallet_id=wallet_id, asset_id=asset_id)
            st.metric("Aktuelle Menge", data.dec_text(current))
            new_qty = st.text_input("Schritt 3 — Neue Menge als Decimal/Text")
            note = st.text_area("Schritt 4 — Notiz Pflicht")
            confirm = st.checkbox("Schritt 5 — Review bestätigt: Korrektur speichern")
            if st.button("Korrektur speichern"):
                try:
                    result = adjust_crypto_position(conn, asset_id=asset_id, wallet_id=wallet_id, new_quantity_text=new_qty, effective_date=str(date.today()), note=note, confirm=confirm)
                    st.success(f"Korrektur auditiert: {result.transaction_id}")
                except Exception as exc:
                    st.error(str(exc))

    elif action == "Transfer zwischen Wallets":
        asset_label = st.selectbox("Schritt 1 — Coin", list(asset_labels)) if asset_labels else None
        from_label = st.selectbox("Schritt 2 — von Wallet", list(wallet_labels)) if wallet_labels else None
        to_label = st.selectbox("Schritt 2 — zu Wallet", list(wallet_labels)) if wallet_labels else None
        qty = st.text_input("Schritt 3 — Menge")
        fee = st.text_input("Schritt 3 — Fee optional", value="0")
        note = st.text_area("Schritt 4 — Notiz optional")
        confirm = st.checkbox("Schritt 5 — Review bestätigt: Transfer speichern")
        if st.button("Transfer speichern"):
            try:
                result = transfer_crypto_position(conn, asset_id=asset_labels[asset_label], from_wallet_id=wallet_labels[from_label], to_wallet_id=wallet_labels[to_label], quantity_text=qty, fee_quantity_text=fee, effective_date=str(date.today()), note=note, confirm=confirm)
                st.success(f"Transfer auditiert: {result.transaction_id}")
            except Exception as exc:
                st.error(str(exc))

    elif action == "Bestand entfernen / auf 0 setzen":
        st.warning("Es wird nichts gelöscht. Der Bestand wird via manual_adjustment auditierbar auf 0 gesetzt.")
        holding_label = st.selectbox("Schritt 1/2 — Coin + Wallet", list(holding_labels)) if holding_labels else None
        note = st.text_area("Schritt 4 — Notiz Pflicht")
        confirm = st.checkbox("Schritt 5 — Review bestätigt: auf 0 setzen")
        if st.button("Bestand auf 0 setzen") and holding_label:
            try:
                asset_id, wallet_id = holding_labels[holding_label]
                result = adjust_crypto_position(conn, asset_id=asset_id, wallet_id=wallet_id, new_quantity_text="0", effective_date=str(date.today()), note=note, confirm=confirm)
                st.success(f"Bestand auf 0 gesetzt und auditiert: {result.transaction_id}")
            except Exception as exc:
                st.error(str(exc))

    elif action == "Neues Wallet":
        name = st.text_input("Schritt 1 — Wallet-Name")
        wallet_type = st.selectbox("Schritt 1 — Wallet-Typ", sorted(VALID_WALLET_TYPES))
        provider = st.text_input("Schritt 2 — Provider")
        chain = st.text_input("Schritt 2 — Chain/Network optional")
        note = st.text_area("Schritt 4 — Notiz optional")
        active = st.checkbox("Schritt 4 — active", value=True)
        confirm = st.checkbox("Schritt 5 — Review bestätigt: Wallet erstellen")
        if st.button("Wallet speichern"):
            try:
                if not confirm:
                    raise ValueError("explicit confirm is required before saving")
                wallet_id = create_wallet(conn, wallet_name=name, wallet_type=wallet_type, platform_provider=provider or None, network_chain=chain or None, notes=note or None)
                if not active:
                    update_wallet(conn, wallet_id, is_active=0)
                st.success("Wallet auditiert erstellt.")
            except Exception as exc:
                st.error(str(exc))

    elif action == "Verlauf ansehen":
        show_table(st, data.get_latest_crypto_transactions(conn))
        with st.expander("Technische Audit-Details anzeigen"):
            show_table(st, data.get_audit_events(conn, limit=50))
