"""Covers Pillar 7's defense-in-depth: a vendor token (a User with
vendor_id set, from the Public Portal) must never be able to hit a studio
*design* endpoint (Masters/Forms/Workflows/Pages/Dashboards/Menus/Roles/
Users schema CRUD) even if it somehow held a role with the matching
action_matrix permission — see app/core/permissions.py::deny_vendor.
Also covers menus.audience: a vendor-facing portal should be able to filter
on it once GET /menus returns it."""

import uuid

from app.core.auth import create_access_token
from tests.conftest import AsyncSessionLocal
from app.models.identity import Role, User, UserRole


async def _vendor_token_with_full_access(tenant_id: uuid.UUID) -> str:
    """A vendor user holding an is_system_role role — the strongest possible
    action_matrix a caller could have — to prove deny_vendor blocks on
    vendor_id alone, independent of permissions."""
    async with AsyncSessionLocal() as db:
        async with db.begin():
            role = Role(tenant_id=tenant_id, name="Vendor Super Role", is_system_role=True, action_matrix={})
            db.add(role)
            await db.flush()
            vendor_user = User(
                tenant_id=tenant_id, name="Vendor User", email=f"vendor-{role.id}@example.com", status="active"
            )
            db.add(vendor_user)
            await db.flush()
            db.add(UserRole(user_id=vendor_user.id, role_id=role.id))
            await db.flush()
            user_id = vendor_user.id

    return create_access_token(tenant_id=tenant_id, user_id=user_id, vendor_id=uuid.uuid4())


async def test_vendor_token_cannot_create_master(client, test_tenant):
    token = await _vendor_token_with_full_access(test_tenant["tenant_id"])
    resp = await client.post(
        "/masters",
        headers={"Authorization": f"Bearer {token}"},
        json={"name": "Vendor Should Not Create This", "field_schema": [{"name": "x", "type": "text"}]},
    )
    assert resp.status_code == 403


async def test_vendor_token_cannot_create_menu(client, test_tenant):
    token = await _vendor_token_with_full_access(test_tenant["tenant_id"])
    resp = await client.post(
        "/menus",
        headers={"Authorization": f"Bearer {token}"},
        json={"label": "Vendor Menu", "icon": "Home", "link_type": "existing_feature", "linked_screen": "Masters.dc.html"},
    )
    assert resp.status_code == 403


async def test_vendor_token_cannot_create_user(client, test_tenant):
    token = await _vendor_token_with_full_access(test_tenant["tenant_id"])
    resp = await client.post(
        "/users",
        headers={"Authorization": f"Bearer {token}"},
        json={"name": "Should Not Be Created", "email": "nope@example.com", "password": "password123"},
    )
    assert resp.status_code == 403


async def test_vendor_token_cannot_create_role(client, test_tenant):
    token = await _vendor_token_with_full_access(test_tenant["tenant_id"])
    resp = await client.post(
        "/roles",
        headers={"Authorization": f"Bearer {token}"},
        json={"name": "Should Not Be Created", "action_matrix": {}},
    )
    assert resp.status_code == 403


async def test_vendor_token_can_still_view_menus(client, test_tenant):
    """deny_vendor is only wired onto mutating menu endpoints — a vendor
    still needs GET /menus to render their portal nav."""
    token = await _vendor_token_with_full_access(test_tenant["tenant_id"])
    resp = await client.get("/menus", headers={"Authorization": f"Bearer {token}"})
    assert resp.status_code == 200


async def test_non_vendor_token_unaffected_by_deny_vendor(client, auth_headers):
    """The admin fixture has no vendor_id — deny_vendor must be a no-op for it."""
    resp = await client.post(
        "/masters",
        headers=auth_headers,
        json={"name": "Non-Vendor Create Still Works", "field_schema": [{"name": "x", "type": "text"}]},
    )
    assert resp.status_code == 201


async def test_menu_audience_defaults_to_internal_and_can_be_set(client, auth_headers):
    create_resp = await client.post(
        "/menus",
        headers=auth_headers,
        json={"label": "Default Audience", "icon": "Home", "link_type": "existing_feature", "linked_screen": "Masters.dc.html"},
    )
    assert create_resp.status_code == 201
    assert create_resp.json()["audience"] == "internal"

    vendor_resp = await client.post(
        "/menus",
        headers=auth_headers,
        json={
            "label": "Vendor Facing",
            "icon": "Home",
            "link_type": "existing_feature",
            "linked_screen": "Masters.dc.html",
            "audience": "vendor",
        },
    )
    assert vendor_resp.status_code == 201
    assert vendor_resp.json()["audience"] == "vendor"
