"""Security tests — auth required and error hygiene."""
from __future__ import annotations

import pytest
from httpx import ASGITransport, AsyncClient

from app.core.config import settings
from app.core.security import get_current_user
from app.main import app
from app.tests.conftest import TENANT_A, tenant_headers
from shared.exceptions import UnauthorizedError
from shared.security import CurrentUser


@pytest.mark.asyncio
async def test_unauthenticated_denied_when_auth_required(db_setup, monkeypatch):
    monkeypatch.setattr(settings, "auth_required", True)

    async def _deny():
        raise UnauthorizedError("توکن احراز هویت ارائه نشده است")

    app.dependency_overrides[get_current_user] = _deny
    try:
        transport = ASGITransport(app=app)
        async with AsyncClient(transport=transport, base_url="http://testserver") as ac:
            resp = await ac.get(
                "/api/v1/programs", headers=tenant_headers(TENANT_A)
            )
        assert resp.status_code == 401
        body = resp.json()
        assert "error" in body
        assert "traceback" not in str(body).lower()
        assert "superapp_password" not in str(body)
    finally:
        app.dependency_overrides.pop(get_current_user, None)
        monkeypatch.setattr(settings, "auth_required", False)


@pytest.mark.asyncio
async def test_permission_denied_for_viewer_role(db_setup, monkeypatch):
    monkeypatch.setattr(settings, "auth_required", True)

    async def _viewer():
        return CurrentUser(user_id="viewer", roles=["tenant_viewer"])

    app.dependency_overrides[get_current_user] = _viewer
    try:
        transport = ASGITransport(app=app)
        async with AsyncClient(transport=transport, base_url="http://testserver") as ac:
            resp = await ac.post(
                "/api/v1/programs",
                json={"code": "SEC", "name": "Secured"},
                headers=tenant_headers(TENANT_A),
            )
        assert resp.status_code == 403
        assert resp.json()["error"]["code"] in {"forbidden", "permission_denied"}
    finally:
        app.dependency_overrides.pop(get_current_user, None)
        monkeypatch.setattr(settings, "auth_required", False)


@pytest.mark.asyncio
async def test_invalid_tenant_header(client):
    resp = await client.get(
        "/api/v1/programs", headers={"X-Tenant-ID": "not-a-uuid"}
    )
    assert resp.status_code == 400
    assert resp.json()["error"]["code"] == "invalid_tenant_id"
