import secrets
import uuid
from datetime import datetime, timezone

from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session

from app.api.deps import get_current_principal, require_role
from app.core.security import generate_api_key, hash_password
from app.db.session import get_db
from app.models.audit import AuditLog
from app.models.org import User, UserRole
from app.models.stubs import APIKey
from app.schemas.admin import (
    APIKeyOut,
    AuditLogOut,
    CreateAPIKeyRequest,
    CreateAPIKeyResponse,
    CreateUserRequest,
    CreateUserResponse,
    UpdateUserRequest,
    UserOut,
)
from app.services.audit import record_audit

router = APIRouter(prefix="/admin", tags=["admin"])


@router.get("/users", response_model=list[UserOut])
def list_users(db: Session = Depends(get_db), current_user: User = Depends(get_current_principal)):
    return db.query(User).filter(User.org_id == current_user.org_id).order_by(User.created_at).all()


@router.post("/users", response_model=CreateUserResponse, status_code=201)
def create_user(
    payload: CreateUserRequest,
    db: Session = Depends(get_db),
    current_user: User = Depends(require_role(UserRole.admin)),
):
    existing = db.query(User).filter(User.email == payload.email).one_or_none()
    if existing:
        raise HTTPException(status_code=400, detail="Email already registered")

    temp_password = secrets.token_urlsafe(12)
    user = User(
        org_id=current_user.org_id,
        email=payload.email,
        full_name=payload.full_name,
        hashed_password=hash_password(temp_password),
        role=payload.role,
    )
    db.add(user)
    db.commit()
    db.refresh(user)
    record_audit(db, current_user, "user.create", "user", user.id, {"email": user.email, "role": user.role.value})

    return CreateUserResponse(user=user, temporary_password=temp_password)


@router.patch("/users/{user_id}", response_model=UserOut)
def update_user(
    user_id: uuid.UUID,
    payload: UpdateUserRequest,
    db: Session = Depends(get_db),
    current_user: User = Depends(require_role(UserRole.admin)),
):
    user = db.get(User, user_id)
    if user is None or user.org_id != current_user.org_id:
        raise HTTPException(status_code=404, detail="User not found")

    if user.role == UserRole.owner and (payload.role is not None or payload.is_active is False):
        remaining_owners = (
            db.query(User)
            .filter(User.org_id == current_user.org_id, User.role == UserRole.owner, User.id != user.id)
            .count()
        )
        if remaining_owners == 0:
            raise HTTPException(status_code=400, detail="Cannot demote or deactivate the last owner")

    if payload.role is not None:
        user.role = payload.role
    if payload.is_active is not None:
        user.is_active = payload.is_active

    db.commit()
    db.refresh(user)
    record_audit(db, current_user, "user.update", "user", user.id, {"role": user.role.value, "is_active": user.is_active})
    return user


@router.get("/audit-logs", response_model=list[AuditLogOut])
def list_audit_logs(
    action: str | None = Query(default=None),
    resource_type: str | None = Query(default=None),
    limit: int = Query(default=100, le=500),
    db: Session = Depends(get_db),
    current_user: User = Depends(require_role(UserRole.admin)),
):
    q = db.query(AuditLog).filter(AuditLog.org_id == current_user.org_id)
    if action:
        q = q.filter(AuditLog.action == action)
    if resource_type:
        q = q.filter(AuditLog.resource_type == resource_type)
    return q.order_by(AuditLog.created_at.desc()).limit(limit).all()


@router.get("/api-keys", response_model=list[APIKeyOut])
def list_api_keys(db: Session = Depends(get_db), current_user: User = Depends(require_role(UserRole.admin))):
    return (
        db.query(APIKey).filter(APIKey.org_id == current_user.org_id).order_by(APIKey.created_at.desc()).all()
    )


@router.post("/api-keys", response_model=CreateAPIKeyResponse, status_code=201)
def create_api_key(
    payload: CreateAPIKeyRequest,
    db: Session = Depends(get_db),
    current_user: User = Depends(require_role(UserRole.admin)),
):
    full_key, prefix, hashed = generate_api_key()
    api_key = APIKey(
        org_id=current_user.org_id,
        name=payload.name,
        key_prefix=prefix,
        hashed_key=hashed,
        created_by=current_user.id,
    )
    db.add(api_key)
    db.commit()
    db.refresh(api_key)
    record_audit(db, current_user, "api_key.create", "api_key", api_key.id, {"name": api_key.name})
    return CreateAPIKeyResponse(api_key=api_key, full_key=full_key)


@router.post("/api-keys/{key_id}/revoke", response_model=APIKeyOut)
def revoke_api_key(
    key_id: uuid.UUID, db: Session = Depends(get_db), current_user: User = Depends(require_role(UserRole.admin))
):
    api_key = db.get(APIKey, key_id)
    if api_key is None or api_key.org_id != current_user.org_id:
        raise HTTPException(status_code=404, detail="API key not found")
    api_key.revoked_at = datetime.now(timezone.utc)
    db.commit()
    db.refresh(api_key)
    record_audit(db, current_user, "api_key.revoke", "api_key", api_key.id)
    return api_key
