"""Shared pytest fixtures."""
from __future__ import annotations

from collections.abc import Generator

import pytest
from flask import Flask
from flask.testing import FlaskClient

from backend.app import create_app
from backend.app.auth import hash_password
from backend.app.config import TestConfig
from backend.app.extensions import db
from backend.app.models import User, UserRole


@pytest.fixture()
def app() -> Generator[Flask, None, None]:
    application = create_app(TestConfig())
    with application.app_context():
        db.create_all()
        yield application
        db.session.remove()
        db.drop_all()


@pytest.fixture()
def client(app: Flask) -> FlaskClient:
    return app.test_client()


@pytest.fixture()
def admin_user(app: Flask) -> User:
    user = User(
        username="admin1",
        password_hash=hash_password("adminpass1"),
        role=UserRole.ADMIN,
    )
    db.session.add(user)
    db.session.commit()
    return user


@pytest.fixture()
def redteam_user(app: Flask) -> User:
    user = User(
        username="redteam1",
        password_hash=hash_password("redteampass1"),
        role=UserRole.REDTEAM,
    )
    db.session.add(user)
    db.session.commit()
    return user


@pytest.fixture()
def soc_user(app: Flask) -> User:
    user = User(
        username="soc1",
        password_hash=hash_password("socpass1"),
        role=UserRole.SOC,
    )
    db.session.add(user)
    db.session.commit()
    return user


def _login(client: FlaskClient, username: str, password: str) -> str:
    resp = client.post(
        "/api/auth/login", json={"username": username, "password": password}
    )
    assert resp.status_code == 200, resp.get_json()
    return resp.get_json()["access_token"]


@pytest.fixture()
def admin_token(client: FlaskClient, admin_user: User) -> str:
    return _login(client, "admin1", "adminpass1")


@pytest.fixture()
def redteam_token(client: FlaskClient, redteam_user: User) -> str:
    return _login(client, "redteam1", "redteampass1")


@pytest.fixture()
def soc_token(client: FlaskClient, soc_user: User) -> str:
    return _login(client, "soc1", "socpass1")


def auth_headers(token: str) -> dict[str, str]:
    return {"Authorization": f"Bearer {token}"}
