from __future__ import annotations

from typing import Any

from fastapi import HTTPException, status

from backend.auth.dependencies import (
    UserPrincipal,
    create_access_token,
    default_tenant_id,
    verify_password,
)
from backend.auth.user_directory import ensure_user_directory_schema


async def _get_pool(app: Any):
    pool = getattr(app.state, "db_pool", None)
    if pool is None:
        raise HTTPException(status_code=503, detail="Database unavailable.")
    return pool


async def login_with_directory(*, app: Any, email: str, password: str) -> dict[str, Any]:
    await ensure_user_directory_schema(app)
    pool = await _get_pool(app)
    tenant_fallback = default_tenant_id()

    async with pool.acquire() as conn:
        row = await conn.fetchrow(
            """
            SELECT
                id::text,
                role,
                password_hash,
                COALESCE(NULLIF(tenant_id, ''), $2) AS tenant_id
            FROM users_and_roles
            WHERE email = $1 AND is_active = TRUE
            """,
            email.strip(),
            tenant_fallback,
        )

    if not row or not verify_password(password, row["password_hash"]):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid email or password.",
        )

    token = create_access_token(
        user_id=row["id"],
        role=row["role"],
        tenant_id=row["tenant_id"],
    )
    return {"access_token": token, "token_type": "bearer", "expires_in": 28800}


async def read_authenticated_user_profile(*, app: Any, user: UserPrincipal) -> dict[str, Any]:
    await ensure_user_directory_schema(app)
    pool = await _get_pool(app)
    tenant_scope = user.tenant_id or default_tenant_id()

    async with pool.acquire() as conn:
        row = await conn.fetchrow(
            """
            SELECT
                full_name,
                email,
                avatar_url,
                COALESCE(NULLIF(tenant_id, ''), $2) AS tenant_id
            FROM users_and_roles
            WHERE id = $1::uuid
              AND COALESCE(NULLIF(tenant_id, ''), $2) = $2
            """,
            user.user_id,
            tenant_scope,
        )

    return {
        "user_id": user.user_id,
        "role": user.role,
        "tenant_id": row["tenant_id"] if row else tenant_scope,
        "full_name": row["full_name"] if row else None,
        "email": row["email"] if row else None,
        "avatar_url": row["avatar_url"] if row else None,
    }


async def list_tenant_users(*, app: Any, user: UserPrincipal) -> list[dict[str, Any]]:
    await ensure_user_directory_schema(app)
    pool = await _get_pool(app)
    tenant_scope = user.tenant_id or default_tenant_id()

    async with pool.acquire() as conn:
        rows = await conn.fetch(
            """
            SELECT
                id::text AS user_id,
                role,
                COALESCE(NULLIF(tenant_id, ''), $1) AS tenant_id,
                full_name,
                email,
                avatar_url
            FROM users_and_roles
            WHERE is_active = TRUE
              AND COALESCE(NULLIF(tenant_id, ''), $1) = $2
            ORDER BY
                COALESCE(NULLIF(full_name, ''), email, id::text) ASC
            """,
            default_tenant_id(),
            tenant_scope,
        )

    return [
        {
            "user_id": row["user_id"],
            "role": row["role"],
            "tenant_id": row["tenant_id"],
            "full_name": row["full_name"],
            "email": row["email"],
            "avatar_url": row["avatar_url"],
        }
        for row in rows
    ]
