from __future__ import annotations

import os
import re
from datetime import datetime, timezone
from pathlib import Path

from fastapi import APIRouter, Depends, File, HTTPException, Request, UploadFile, status
from pydantic import BaseModel

from backend.auth.dependencies import UserPrincipal, get_current_user
from backend.auth.service import (
    list_tenant_users,
    login_with_directory,
    read_authenticated_user_profile,
)
from backend.auth.user_directory import ensure_user_directory_schema

router = APIRouter()

ASSET_DIR = os.getenv("VELOCITY_ASSET_DIR", "/opt/dlami/nvme/assets")


def _sanitize_filename(value: str) -> str:
    cleaned = re.sub(r"[^A-Za-z0-9._-]+", "_", value).strip("._")
    return cleaned or "upload"


class LoginRequest(BaseModel):
    email: str
    password: str


@router.post("/api/auth/login", tags=["Auth"])
async def login(body: LoginRequest, request: Request):
    """
    Authenticate a user and return a JWT.
    Credentials are verified against the users_and_roles table.
    """
    return await login_with_directory(
        app=request.app,
        email=body.email,
        password=body.password,
    )


@router.get("/api/auth/me", tags=["Auth"])
async def me(request: Request, user: UserPrincipal = Depends(get_current_user)):
    return await read_authenticated_user_profile(app=request.app, user=user)


@router.get("/api/auth/users", tags=["Auth"])
async def list_auth_users(request: Request, user: UserPrincipal = Depends(get_current_user)):
    return await list_tenant_users(app=request.app, user=user)


@router.post("/api/auth/profile/avatar", tags=["Auth"])
async def upload_profile_avatar(
    request: Request,
    file: UploadFile = File(...),
    user: UserPrincipal = Depends(get_current_user),
):
    await ensure_user_directory_schema(request.app)
    pool = getattr(request.app.state, "db_pool", None)
    if pool is None:
        raise HTTPException(status_code=503, detail="Database unavailable.")

    allowed = {"image/png", "image/jpeg", "image/jpg", "image/webp"}
    if file.content_type not in allowed:
        raise HTTPException(status_code=400, detail="Unsupported avatar format.")

    extension = Path(file.filename or "avatar.png").suffix.lower() or ".png"
    if extension not in {".png", ".jpg", ".jpeg", ".webp"}:
        extension = ".png"

    avatar_dir = Path(ASSET_DIR) / "profile_avatars"
    avatar_dir.mkdir(parents=True, exist_ok=True)

    filename = (
        f"{user.user_id}_{_sanitize_filename(Path(file.filename or 'avatar').stem)}_"
        f"{int(datetime.now(timezone.utc).timestamp())}{extension}"
    )
    destination = avatar_dir / filename
    contents = await file.read()
    destination.write_bytes(contents)

    avatar_url = f"/assets/profile_avatars/{filename}"

    async with pool.acquire() as conn:
        result = await conn.execute(
            """
            UPDATE users_and_roles
            SET avatar_url = $2
            WHERE id = $1::uuid
              AND tenant_id = $3
            """,
            user.user_id,
            avatar_url,
            user.tenant_id,
        )

    if result == "UPDATE 0":
        raise HTTPException(status_code=404, detail="Authenticated user profile was not found.")

    return {"avatar_url": avatar_url}
