"""Regression tests for the invoice CRUD endpoints alongside PUT edit:

- POST /api/invoices                  -> create still works
- GET  /api/invoices/{id}             -> read still works
- PUT  /api/invoices/{id}             -> 7 invoice types preserve invoice_no/type/created_at
- PUT  /api/invoices/{id}             -> cancelled invoice keeps status=cancelled (untouched)
- DELETE /api/invoices/{id}           -> soft delete works (subsequent GET 404)
"""
from tests.conftest import BASE_URL

INVOICE_TYPES = [
    "sale", "purchase", "quotation", "sale_order",
    "proforma", "credit_note", "debit_note",
]


def _payload(t, *, party="REG-PARTY", qty=1, rate=100):
    return {
        "type": t,
        "party_name": party,
        "party_state": "Goa",
        "invoice_date": "2026-05-30",
        "lines": [{"name": "Item", "qty": qty, "unit": "PCS", "rate": rate, "gst_rate": 18, "discount": 0}],
        "extra_discount": 0, "round_off": 0, "tax_inclusive": False,
        "payment_received": 0, "payment_mode": "Cash", "status": "unpaid",
    }


def _post(s, cid, t, **kw):
    r = s.post(f"{BASE_URL}/api/invoices?company_id={cid}", json=_payload(t, **kw), timeout=30)
    assert r.status_code == 200, f"POST {t} -> {r.status_code} {r.text}"
    return r.json()


def test_post_invoice_create_regression(admin_session, default_company_id):
    inv = _post(admin_session, default_company_id, "sale", party="REG-POST")
    assert inv["id"] and inv["invoice_no"]
    assert inv["type"] == "sale"
    admin_session.delete(f"{BASE_URL}/api/invoices/{inv['id']}", timeout=30)


def test_get_invoice_regression(admin_session, default_company_id):
    inv = _post(admin_session, default_company_id, "sale", party="REG-GET")
    r = admin_session.get(f"{BASE_URL}/api/invoices/{inv['id']}", timeout=30)
    assert r.status_code == 200
    assert r.json()["id"] == inv["id"]
    admin_session.delete(f"{BASE_URL}/api/invoices/{inv['id']}", timeout=30)


def test_delete_invoice_soft_delete_regression(admin_session, default_company_id):
    inv = _post(admin_session, default_company_id, "sale", party="REG-DEL")
    r = admin_session.delete(f"{BASE_URL}/api/invoices/{inv['id']}", timeout=30)
    assert r.status_code == 200, r.text
    # After soft delete, GET should return 404
    r = admin_session.get(f"{BASE_URL}/api/invoices/{inv['id']}", timeout=30)
    assert r.status_code == 404


def test_put_invoice_preserves_type_and_invoice_no_all_types(admin_session, default_company_id):
    """For each invoice type, PUT must preserve invoice_no, type and created_at."""
    for t in INVOICE_TYPES:
        inv = _post(admin_session, default_company_id, t, party=f"REG-TYPE-{t}")
        original_no = inv["invoice_no"]
        original_created = inv.get("created_at")
        # Edit: change party + bump qty
        payload = _payload(t, party=f"REG-TYPE-{t}-EDITED", qty=5, rate=200)
        r = admin_session.put(f"{BASE_URL}/api/invoices/{inv['id']}", json=payload, timeout=30)
        assert r.status_code == 200, f"PUT {t}: {r.status_code} {r.text}"
        out = r.json()
        assert out["invoice_no"] == original_no, f"{t} invoice_no changed"
        assert out["type"] == t, f"{t} type changed to {out['type']}"
        if original_created:
            assert out.get("created_at") == original_created, f"{t} created_at mutated"
        assert out["party_name"] == f"REG-TYPE-{t}-EDITED"
        admin_session.delete(f"{BASE_URL}/api/invoices/{inv['id']}", timeout=30)


def test_put_invoice_blocked_when_cancelled(admin_session, default_company_id):
    """If the invoice is in cancelled state, PUT must reject the edit (400)."""
    inv = _post(admin_session, default_company_id, "sale", party="REG-CANCEL")
    inv_id = inv["id"]
    # Cancel the invoice via dedicated endpoint if available, else direct DB-like soft delete:
    r = admin_session.post(f"{BASE_URL}/api/invoices/{inv_id}/cancel", timeout=30)
    if r.status_code not in (200, 204):
        # No cancel endpoint - skip this test gracefully
        admin_session.delete(f"{BASE_URL}/api/invoices/{inv_id}", timeout=30)
        import pytest
        pytest.skip(f"No /cancel endpoint (got {r.status_code}); cancellation flow not exercised here")
    # Now PUT should be rejected with 400
    payload = _payload("sale", party="REG-CANCEL-EDIT")
    r = admin_session.put(f"{BASE_URL}/api/invoices/{inv_id}", json=payload, timeout=30)
    assert r.status_code == 400, f"cancelled invoice should reject PUT, got {r.status_code}: {r.text}"
    admin_session.delete(f"{BASE_URL}/api/invoices/{inv_id}", timeout=30)
