from __future__ import annotations

from jarvis_finance.services.budget_accounts import confirm_create_budget_account
from jarvis_finance.services.budget_categories import confirm_create_category
from jarvis_finance.services.budget_data_explorer import get_budget_data_explorer, get_category_analysis_v2
from jarvis_finance.services.budget_analytics import get_monthly_comparison
from jarvis_finance.services.budget_analytics_v2 import get_budget_vs_actual_analysis
from jarvis_finance.services.budget_transactions import confirm_budget_transaction
from jarvis_finance.storage.database import connect_memory
from jarvis_finance.storage.migrations import apply_migrations


def db():
    conn = connect_memory(); apply_migrations(conn); return conn


def seed(conn):
    account = confirm_create_budget_account(conn, {"name": "Haushalt", "account_type": "checking", "currency": "CHF"})["entity_id"]
    food = confirm_create_category(conn, {"name": "Essen & Haushalt", "category_type": "expense"})["entity_id"]
    income = confirm_create_category(conn, {"name": "Lohn", "category_type": "income"})["entity_id"]
    confirm_budget_transaction(conn, {"account_id": account, "transaction_type": "income", "transaction_date": "2026-05-01", "description": "Lohn", "payee": "Arbeitgeber", "amount_original": "100.00", "currency_original": "CHF", "category_id": income, "source_type": "manual"})
    confirm_budget_transaction(conn, {"account_id": account, "transaction_type": "expense", "transaction_date": "2026-05-02", "description": "Einkauf", "payee": "Migros", "amount_original": "25.00", "currency_original": "CHF", "category_id": food, "source_type": "manual"})


def assert_envelope(data: dict, view: str) -> None:
    assert data["meta"]["view"] == view
    assert data["meta"]["currency"] == "CHF"
    assert data["meta"]["generated_at"]
    assert isinstance(data["filters_applied"], dict)
    assert isinstance(data["totals"], dict)
    assert isinstance(data["series"], list)
    assert isinstance(data["rows"], list)
    assert isinstance(data["warnings"], list)
    assert isinstance(data["errors"], list)


def test_data_explorer_returns_analytics_envelope_and_legacy_keys() -> None:
    conn = db(); seed(conn)
    data = get_budget_data_explorer(conn, year="2026", month="2026-05", type="expense")
    assert_envelope(data, "data_explorer")
    assert data["filters_applied"]["year"] == "2026"
    assert data["totals"]["transaction_count"] == 1
    assert data["rows"] == data["transactions"]
    assert data["kpis"]["expense_sum_chf"] == "25.00"


def test_category_monthly_and_budget_vs_actual_return_analytics_envelope() -> None:
    conn = db(); seed(conn)
    category = get_category_analysis_v2(conn, year="2026", tx_type="expense")
    monthly = get_monthly_comparison(conn, year="2026")
    budget_vs_actual = get_budget_vs_actual_analysis(conn, year="2026")

    assert_envelope(category, "category_analysis")
    assert category["rows"] == category["categories"]
    assert_envelope(monthly, "monthly_comparison")
    assert monthly["rows"] == monthly["months"]
    assert_envelope(budget_vs_actual, "budget_vs_actual")
    assert budget_vs_actual["rows"] == budget_vs_actual["budget_vs_actual_by_category"]
