"""
Dashboard first-run / empty-state experience — Story 3.7.

The dashboard now shows 5 widgets with inline empty states rather than
a separate "Getting Started" checklist. These tests verify the empty-state
behaviour within each widget and the presence of onboarding CTAs.
"""
from decimal import Decimal

import pytest

from app.extensions import db as _db
from app.models.account import Account
from app.models.transaction import Transaction


# ── Fixtures ──────────────────────────────────────────────────────────────────

@pytest.fixture()
def acct(db):
    a = Account(name='Chase', type='checking', is_active=True)
    _db.session.add(a)
    _db.session.commit()
    return a


@pytest.fixture()
def txn(db, acct):
    t = Transaction(
        date='2026-05-15',
        merchant_normalized='ALDI',
        merchant_raw='ALDI',
        amount=Decimal('29.99'),
        account_id=acct.id,
        is_manual=True,
    )
    _db.session.add(t)
    _db.session.commit()
    return t


# ── Basic render ──────────────────────────────────────────────────────────────

class TestDashboardBasic:
    def test_returns_200(self, client, db):
        response = client.get('/')
        assert response.status_code == 200

    def test_has_page_title(self, client, db):
        response = client.get('/')
        assert b'Dashboard' in response.data


# ── Empty-state behaviour (no transactions) ───────────────────────────────────

class TestFirstRunState:
    def test_shows_dashboard_widgets(self, client, db):
        """Dashboard renders widget shells even with no data."""
        response = client.get('/')
        assert b'Budget Burn' in response.data
        assert b'Monthly Spending' in response.data
        assert b'Upcoming Bills' in response.data
        assert b'Recent Transactions' in response.data
        assert b'Debt Paydown' in response.data

    def test_shows_account_or_transaction_cta(self, client, db):
        """Empty state widgets link to onboarding destinations."""
        response = client.get('/')
        assert b'account' in response.data.lower() or b'transaction' in response.data.lower()

    def test_shows_link_to_accounts_or_settings(self, client, db):
        """At least one link to settings (accounts) appears somewhere."""
        response = client.get('/')
        assert b'/settings' in response.data or b'/transactions' in response.data

    def test_shows_add_transaction_step(self, client, db):
        response = client.get('/')
        assert b'transaction' in response.data.lower()

    def test_shows_link_to_create_transaction(self, client, db):
        response = client.get('/')
        assert b'/transactions/create' in response.data or b'/transactions' in response.data

    def test_no_transactions_shows_empty_state_message(self, client, db):
        response = client.get('/')
        assert b'No transactions' in response.data or b'no transactions' in response.data.lower()


# ── Step completion states ────────────────────────────────────────────────────

class TestStepCompletion:
    def test_account_step_reflected_in_dashboard(self, client, db, acct):
        response = client.get('/')
        assert response.status_code == 200

    def test_dashboard_renders_without_account(self, client, db):
        response = client.get('/')
        assert response.status_code == 200

    def test_transaction_step_incomplete_without_transactions(self, client, db, acct):
        response = client.get('/')
        assert b'No transactions' in response.data or b'Add' in response.data

    def test_transaction_step_complete_when_transaction_exists(self, client, db, txn):
        response = client.get('/')
        assert response.status_code == 200
        # Transaction should appear in the Recent Transactions widget
        assert b'ALDI' in response.data


# ── With-data state ───────────────────────────────────────────────────────────

class TestUpAndRunningState:
    def test_transaction_appears_in_recent_widget(self, client, db, txn):
        response = client.get('/')
        assert b'ALDI' in response.data

    def test_does_not_show_empty_state_for_transactions_when_txns_exist(self, client, db, txn):
        response = client.get('/')
        # The "no transactions yet" placeholder should not appear
        assert b'No transactions yet' not in response.data

    def test_shows_link_to_transactions_list(self, client, db, txn):
        response = client.get('/')
        assert b'/transactions' in response.data

    def test_shows_link_to_add_transaction(self, client, db):
        response = client.get('/')
        assert b'/transactions/create' in response.data or b'/transactions' in response.data
