from __future__ import annotations

from decimal import Decimal

from quartermaster import month_service, service
from quartermaster.models import Section


def test_add_entry_stores_notes(db):
    entry = service.add_entry(
        db,
        Section.sinking_fund,
        "Emergency",
        Decimal("500.00"),
        notes="Target: 3 months of expenses",
    )
    assert entry.notes == "Target: 3 months of expenses"


def test_add_entry_strips_and_nulls_empty_notes(db):
    entry = service.add_entry(
        db, Section.other, "Gift", Decimal("25.00"), notes="   "
    )
    assert entry.notes is None



def test_snapshot_copies_notes(db):
    service.add_entry(
        db,
        Section.sinking_fund,
        "Emergency",
        Decimal("500.00"),
        notes="3 months expenses",
    )
    month = month_service.create_month(db, "2026-04")
    emergency = next(e for e in month.entries if e.origin_name == "Emergency")
    assert emergency.notes == "3 months expenses"


def test_month_notes_edit_does_not_change_deviation_state(db):
    service.add_entry(
        db, Section.fixed_bill, "Rent", Decimal("1200.00"), notes="auto-pay"
    )
    month = month_service.create_month(db, "2026-04")
    rent = next(e for e in month.entries if e.origin_name == "Rent")
    # unchanged initially
    assert (
        month_service.deviation_state(rent) == month_service.DeviationState.unchanged
    )
    # update notes only
    month_service.update_month_entry(
        db, month, rent.id, notes="auto-pay; renew July 2027"
    )
    db.refresh(rent)
    assert rent.notes == "auto-pay; renew July 2027"
    assert (
        month_service.deviation_state(rent) == month_service.DeviationState.unchanged
    )


def test_update_month_entry_notes_to_empty_nulls(db):
    service.add_entry(db, Section.other, "Parking", Decimal("25.00"), notes="work")
    month = month_service.create_month(db, "2026-04")
    entry = next(e for e in month.entries if e.origin_name == "Parking")
    assert entry.notes == "work"
    month_service.update_month_entry(db, month, entry.id, notes="")
    db.refresh(entry)
    assert entry.notes is None


# --- route-level -----------------------------------------------------------


def test_create_entry_route_accepts_notes(client):
    response = client.post(
        "/sections/sinking_fund/entries",
        data={"name": "Emergency", "amount": "500.00", "notes": "3 mo cushion"},
    )
    assert response.status_code == 200
    assert "3 mo cushion" in response.text


def test_update_entry_notes_via_save_route(client):
    client.post(
        "/sections/food/entries",
        data={"name": "Groceries", "amount": "400.00"},
    )
    response = client.post(
        "/entries/1",
        data={"name": "Groceries", "amount": "400.00", "notes": "weekly"},
    )
    assert response.status_code == 200
    assert "weekly" in response.text


def test_update_entry_notes_empty_clears_via_save_route(client):
    client.post(
        "/sections/food/entries",
        data={"name": "Groceries", "amount": "400.00", "notes": "weekly"},
    )
    response = client.post(
        "/entries/1",
        data={"name": "Groceries", "amount": "400.00", "notes": ""},
    )
    assert response.status_code == 200
    assert "note-badge" not in response.text


def test_old_entry_notes_route_is_removed(client):
    client.post(
        "/sections/food/entries",
        data={"name": "Groceries", "amount": "400.00"},
    )
    response = client.post("/entries/1/notes", data={"notes": "weekly"})
    assert response.status_code == 404


def test_create_month_entry_route_accepts_notes(client):
    client.post("/month/2026-04/create")
    response = client.post(
        "/month/2026-04/sections/other/entries",
        data={"name": "Gift", "planned": "25.00", "notes": "birthday"},
    )
    assert response.status_code == 200
    assert "birthday" in response.text


def test_update_month_entry_route_accepts_notes(client):
    client.post(
        "/sections/fixed_bill/entries",
        data={"name": "Rent", "amount": "1200.00"},
    )
    client.post("/month/2026-04/create")
    response = client.post(
        "/month/2026-04/entries/1", data={"notes": "auto-pay"}
    )
    assert response.status_code == 200
    assert "auto-pay" in response.text


def test_budget_page_renders_note_badge_when_notes_set(client):
    client.post(
        "/sections/fixed_bill/entries",
        data={"name": "Rent", "amount": "1200.00", "notes": "due 1st"},
    )
    response = client.get("/")
    assert response.status_code == 200
    assert "note-badge" in response.text
    assert "due 1st" in response.text


def test_budget_page_omits_note_badge_when_notes_empty(client):
    client.post(
        "/sections/food/entries",
        data={"name": "Groceries", "amount": "400.00"},
    )
    response = client.get("/")
    assert response.status_code == 200
    assert "note-badge" not in response.text


def test_month_page_renders_notes_inputs(client):
    client.post(
        "/sections/fixed_bill/entries",
        data={"name": "Rent", "amount": "1200.00", "notes": "auto-pay"},
    )
    client.post("/month/2026-04/create")
    response = client.get("/month/2026-04")
    assert response.status_code == 200
    # notes input lives inside the expandable entry body now
    assert 'name="notes"' in response.text
    assert "auto-pay" in response.text
