"""INDL-59 — Plan-based feature gating for the Billing page Invoices table.

Resolves PRD Open Question #3: the Billing page's Invoices table is backed
by `GET /api/v1/billing/invoices` (src/apps/billing/router.py) — a distinct
component from the Sales & Contracts "Invoices" tab, NOT the same endpoint
reused. It is gated behind `require_feature("billingInvoicesTab")`.
`/billing/subscription` (plan info + Update Plan) stays ungated on every
plan — Starter tenants must still be able to view/change their own plan.
"""
from uuid import uuid4

import pytest
from httpx import AsyncClient
from sqlalchemy.ext.asyncio import AsyncSession

from src.apps.auth.models.user import User
from src.apps.tenants.models.account import Account
from src.core.security import build_token_payload, create_access_token, hash_password

INVOICES_URL = "/api/v1/billing/invoices"
SUBSCRIPTION_URL = "/api/v1/billing/subscription"


async def _make_account(db: AsyncSession, *, plan: str) -> Account:
    uid = uuid4().hex[:8]
    acc = Account(
        organization_name=f"Plan Gate Cemetery {uid}",
        subdomain=f"plangate-billing-{uid}",
        contact_email=f"admin-{uid}@plangate.test",
        plan=plan,
        status="active",
    )
    db.add(acc)
    await db.flush()
    return acc


async def _make_token(db: AsyncSession, account: Account) -> str:
    user = User(
        tenant_id=account.id,
        email=f"admin-{uuid4().hex[:6]}@plangate.test",
        password_hash=hash_password("Test1234!"),
        first_name="Admin",
        last_name="User",
        role="administrator",
        status="active",
    )
    db.add(user)
    await db.flush()
    return create_access_token(build_token_payload(user, account))


def _headers(token: str, account: Account) -> dict:
    return {"Authorization": f"Bearer {token}", "X-Tenant-ID": str(account.id)}


@pytest.mark.asyncio
async def test_starter_tenant_is_403_on_invoices(client: AsyncClient, db_session: AsyncSession):
    acc = await _make_account(db_session, plan="starter")
    token = await _make_token(db_session, acc)

    resp = await client.get(INVOICES_URL, headers=_headers(token, acc))

    assert resp.status_code == 403


@pytest.mark.parametrize("plan", ["professional", "enterprise"])
@pytest.mark.asyncio
async def test_paid_plans_pass_invoices_plan_gate(
    client: AsyncClient, db_session: AsyncSession, plan
):
    acc = await _make_account(db_session, plan=plan)
    token = await _make_token(db_session, acc)

    resp = await client.get(INVOICES_URL, headers=_headers(token, acc))

    assert resp.status_code == 200


@pytest.mark.asyncio
async def test_starter_tenant_still_reaches_ungated_subscription_endpoint(
    client: AsyncClient, db_session: AsyncSession
):
    """A Starter tenant must still be able to view/change their own plan."""
    acc = await _make_account(db_session, plan="starter")
    token = await _make_token(db_session, acc)

    resp = await client.get(SUBSCRIPTION_URL, headers=_headers(token, acc))

    assert resp.status_code == 200
