"""Debt book coverage against completed, real sales."""
from datetime import date, datetime, timedelta, timezone
from decimal import Decimal

import pytest

pytest_plugins = ("test_workspace",)


def h(user):
    from app.core.security import create_access_token
    return {"Authorization": f"Bearer {create_access_token(str(user.id))}"}


def setup_sale(client, user, paid="0", receipt="R-1"):
    w = client.post("/api/businesses/onboarding", json={"name":"Debt", "main_branch_name":"Main", "country":"Nigeria", "currency":"NGN", "default_language":"en"}, headers=h(user)).json()
    b, branch = w["business"]["id"], w["accessible_branches"][0]["id"]
    p = client.post(f"/api/businesses/{b}/products", json={"name":"Product", "product_type":"SINGLE", "selling_price":"100"}, headers=h(user)).json()
    client.post(f"/api/businesses/{b}/branches/{branch}/stock-adjustments", json={"product_id":p["id"], "quantity_changed":"10", "reason":"RESTOCK"}, headers=h(user))
    c = client.post(f"/api/businesses/{b}/customers", json={"name":"Customer"}, headers=h(user)).json()
    body={"branch_id":branch,"customer_id":c["id"],"receipt_number":receipt,"items":[{"product_id":p["id"],"quantity":"1","unit_price":"100"}],"payments":[] if paid=="0" else [{"amount":paid,"payment_method":"CASH"}]}
    sale=client.post(f"/api/businesses/{b}/sales",json=body,headers={**h(user),"Idempotency-Key":receipt}).json()["sale"]
    return b,c,sale,body


def test_paid_sale_has_no_receivable(client, verified_user):
    b, _, _, _ = setup_sale(client, verified_user, "100", "paid")
    assert client.get(f"/api/businesses/{b}/receivables",headers=h(verified_user)).json() == []


def test_credit_sale_creates_one_receivable_on_idempotent_retry(client, verified_user):
    b, _, sale, body = setup_sale(client, verified_user, "20", "credit")
    rows=client.get(f"/api/businesses/{b}/receivables",headers=h(verified_user)).json()
    assert len(rows)==1 and rows[0]["original_amount"]==80.0 and rows[0]["sale_id"]==sale["id"]
    assert client.post(f"/api/businesses/{b}/sales",json=body,headers={**h(verified_user),"Idempotency-Key":"credit"}).status_code==201
    assert len(client.get(f"/api/businesses/{b}/receivables",headers=h(verified_user)).json())==1


def test_collection_updates_sale_and_ledgers_and_rejects_invalid_amounts(client, verified_user):
    b, customer, sale, _ = setup_sale(client, verified_user, "20", "collect")
    r=client.get(f"/api/businesses/{b}/receivables",headers=h(verified_user)).json()[0]
    url=f"/api/businesses/{b}/receivables/{r['id']}/collections"
    assert client.post(url,json={"amount":"30","payment_method":"TRANSFER","reference":"bank"},headers=h(verified_user)).status_code==201
    assert client.get(f"/api/businesses/{b}/sales/{sale['id']}",headers=h(verified_user)).json()["sale"]["balance"]==50.0
    assert len(client.get(f"/api/businesses/{b}/sales/{sale['id']}/payments",headers=h(verified_user)).json())==2
    assert client.post(url,json={"amount":"0","payment_method":"CASH"},headers=h(verified_user)).status_code==422
    assert client.post(url,json={"amount":"51","payment_method":"CASH"},headers=h(verified_user)).status_code==422
    assert client.post(url,json={"amount":"50","payment_method":"CASH"},headers=h(verified_user)).status_code==201
    assert client.post(url,json={"amount":"1","payment_method":"CASH"},headers=h(verified_user)).status_code==422
    summary=client.get(f"/api/businesses/{b}/customers/{customer['id']}/receivables",headers=h(verified_user)).json()
    assert summary["total_outstanding"]==0.0 and len(summary["collections"])==2
    assert [e["event_type"] for e in client.get(f"/api/businesses/{b}/customers/{customer['id']}/statement",headers=h(verified_user)).json()] == ["CREDIT_SALE", "COLLECTION", "COLLECTION"]


def test_aging_and_business_isolation(client, verified_user):
    b, _, _, _ = setup_sale(client, verified_user, "0", "aging")
    r=client.get(f"/api/businesses/{b}/receivables",headers=h(verified_user)).json()[0]
    from app.db.session import SessionLocal
    from app.models.receivable import Receivable
    db=SessionLocal(); obj=db.get(Receivable,r["id"]); obj.due_date=datetime.now(timezone.utc).date()-timedelta(days=31); db.commit(); db.close()
    aging=client.get(f"/api/businesses/{b}/receivables/aging",headers=h(verified_user)).json()
    assert aging[0]["aging_bucket"]=="31_60"
    other=client.post("/api/businesses",json={"name":"Other", "main_branch_name":"Main", "country":"Nigeria", "currency":"NGN", "default_language":"en"},headers={**h(verified_user),"Idempotency-Key":"other"}).json()["business"]["id"]
    assert client.get(f"/api/businesses/{other}/receivables",headers=h(verified_user)).json()==[]
    assert client.get(f"/api/businesses/{other}/receivables/{r['id']}",headers=h(verified_user)).status_code==404


def test_receivables_require_finance_permission(client, verified_user):
    business_id, customer, _, _ = setup_sale(client, verified_user, "0", "finance-permission")
    from app.db.session import SessionLocal
    from app.models.membership import Membership
    from sqlalchemy import select
    db = SessionLocal()
    membership = db.scalar(select(Membership).where(Membership.business_id == business_id, Membership.user_id == verified_user.id))
    membership.role = "STOREKEEPER"
    db.commit()
    db.close()

    assert client.get(f"/api/businesses/{business_id}/receivables", headers=h(verified_user)).status_code == 403
    assert client.get(f"/api/businesses/{business_id}/customers/{customer['id']}/statement", headers=h(verified_user)).status_code == 403
