"""AI domain — HTTP routes."""
from __future__ import annotations

from uuid import UUID

from fastapi import APIRouter, Depends
from sqlalchemy.ext.asyncio import AsyncSession

from src.core.database import get_db
from src.core.dependencies import require_active_billing_for_project_id
from src.domain.auth.models import User
from src.domain.auth.router import get_current_user
from src.domain.ai.repository import (
    ProjectAIConfigRepository,
    ProjectAIEmbedConfigRepository,
    WorkspaceVectorizeConfigRepository,
)
from src.domain.ai.schemas import (
    AIConfigResponse,
    CreateEmbedConfigRequest,
    EmbedConfigResponse,
    ProvisionVectorizeRequest,
    ReembedTriggerResponse,
    SetBYOKCompletionKeyRequest,
    UpdateAIConfigRequest,
    UpdateEmbedConfigRequest,
    VectorizeConfigResponse,
)
from src.domain.ai.service import AIService
from src.domain.projects.repository import ProjectRepository
from src.integrations.cloud_control_client import CloudControlClient

router = APIRouter(
    prefix="/api/projects/{project_id}/ai",
    tags=["ai"],
)

workspace_router = APIRouter(
    prefix="/api/workspaces/{workspace_id}/ai",
    tags=["ai"],
)


def _get_service(db: AsyncSession = Depends(get_db)) -> AIService:
    return AIService(
        config_repo=ProjectAIConfigRepository(db),
        embed_repo=ProjectAIEmbedConfigRepository(db),
        vectorize_repo=WorkspaceVectorizeConfigRepository(db),
        cloud_client=CloudControlClient(),
    )


# ---------------------------------------------------------------------------
# Project AI config
# ---------------------------------------------------------------------------


@router.get("/config", response_model=AIConfigResponse)
async def get_ai_config(
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    svc: AIService = Depends(_get_service),
) -> AIConfigResponse:
    return await svc.get_or_create_config(project_id)


@router.patch("/config", response_model=AIConfigResponse)
async def update_ai_config(
    body: UpdateAIConfigRequest,
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    svc: AIService = Depends(_get_service),
) -> AIConfigResponse:
    return await svc.update_config(project_id, body)


@router.put("/config/byok-completion", response_model=AIConfigResponse)
async def set_byok_completion_key(
    body: SetBYOKCompletionKeyRequest,
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    svc: AIService = Depends(_get_service),
) -> AIConfigResponse:
    """Store a BYOK completion API key (openai or anthropic). Key is encrypted and never returned."""
    return await svc.set_byok_completion_key(project_id, body)


# ---------------------------------------------------------------------------
# Embed configs
# ---------------------------------------------------------------------------


@router.get("/embed-configs", response_model=list[EmbedConfigResponse])
async def list_embed_configs(
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    svc: AIService = Depends(_get_service),
) -> list[EmbedConfigResponse]:
    return await svc.list_embed_configs(project_id)


@router.post("/embed-configs", response_model=EmbedConfigResponse, status_code=201)
async def create_embed_config(
    body: CreateEmbedConfigRequest,
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    svc: AIService = Depends(_get_service),
) -> EmbedConfigResponse:
    return await svc.create_embed_config(project_id, body)


@router.patch(
    "/embed-configs/{entity_key}/{field_key}",
    response_model=EmbedConfigResponse,
)
async def update_embed_config(
    entity_key: str,
    field_key: str,
    body: UpdateEmbedConfigRequest,
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    svc: AIService = Depends(_get_service),
) -> EmbedConfigResponse:
    return await svc.update_embed_config(project_id, entity_key, field_key, body)


@router.delete(
    "/embed-configs/{entity_key}/{field_key}",
    status_code=204,
    response_model=None,
)
async def delete_embed_config(
    entity_key: str,
    field_key: str,
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    svc: AIService = Depends(_get_service),
) -> None:
    await svc.delete_embed_config(project_id, entity_key, field_key)


# ---------------------------------------------------------------------------
# Re-embed trigger (after plan upgrade — incompatible dimensions)
# ---------------------------------------------------------------------------


@router.post("/reembed", response_model=ReembedTriggerResponse)
async def trigger_reembed(
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    svc: AIService = Depends(_get_service),
) -> ReembedTriggerResponse:
    """Queue a bulk re-embed job after a plan upgrade that changed vector dimensions."""
    return await svc.trigger_reembed(project_id)


# ---------------------------------------------------------------------------
# Workspace vectorize index
# ---------------------------------------------------------------------------


@workspace_router.get("/vectorize", response_model=VectorizeConfigResponse)
async def get_vectorize_config(
    workspace_id: UUID,
    user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
    svc: AIService = Depends(_get_service),
) -> VectorizeConfigResponse:
    cfg = await svc.get_vectorize_config(workspace_id)
    if not cfg:
        from src.core.exceptions import NotFoundError
        raise NotFoundError("Vectorize index not yet provisioned for this workspace")
    return cfg


@workspace_router.post(
    "/vectorize",
    response_model=VectorizeConfigResponse,
    status_code=201,
)
async def provision_vectorize(
    workspace_id: UUID,
    body: ProvisionVectorizeRequest,
    _: User = Depends(get_current_user),
    svc: AIService = Depends(_get_service),
) -> VectorizeConfigResponse:
    """Provision a CF Vectorize index for a workspace. Called once on workspace AI activation."""
    return await svc.provision_vectorize(workspace_id, body)
