from __future__ import annotations

from sqlite3 import Connection

from fastapi import HTTPException

from jarvis_finance.audit.log import record_audit_event
from jarvis_finance.services.budget_common import new_id, now, row_to_dict, validate_account_type, validate_currency


def _normalise_payload(payload: dict) -> dict:
    name = str(payload.get("name") or "").strip()
    if not name:
        raise HTTPException(status_code=422, detail="name is required")
    linked_account_id = payload.get("linked_account_id") or None
    return {
        "budget_account_id": payload.get("budget_account_id") or new_id("bacc"),
        "linked_account_id": linked_account_id,
        "name": name,
        "account_type": validate_account_type(payload.get("account_type") or "other"),
        "currency": validate_currency(payload.get("currency") or "CHF"),
        "notes": payload.get("notes") or None,
    }


def create_budget_account_preview(conn: Connection, payload: dict) -> dict:
    normalised = _normalise_payload(payload)
    if normalised["linked_account_id"]:
        exists = conn.execute("SELECT 1 FROM accounts WHERE account_id=?", (normalised["linked_account_id"],)).fetchone()
        if not exists:
            raise HTTPException(status_code=422, detail="linked_account_id does not exist")
    return {
        "preview_id": new_id("preview"),
        "summary": f"{normalised['name']} · {normalised['account_type']} · {normalised['currency']}",
        "warnings": [],
        "payload": normalised,
    }


def confirm_create_budget_account(conn: Connection, payload: dict) -> dict:
    normalised = _normalise_payload(payload)
    ts = now()
    conn.execute(
        """
        INSERT INTO budget_accounts(
            budget_account_id, linked_account_id, name, account_type, currency,
            is_active, archived_at, notes, created_at, updated_at
        ) VALUES (?, ?, ?, ?, ?, 1, NULL, ?, ?, ?)
        """,
        (
            normalised["budget_account_id"],
            normalised["linked_account_id"],
            normalised["name"],
            normalised["account_type"],
            normalised["currency"],
            normalised["notes"],
            ts,
            ts,
        ),
    )
    audit_id = record_audit_event(conn, source="vue_dashboard", action="create", entity_type="budget_account", entity_id=normalised["budget_account_id"], new_values=normalised, user_text_note=normalised.get("notes"), created_by="user")
    conn.commit()
    return {"status": "confirmed", "entity_id": normalised["budget_account_id"], "audit_id": audit_id, "message": "Budgetkonto gespeichert"}


def archive_budget_account(conn: Connection, account_id: str) -> dict:
    row = conn.execute("SELECT * FROM budget_accounts WHERE budget_account_id=?", (account_id,)).fetchone()
    if not row:
        raise HTTPException(status_code=404, detail="budget account not found")
    ts = now()
    conn.execute("UPDATE budget_accounts SET is_active=0, archived_at=?, updated_at=? WHERE budget_account_id=?", (ts, ts, account_id))
    audit_id = record_audit_event(conn, source="vue_dashboard", action="archive", entity_type="budget_account", entity_id=account_id, old_values=row_to_dict(row), new_values={"is_active": 0, "archived_at": ts}, confirmed=True, created_by="user")
    conn.commit()
    return {"status": "archived", "entity_id": account_id, "audit_id": audit_id, "message": "Budgetkonto archiviert"}


def list_budget_accounts(conn: Connection, include_archived: bool = True) -> list[dict]:
    where = "" if include_archived else "WHERE is_active = 1"
    rows = conn.execute(f"SELECT * FROM budget_accounts {where} ORDER BY is_active DESC, name").fetchall()
    return [row_to_dict(r) | {"is_active": bool(r["is_active"])} for r in rows]
