"""Loyalty is a signed, immutable integer-points ledger: earn positive, redeem negative."""
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 workspace(client, user, name="Loyalty Store"):
    response = client.post("/api/businesses/onboarding", json={"name": name, "main_branch_name": "Main", "country": "Nigeria", "currency": "NGN", "default_language": "en"}, headers=h(user))
    assert response.status_code == 201, response.text
    return response.json()

def customer(client, user, business):
    response = client.post(f"/api/businesses/{business}/customers", json={"name": "Loyal Customer"}, headers=h(user))
    assert response.status_code == 201
    return response.json()["id"]

def completed_sale(client, user, business, branch, customer_id, total="5500"):
    product = client.post(f"/api/businesses/{business}/products", json={"name": "Loyal Product", "product_type": "SINGLE", "selling_price": total, "track_stock": False}, headers=h(user)).json()
    response = client.post(f"/api/businesses/{business}/sales", json={"branch_id": branch, "customer_id": customer_id, "receipt_number": "LOYAL-1", "items": [{"product_id": product["id"], "quantity": "1", "unit_price": total}], "payments": [{"amount": total, "payment_method": "CASH"}]}, headers={**h(user), "Idempotency-Key": "loyal-sale"})
    assert response.status_code == 201, response.text
    return response.json()["sale"]["id"]

def test_settings_earning_redemption_history_and_duplicate_protection(client, verified_user):
    w = workspace(client, verified_user); business = w["business"]["id"]; branch = w["accessible_branches"][0]["id"]
    assert client.get(f"/api/businesses/{business}/loyalty/settings", headers=h(verified_user)).json()["enabled"] is False
    configured = client.patch(f"/api/businesses/{business}/loyalty/settings", json={"enabled": True, "earn_amount": "1000", "earn_points": 1}, headers=h(verified_user))
    assert configured.status_code == 200
    cid = customer(client, verified_user, business); sid = completed_sale(client, verified_user, business, branch, cid)
    earned = client.post(f"/api/businesses/{business}/sales/{sid}/loyalty/earn", headers=h(verified_user))
    assert earned.status_code == 200 and earned.json()["created"] is True and earned.json()["transaction"]["points"] == 5
    retry = client.post(f"/api/businesses/{business}/sales/{sid}/loyalty/earn", headers=h(verified_user))
    assert retry.status_code == 200 and retry.json()["created"] is False
    assert client.get(f"/api/businesses/{business}/customers/{cid}/loyalty", headers=h(verified_user)).json()["current_points"] == 5
    assert client.post(f"/api/businesses/{business}/customers/{cid}/loyalty/redeem", json={"points": 3}, headers=h(verified_user)).status_code == 200
    assert client.post(f"/api/businesses/{business}/customers/{cid}/loyalty/redeem", json={"points": 3}, headers=h(verified_user)).status_code == 422
    history = client.get(f"/api/businesses/{business}/customers/{cid}/loyalty/history", headers=h(verified_user))
    assert history.status_code == 200 and len(history.json()) == 2

def test_disabled_and_cross_business_loyalty_are_rejected(client, verified_user):
    one = workspace(client, verified_user); two = 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-loyal"}).json()
    b1, b2 = one["business"]["id"], two["business"]["id"]
    cid = customer(client, verified_user, b1)
    assert client.get(f"/api/businesses/{b2}/customers/{cid}/loyalty", headers=h(verified_user)).status_code == 404
    assert client.post(f"/api/businesses/{b1}/customers/{cid}/loyalty/redeem", json={"points": 1}, headers=h(verified_user)).status_code == 422
    assert client.post(f"/api/businesses/{b1}/customers/{cid}/loyalty/redeem", json={"points": 0}, headers=h(verified_user)).status_code == 422

def test_adjustment_requires_loyalty_management_permission(client, verified_user):
    import uuid
    from app.db.session import SessionLocal
    from app.models.membership import Membership
    from app.models.user import User
    from app.core.security import hash_password
    w = workspace(client, verified_user); business = w["business"]["id"]; cid = customer(client, verified_user, business)
    db = SessionLocal(); cashier = User(full_name="Cashier", email=f"loyal-cashier-{uuid.uuid4().hex}@example.com", password_hash=hash_password("TestPassword123!"), is_email_verified=True); db.add(cashier); db.flush(); db.add(Membership(business_id=business, user_id=cashier.id, role="CASHIER")); db.commit()
    try:
        assert client.post(f"/api/businesses/{business}/customers/{cid}/loyalty/adjust", json={"points": 2, "notes": "welcome"}, headers=h(cashier)).status_code == 403
        assert client.post(f"/api/businesses/{business}/customers/{cid}/loyalty/adjust", json={"points": 2, "notes": "welcome"}, headers=h(verified_user)).status_code == 200
        assert client.post(f"/api/businesses/{business}/customers/{cid}/loyalty/adjust", json={"points": -3, "notes": "correction"}, headers=h(verified_user)).status_code == 422
    finally:
        from sqlalchemy import delete
        db.execute(delete(Membership).where(Membership.user_id == cashier.id))
        db.execute(delete(User).where(User.id == cashier.id))
        db.commit()
        db.close()
