from fastapi import Depends, FastAPI
from fastapi.testclient import TestClient

from services.shared.core import Role
from services.shared.security import get_actor, issue_app_token, require_roles


def build_app() -> FastAPI:
    app = FastAPI()

    @app.get('/actor')
    def actor_view(actor: dict = Depends(get_actor)) -> dict:
        return actor

    @app.get('/admin')
    def admin_view(_: dict = Depends(require_roles(Role.ADMIN))) -> dict:
        return {'ok': True}

    return app


def test_valid_bearer_token_resolves_actor(monkeypatch):
    monkeypatch.setenv('APP_TOKEN_SECRET', 'track1-secret')
    client = TestClient(build_app())
    token = issue_app_token(
        subject='usr_1',
        username='alice',
        role='admin',
        auth_source='oidc',
        provider='keycloak',
    )

    response = client.get('/actor', headers={'Authorization': f'Bearer {token}'})

    assert response.status_code == 200
    body = response.json()
    assert body['user'] == 'alice'
    assert body['role'] == 'admin'
    assert body['auth_source'] == 'oidc'


def test_invalid_bearer_token_returns_401(monkeypatch):
    monkeypatch.setenv('APP_TOKEN_SECRET', 'track1-secret')
    client = TestClient(build_app())

    response = client.get('/actor', headers={'Authorization': 'Bearer broken.token.value'})

    assert response.status_code == 401


def test_legacy_header_auth_can_be_disabled(monkeypatch):
    monkeypatch.setenv('ALLOW_LEGACY_HEADER_AUTH', '0')
    client = TestClient(build_app())

    response = client.get('/admin', headers={'X-User': 'admin', 'X-Role': 'admin'})

    assert response.status_code == 403


def test_bearer_token_can_use_tenant_header_when_legacy_auth_disabled(monkeypatch):
    monkeypatch.setenv('APP_TOKEN_SECRET', 'track1-secret')
    monkeypatch.setenv('ALLOW_LEGACY_HEADER_AUTH', '0')
    client = TestClient(build_app())
    token = issue_app_token(
        subject='usr_1',
        username='alice',
        role='admin',
        auth_source='local',
    )

    response = client.get(
        '/actor',
        headers={'Authorization': f'Bearer {token}', 'X-Tenant-ID': 'default'},
    )

    assert response.status_code == 200
    body = response.json()
    assert body['user'] == 'alice'
    assert body['role'] == 'admin'
    assert body['tenant_id'] == 'default'
    assert body['tenant_source'] == 'header'


def test_bearer_token_tenant_takes_precedence_over_header(monkeypatch):
    monkeypatch.setenv('APP_TOKEN_SECRET', 'track1-secret')
    client = TestClient(build_app())
    token = issue_app_token(
        subject='usr_1',
        username='alice',
        role='admin',
        auth_source='oidc',
        tenant_id='token-tenant',
    )

    response = client.get(
        '/actor',
        headers={'Authorization': f'Bearer {token}', 'X-Tenant-ID': 'header-tenant'},
    )

    assert response.status_code == 200
    body = response.json()
    assert body['tenant_id'] == 'token-tenant'
    assert body['tenant_source'] == 'token'


def test_legacy_header_auth_still_works_when_enabled(monkeypatch):
    monkeypatch.setenv('ALLOW_LEGACY_HEADER_AUTH', '1')
    client = TestClient(build_app())

    response = client.get('/admin', headers={'X-User': 'admin', 'X-Role': 'admin'})

    assert response.status_code == 200
