"""INDL-59 — Plan-based feature gating for AI record extraction.

`POST /api/v1/ai/extract-record` is the backing route for the "Upload &
auto-fill" AI record-extraction feature, gated behind
`require_feature("aiRecordExtraction")`. Starter (manual upload only) must
403; Professional and Enterprise both pass the gate — corrected on
stakeholder review from an earlier Enterprise-only iteration of this matrix.

The gate is checked before the request body, so these tests send no file and
assert only that Starter is refused and the paid plans get past the gate.
"""
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

URL = "/api/v1/ai/extract-record"


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-ai-{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"staff-{uuid4().hex[:6]}@plangate.test",
        password_hash=hash_password("Test1234!"),
        first_name="Staff",
        last_name="User",
        role="staff",
        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_is_403_on_ai_extract_record(client: AsyncClient, db_session: AsyncSession):
    acc = await _make_account(db_session, plan="starter")
    token = await _make_token(db_session, acc)

    resp = await client.post(URL, headers=_headers(token, acc))

    assert resp.status_code == 403
    assert "Professional and Enterprise" in resp.json()["message"]


@pytest.mark.parametrize("plan", ["professional", "enterprise"])
@pytest.mark.asyncio
async def test_professional_and_enterprise_pass_the_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.post(URL, headers=_headers(token, acc))

    # 422 = past the plan gate, rejected by FastAPI for the missing `file`
    # part. Anything but 403 proves the gate let this plan through.
    assert resp.status_code != 403
    assert resp.status_code == 422
