import uuid
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import update

from app.database import get_db
from app.utils.auth import require_global_admin
from app.domains.tenants.schemas import (
    TenantCreate, TenantUpdate, TenantOut,
    TenantAIConfigUpdate, TenantAIConfigOut,
)
from app.domains.tenants import service
from app.domains.tenants.models import Tenant

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


@router.get("/", response_model=list[TenantOut])
async def list_tenants(
    db: AsyncSession = Depends(get_db),
    _: object = Depends(require_global_admin),
):
    rows = await service.list_tenants(db)
    result = []
    for row in rows:
        tenant = row["tenant"]
        out = TenantOut.model_validate(tenant)
        out.user_count = row["user_count"]
        result.append(out)
    return result


@router.get("/{tenant_id}", response_model=TenantOut)
async def get_tenant(
    tenant_id: uuid.UUID,
    db: AsyncSession = Depends(get_db),
    _: object = Depends(require_global_admin),
):
    tenant = await service.get_tenant(db, tenant_id)
    if not tenant:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Tenant not found")
    return TenantOut.model_validate(tenant)


@router.post("/", response_model=TenantOut, status_code=status.HTTP_201_CREATED)
async def create_tenant(
    body: TenantCreate,
    db: AsyncSession = Depends(get_db),
    _: object = Depends(require_global_admin),
):
    tenant = await service.create_tenant(db, name=body.name, slug=body.slug, is_active=body.is_active)
    return TenantOut.model_validate(tenant)


@router.put("/{tenant_id}", response_model=TenantOut)
async def update_tenant(
    tenant_id: uuid.UUID,
    body: TenantUpdate,
    db: AsyncSession = Depends(get_db),
    _: object = Depends(require_global_admin),
):
    tenant = await service.update_tenant(
        db, tenant_id,
        name=body.name,
        slug=body.slug,
        is_active=body.is_active,
    )
    if not tenant:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Tenant not found")
    return TenantOut.model_validate(tenant)


@router.delete("/{tenant_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_tenant(
    tenant_id: uuid.UUID,
    db: AsyncSession = Depends(get_db),
    _: object = Depends(require_global_admin),
):
    ok = await service.delete_tenant(db, tenant_id)
    if not ok:
        raise HTTPException(
            status_code=status.HTTP_409_CONFLICT,
            detail="Tenant not found or still has users assigned",
        )


# ---------------------------------------------------------------------------
# Per-tenant Azure AI configuration
# ---------------------------------------------------------------------------

def _tenant_ai_config_out(tenant: Tenant) -> TenantAIConfigOut:
    """Build TenantAIConfigOut from a Tenant ORM object (never exposes api_key)."""
    cfg = tenant.tenant_config or {}
    return TenantAIConfigOut(
        ai_enabled=cfg.get("ai_enabled", False),
        ai_endpoint=cfg.get("ai_endpoint"),
        ai_deployment=cfg.get("ai_deployment", "gpt-4o"),
        ai_api_version=cfg.get("ai_api_version", "2024-02-01"),
        has_api_key=bool(cfg.get("ai_api_key")),
        ai_max_tokens=cfg.get("ai_max_tokens", 500),
        ai_temperature=cfg.get("ai_temperature", 0.1),
        ai_validation_prompt=cfg.get("ai_validation_prompt"),
    )


@router.get("/{tenant_id}/ai-config", response_model=TenantAIConfigOut)
async def get_tenant_ai_config(
    tenant_id: uuid.UUID,
    db: AsyncSession = Depends(get_db),
    _: object = Depends(require_global_admin),
):
    """Return AI config for a tenant (without the raw api_key)."""
    tenant = await service.get_tenant(db, tenant_id)
    if not tenant:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Tenant not found")
    return _tenant_ai_config_out(tenant)


@router.put("/{tenant_id}/ai-config", response_model=TenantAIConfigOut)
async def update_tenant_ai_config(
    tenant_id: uuid.UUID,
    body: TenantAIConfigUpdate,
    db: AsyncSession = Depends(get_db),
    _: object = Depends(require_global_admin),
):
    """Merge AI configuration into tenant_config JSONB.
    If ai_api_key is None in the request body, the existing key is preserved.
    """
    tenant = await service.get_tenant(db, tenant_id)
    if not tenant:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Tenant not found")

    # Build the merged config dict
    current_cfg: dict = dict(tenant.tenant_config or {})

    current_cfg["ai_enabled"] = body.ai_enabled
    current_cfg["ai_endpoint"] = body.ai_endpoint
    current_cfg["ai_deployment"] = body.ai_deployment
    current_cfg["ai_api_version"] = body.ai_api_version
    current_cfg["ai_max_tokens"] = body.ai_max_tokens
    current_cfg["ai_temperature"] = body.ai_temperature
    current_cfg["ai_validation_prompt"] = body.ai_validation_prompt

    # Only overwrite the stored key if a new value was actually provided
    if body.ai_api_key is not None:
        current_cfg["ai_api_key"] = body.ai_api_key

    # Use direct SQL UPDATE to reliably persist JSONB mutations
    await db.execute(
        update(Tenant)
        .where(Tenant.id == tenant_id)
        .values(tenant_config=current_cfg)
    )
    await db.commit()
    await db.refresh(tenant)
    return _tenant_ai_config_out(tenant)


@router.post("/{tenant_id}/ai-config/test")
async def test_tenant_ai_config(
    tenant_id: uuid.UUID,
    db: AsyncSession = Depends(get_db),
    _: object = Depends(require_global_admin),
):
    """Send a minimal ping to Azure OpenAI using the tenant's stored credentials.
    Returns {"ok": true} or {"ok": false, "error": "human readable message"}.
    """
    tenant = await service.get_tenant(db, tenant_id)
    if not tenant:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Tenant not found")

    cfg = tenant.tenant_config or {}
    api_key = cfg.get("ai_api_key")
    endpoint = cfg.get("ai_endpoint")
    deployment = cfg.get("ai_deployment", "gpt-4o")
    api_version = cfg.get("ai_api_version", "2024-02-01")

    if not api_key:
        return {"ok": False, "error": "No API key configured for this tenant"}
    if not endpoint:
        return {"ok": False, "error": "No endpoint configured for this tenant"}

    import asyncio

    def _ping() -> dict:
        try:
            from openai import AzureOpenAI
            client = AzureOpenAI(
                api_key=api_key,
                azure_endpoint=endpoint,
                api_version=api_version,
            )
            client.chat.completions.create(
                model=deployment,
                messages=[{"role": "user", "content": "ping"}],
                max_completion_tokens=5,
            )
            return {"ok": True}
        except Exception as exc:
            return {"ok": False, "error": str(exc)}

    return await asyncio.to_thread(_ping)
