"""
Prompt Template Management API.
[AC-AISVC-52, AC-AISVC-57, AC-AISVC-58, AC-AISVC-54, AC-AISVC-55] Prompt template CRUD and publish/rollback endpoints.
[AC-AISVC-99] Prompt template preview endpoint.
"""

import logging
import uuid
from typing import Any, Optional

from fastapi import APIRouter, Depends, Header, HTTPException
from pydantic import BaseModel
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.database import get_session
from app.models.entities import PromptTemplateCreate, PromptTemplateUpdate
from app.services.prompt.template_service import PromptTemplateService
from app.services.monitoring.prompt_monitor import PromptMonitor


class PromptTemplateUpdateAPI(BaseModel):
    """API model for updating prompt template with metadata field mapping."""
    name: str | None = None
    scene: str | None = None
    description: str | None = None
    system_instruction: str | None = None
    variables: list[dict[str, Any]] | None = None
    is_default: bool | None = None
    metadata: dict[str, Any] | None = None

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/admin/prompt-templates", tags=["Prompt Management"])


def get_tenant_id(x_tenant_id: str = Header(..., alias="X-Tenant-Id")) -> str:
    """Extract tenant ID from header."""
    if not x_tenant_id:
        raise HTTPException(status_code=400, detail="X-Tenant-Id header is required")
    return x_tenant_id


@router.get("")
async def list_templates(
    tenant_id: str = Depends(get_tenant_id),
    scene: str | None = None,
    session: AsyncSession = Depends(get_session),
) -> dict[str, Any]:
    """
    [AC-AISVC-57] List all prompt templates for a tenant.
    """
    logger.info(f"[AC-AISVC-57] Listing prompt templates for tenant={tenant_id}, scene={scene}")

    service = PromptTemplateService(session)
    templates = await service.list_templates(tenant_id, scene)

    data = []
    for t in templates:
        published_version = await service.get_published_version_info(tenant_id, t.id)
        data.append({
            "id": str(t.id),
            "name": t.name,
            "scene": t.scene,
            "description": t.description,
            "is_default": t.is_default,
            "published_version": published_version,
            "created_at": t.created_at.isoformat(),
            "updated_at": t.updated_at.isoformat(),
        })

    return {"data": data}


@router.post("", status_code=201)
async def create_template(
    body: PromptTemplateCreate,
    tenant_id: str = Depends(get_tenant_id),
    session: AsyncSession = Depends(get_session),
) -> dict[str, Any]:
    """
    [AC-AISVC-52] Create a new prompt template.
    """
    logger.info(f"[AC-AISVC-52] Creating prompt template for tenant={tenant_id}, name={body.name}")

    service = PromptTemplateService(session)
    template = await service.create_template(tenant_id, body)

    return {
        "id": str(template.id),
        "name": template.name,
        "scene": template.scene,
        "description": template.description,
        "is_default": template.is_default,
        "created_at": template.created_at.isoformat(),
        "updated_at": template.updated_at.isoformat(),
    }


@router.get("/{tpl_id}")
async def get_template_detail(
    tpl_id: uuid.UUID,
    tenant_id: str = Depends(get_tenant_id),
    session: AsyncSession = Depends(get_session),
) -> dict[str, Any]:
    """
    [AC-AISVC-58] Get prompt template detail with version history.
    """
    logger.info(f"[AC-AISVC-58] Getting template detail for tenant={tenant_id}, id={tpl_id}")

    service = PromptTemplateService(session)
    detail = await service.get_template_detail(tenant_id, tpl_id)

    if not detail:
        raise HTTPException(status_code=404, detail="Template not found")

    return detail


@router.put("/{tpl_id}")
async def update_template(
    tpl_id: uuid.UUID,
    body: PromptTemplateUpdateAPI,
    tenant_id: str = Depends(get_tenant_id),
    session: AsyncSession = Depends(get_session),
) -> dict[str, Any]:
    """
    [AC-AISVC-53] Update prompt template (creates a new version).
    [AC-IDSMETA-16] Return current_content and metadata for frontend display.
    """
    logger.info(f"[AC-AISVC-53] Updating template for tenant={tenant_id}, id={tpl_id}")

    service = PromptTemplateService(session)

    # Convert API model to entity model (metadata -> metadata_)
    update_data = PromptTemplateUpdate(
        name=body.name,
        scene=body.scene,
        description=body.description,
        system_instruction=body.system_instruction,
        variables=body.variables,
        is_default=body.is_default,
        metadata_=body.metadata,
    )

    template = await service.update_template(tenant_id, tpl_id, update_data)

    if not template:
        raise HTTPException(status_code=404, detail="Template not found")

    published_version = await service.get_published_version_info(tenant_id, template.id)

    # Get latest version content for current_content
    latest_version = await service._get_latest_version(template.id)

    return {
        "id": str(template.id),
        "name": template.name,
        "scene": template.scene,
        "description": template.description,
        "is_default": template.is_default,
        "current_content": latest_version.system_instruction if latest_version else None,
        "metadata": template.metadata_,
        "published_version": published_version,
        "created_at": template.created_at.isoformat(),
        "updated_at": template.updated_at.isoformat(),
    }


@router.post("/{tpl_id}/publish")
async def publish_template(
    tpl_id: uuid.UUID,
    body: dict[str, int],
    tenant_id: str = Depends(get_tenant_id),
    session: AsyncSession = Depends(get_session),
) -> dict[str, Any]:
    """
    [AC-AISVC-54] Publish a specific version of the template.
    """
    version = body.get("version")
    if version is None:
        raise HTTPException(status_code=400, detail="version is required")

    logger.info(
        f"[AC-AISVC-54] Publishing template version for tenant={tenant_id}, "
        f"id={tpl_id}, version={version}"
    )

    service = PromptTemplateService(session)
    success = await service.publish_version(tenant_id, tpl_id, version)

    if not success:
        raise HTTPException(status_code=404, detail="Template or version not found")

    return {"success": True, "message": f"Version {version} published successfully"}


@router.post("/{tpl_id}/rollback")
async def rollback_template(
    tpl_id: uuid.UUID,
    body: dict[str, int],
    tenant_id: str = Depends(get_tenant_id),
    session: AsyncSession = Depends(get_session),
) -> dict[str, Any]:
    """
    [AC-AISVC-55] Rollback to a specific historical version.
    """
    version = body.get("version")
    if version is None:
        raise HTTPException(status_code=400, detail="version is required")

    logger.info(
        f"[AC-AISVC-55] Rolling back template for tenant={tenant_id}, "
        f"id={tpl_id}, version={version}"
    )

    service = PromptTemplateService(session)
    success = await service.rollback_version(tenant_id, tpl_id, version)

    if not success:
        raise HTTPException(status_code=404, detail="Template or version not found")

    return {"success": True, "message": f"Rolled back to version {version} successfully"}


@router.delete("/{tpl_id}", status_code=204)
async def delete_template(
    tpl_id: uuid.UUID,
    tenant_id: str = Depends(get_tenant_id),
    session: AsyncSession = Depends(get_session),
) -> None:
    """
    Delete a prompt template and all its versions.
    """
    logger.info(f"Deleting template for tenant={tenant_id}, id={tpl_id}")

    service = PromptTemplateService(session)
    success = await service.delete_template(tenant_id, tpl_id)

    if not success:
        raise HTTPException(status_code=404, detail="Template not found")


class PromptPreviewRequest(BaseModel):
    """Request body for previewing a prompt template."""

    variables: dict[str, str] | None = None
    sample_history: list[dict[str, str]] | None = None
    sample_message: str | None = None


@router.post("/{tpl_id}/preview")
async def preview_template(
    tpl_id: uuid.UUID,
    body: PromptPreviewRequest,
    tenant_id: str = Depends(get_tenant_id),
    session: AsyncSession = Depends(get_session),
) -> dict[str, Any]:
    """
    [AC-AISVC-99] Preview a prompt template with variable substitution.

    Returns rendered content and token count estimation.
    """
    logger.info(
        f"[AC-AISVC-99] Previewing template for tenant={tenant_id}, id={tpl_id}"
    )

    monitor = PromptMonitor(session)
    result = await monitor.preview_template(
        tenant_id=tenant_id,
        template_id=tpl_id,
        variables=body.variables,
        sample_history=body.sample_history,
        sample_message=body.sample_message,
    )

    if not result:
        raise HTTPException(status_code=404, detail="Template not found")

    return result.to_dict()
