"""
routes_oracle_templates.py
──────────────────────────
Oracle Template Catalog API

Extends the existing Oracle route surface with template taxonomy and seeding.

Endpoints:
  GET  /oracle/template-chapters                    — list chapters
  POST /oracle/template-chapters                    — create a chapter
  GET  /oracle/template-subchapters                 — list subchapters (optionally filtered)
  POST /oracle/template-subchapters                 — create a subchapter
  GET  /oracle/component-templates                  — list templates (filterable)
  POST /oracle/component-templates                  — create a template
  GET  /oracle/component-templates/{id}             — get a template
  POST /oracle/component-templates/{id}/seed        — add a seed example
  GET  /oracle/component-templates/{id}/seed        — list seed examples for a template
  POST /oracle/component-templates/synthetic-jobs   — trigger a Kimi synthetic job
"""

from __future__ import annotations

import json
import logging
import os
from typing import Any, Optional

from fastapi import APIRouter, Depends, HTTPException, Query, Request, status
from pydantic import BaseModel, Field

from backend.auth.dependencies import get_current_user

logger = logging.getLogger("velocity.oracle_templates")

router = APIRouter()
_DEFAULT_TENANT_ID = os.getenv("ORACLE_DEFAULT_TENANT_ID", "tenant_velocity")


# ── Helpers ───────────────────────────────────────────────────────────────────

def _pool(request: Request):
    pool = request.app.state.db_pool
    if pool is None:
        raise HTTPException(503, "Database unavailable.")
    return pool


def _tenant_id() -> str:
    return _DEFAULT_TENANT_ID


# ── Models ────────────────────────────────────────────────────────────────────

class ChapterCreate(BaseModel):
    name: str
    description: Optional[str] = None
    sort_order: int = 0


class SubchapterCreate(BaseModel):
    chapter_id: str
    name: str
    description: Optional[str] = None
    sort_order: int = 0


class TemplateCreate(BaseModel):
    name: str
    category: str
    chapter_id: Optional[str] = None
    subchapter_id: Optional[str] = None
    component_type: Optional[str] = None
    accepted_shapes: list[str] = Field(default_factory=list)
    json_template: Optional[dict] = None
    description: Optional[str] = None
    origin: str = "premade"
    version: str = "1.0.0"


class SeedExampleCreate(BaseModel):
    title: str
    example_json: dict
    quality_notes: Optional[str] = None
    chapter_id: Optional[str] = None
    subchapter_id: Optional[str] = None
    is_canonical: bool = False


class SyntheticJobCreate(BaseModel):
    template_id: str
    chapter_id: Optional[str] = None
    subchapter_id: Optional[str] = None
    model: str = "kimi"
    requested_count: int = Field(10, ge=1, le=500)


# ── Template Chapters ─────────────────────────────────────────────────────────

@router.get("/template-chapters", summary="List Oracle template chapters")
async def list_template_chapters(
    request: Request,
    include_inactive: bool = Query(False),
    user=Depends(get_current_user),
):
    pool = _pool(request)
    async with pool.acquire() as conn:
        where = "WHERE ch.tenant_id=$1" + ("" if include_inactive else " AND ch.is_active=TRUE")
        rows = await conn.fetch(
            f"""
            SELECT ch.chapter_id, ch.name, ch.description, ch.sort_order, ch.is_active,
                   COUNT(sub.subchapter_id) FILTER (WHERE sub.is_active=TRUE) as subchapter_count,
                   COUNT(t.template_id) as template_count
            FROM oracle_template_chapters ch
            LEFT JOIN oracle_template_subchapters sub ON sub.chapter_id = ch.chapter_id
            LEFT JOIN oracle_component_templates t ON t.chapter_id = ch.chapter_id
                                                   AND t.status != 'archived'
            {where}
            GROUP BY ch.chapter_id
            ORDER BY ch.sort_order ASC
            """,
            _tenant_id(),
        )
    return {"chapters": [dict(r) for r in rows]}


@router.post("/template-chapters", status_code=status.HTTP_201_CREATED,
             summary="Create a template chapter")
async def create_template_chapter(
    request: Request,
    body: ChapterCreate,
    user=Depends(get_current_user),
):
    pool = _pool(request)
    async with pool.acquire() as conn:
        row = await conn.fetchrow(
            """
            INSERT INTO oracle_template_chapters (tenant_id, name, description, sort_order)
            VALUES ($1,$2,$3,$4)
            RETURNING chapter_id, created_at
            """,
            _tenant_id(), body.name, body.description, body.sort_order,
        )
    return {"chapter_id": str(row["chapter_id"]), "created_at": str(row["created_at"])}


# ── Template Subchapters ──────────────────────────────────────────────────────

@router.get("/template-subchapters", summary="List Oracle template subchapters")
async def list_template_subchapters(
    request: Request,
    chapter_id: Optional[str] = Query(None),
    include_inactive: bool = Query(False),
    user=Depends(get_current_user),
):
    pool = _pool(request)
    async with pool.acquire() as conn:
        where = "WHERE sub.tenant_id=$1"
        params: list[Any] = [_tenant_id()]
        idx = 2
        if not include_inactive:
            where += " AND sub.is_active=TRUE"
        if chapter_id:
            where += f" AND sub.chapter_id=${idx}"; params.append(chapter_id); idx += 1

        rows = await conn.fetch(
            f"""
            SELECT sub.subchapter_id, sub.chapter_id, ch.name as chapter_name,
                   sub.name, sub.description, sub.sort_order, sub.is_active,
                   COUNT(t.template_id) as template_count
            FROM oracle_template_subchapters sub
            JOIN oracle_template_chapters ch ON ch.chapter_id = sub.chapter_id
            LEFT JOIN oracle_component_templates t ON t.subchapter_id = sub.subchapter_id
                                                   AND t.status != 'archived'
            {where}
            GROUP BY sub.subchapter_id, ch.name
            ORDER BY sub.chapter_id, sub.sort_order ASC
            """,
            *params,
        )
    return {"subchapters": [dict(r) for r in rows]}


@router.post("/template-subchapters", status_code=status.HTTP_201_CREATED,
             summary="Create a template subchapter")
async def create_template_subchapter(
    request: Request,
    body: SubchapterCreate,
    user=Depends(get_current_user),
):
    pool = _pool(request)
    async with pool.acquire() as conn:
        # Verify chapter exists and belongs to tenant
        ch_exists = await conn.fetchval(
            "SELECT 1 FROM oracle_template_chapters WHERE chapter_id=$1 AND tenant_id=$2",
            body.chapter_id, _tenant_id(),
        )
        if not ch_exists:
            raise HTTPException(404, "Chapter not found")

        row = await conn.fetchrow(
            """
            INSERT INTO oracle_template_subchapters
                (chapter_id, tenant_id, name, description, sort_order)
            VALUES ($1,$2,$3,$4,$5)
            RETURNING subchapter_id, created_at
            """,
            body.chapter_id, _tenant_id(), body.name, body.description, body.sort_order,
        )
    return {"subchapter_id": str(row["subchapter_id"]), "created_at": str(row["created_at"])}


# ── Component Templates ───────────────────────────────────────────────────────

@router.get("/component-templates", summary="List Oracle component templates")
async def list_component_templates(
    request: Request,
    chapter_id: Optional[str] = Query(None),
    subchapter_id: Optional[str] = Query(None),
    status_filter: Optional[str] = Query(None, alias="status"),
    search: Optional[str] = Query(None),
    limit: int = Query(50, ge=1, le=200),
    offset: int = Query(0, ge=0),
    user=Depends(get_current_user),
):
    pool = _pool(request)
    where = "WHERE t.tenant_id=$1"
    params: list[Any] = [_tenant_id()]
    idx = 2

    if chapter_id:
        where += f" AND t.chapter_id=${idx}"; params.append(chapter_id); idx += 1
    if subchapter_id:
        where += f" AND t.subchapter_id=${idx}"; params.append(subchapter_id); idx += 1
    if status_filter:
        where += f" AND t.status=${idx}"; params.append(status_filter); idx += 1
    if search:
        where += f" AND (t.name ILIKE ${idx} OR t.description ILIKE ${idx})"
        params.append(f"%{search}%"); idx += 1

    async with pool.acquire() as conn:
        rows = await conn.fetch(
            f"""
            SELECT t.template_id, t.name, t.category, t.status, t.origin, t.version,
                   t.accepted_shapes, t.use_count, t.chapter_id, t.subchapter_id,
                   t.description, ch.name as chapter_name, sub.name as subchapter_name,
                   t.created_at, t.updated_at
            FROM oracle_component_templates t
            LEFT JOIN oracle_template_chapters ch ON ch.chapter_id = t.chapter_id
            LEFT JOIN oracle_template_subchapters sub ON sub.subchapter_id = t.subchapter_id
            {where}
            ORDER BY t.updated_at DESC
            LIMIT ${idx} OFFSET ${idx+1}
            """,
            *params, limit, offset,
        )
        total = await conn.fetchval(
            f"SELECT COUNT(*) FROM oracle_component_templates t {where}", *params,
        )
    return {"total": total, "limit": limit, "offset": offset, "templates": [dict(r) for r in rows]}


@router.post("/component-templates", status_code=status.HTTP_201_CREATED,
             summary="Create a component template")
async def create_component_template(
    request: Request,
    body: TemplateCreate,
    user=Depends(get_current_user),
):
    pool = _pool(request)
    async with pool.acquire() as conn:
        row = await conn.fetchrow(
            """
            INSERT INTO oracle_component_templates (
                tenant_id, name, category, chapter_id, subchapter_id,
                accepted_shapes, json_template, description, origin, version, status
            ) VALUES ($1,$2,$3,$4,$5,$6,$7::jsonb,$8,$9,$10,'draft')
            RETURNING template_id, created_at
            """,
            _tenant_id(), body.name, body.category, body.chapter_id, body.subchapter_id,
            body.accepted_shapes,
            json.dumps(body.json_template) if body.json_template else None,
            body.description, body.origin, body.version,
        )
    return {"template_id": str(row["template_id"]), "created_at": str(row["created_at"])}


@router.get("/component-templates/{template_id}", summary="Get a component template")
async def get_component_template(
    template_id: str,
    request: Request,
    user=Depends(get_current_user),
):
    pool = _pool(request)
    async with pool.acquire() as conn:
        row = await conn.fetchrow(
            """
            SELECT t.*, ch.name as chapter_name, sub.name as subchapter_name
            FROM oracle_component_templates t
            LEFT JOIN oracle_template_chapters ch ON ch.chapter_id = t.chapter_id
            LEFT JOIN oracle_template_subchapters sub ON sub.subchapter_id = t.subchapter_id
            WHERE t.template_id=$1 AND t.tenant_id=$2
            """,
            template_id, _tenant_id(),
        )
    if not row:
        raise HTTPException(404, "Template not found")
    return dict(row)


# ── Seed Examples ─────────────────────────────────────────────────────────────

@router.post("/component-templates/{template_id}/seed", status_code=status.HTTP_201_CREATED,
             summary="Add a seed example to a template")
async def add_seed_example(
    template_id: str,
    request: Request,
    body: SeedExampleCreate,
    user=Depends(get_current_user),
):
    pool = _pool(request)
    async with pool.acquire() as conn:
        exists = await conn.fetchval(
            "SELECT 1 FROM oracle_component_templates WHERE template_id=$1 AND tenant_id=$2",
            template_id, _tenant_id(),
        )
        if not exists:
            raise HTTPException(404, "Template not found")

        row = await conn.fetchrow(
            """
            INSERT INTO oracle_template_seed_examples (
                template_id, chapter_id, subchapter_id, title, example_json,
                quality_notes, is_canonical
            ) VALUES ($1,$2,$3,$4,$5::jsonb,$6,$7)
            RETURNING example_id, created_at
            """,
            template_id, body.chapter_id, body.subchapter_id, body.title,
            json.dumps(body.example_json), body.quality_notes, body.is_canonical,
        )
    return {"example_id": str(row["example_id"]), "created_at": str(row["created_at"])}


@router.get("/component-templates/{template_id}/seed", summary="List seed examples for a template")
async def list_seed_examples(
    template_id: str,
    request: Request,
    user=Depends(get_current_user),
):
    pool = _pool(request)
    async with pool.acquire() as conn:
        rows = await conn.fetch(
            """
            SELECT example_id, title, example_json, quality_notes, is_canonical, created_at
            FROM oracle_template_seed_examples
            WHERE template_id=$1
            ORDER BY is_canonical DESC, created_at ASC
            """,
            template_id,
        )
    return {"examples": [dict(r) for r in rows]}


# ── Synthetic Jobs ────────────────────────────────────────────────────────────

@router.post("/component-templates/synthetic-jobs", status_code=status.HTTP_201_CREATED,
             summary="Trigger a Kimi synthetic data generation job")
async def trigger_synthetic_job(
    request: Request,
    body: SyntheticJobCreate,
    user=Depends(get_current_user),
):
    """
    Queues a Kimi synthetic data expansion job for a template.
    The job will be picked up by the background synthetic generation worker.
    """
    pool = _pool(request)
    async with pool.acquire() as conn:
        exists = await conn.fetchval(
            "SELECT 1 FROM oracle_component_templates WHERE template_id=$1 AND tenant_id=$2",
            body.template_id, _tenant_id(),
        )
        if not exists:
            raise HTTPException(404, "Template not found")

        row = await conn.fetchrow(
            """
            INSERT INTO oracle_synthetic_generation_jobs (
                tenant_id, template_id, chapter_id, subchapter_id,
                model, requested_count, created_by
            ) VALUES ($1,$2,$3,$4,$5,$6,$7)
            RETURNING job_id, status, created_at
            """,
            _tenant_id(), body.template_id, body.chapter_id, body.subchapter_id,
            body.model, body.requested_count, user.user_id,
        )
    logger.info(
        "Synthetic job queued: %s for template %s (%d examples)",
        row["job_id"], body.template_id, body.requested_count,
    )
    return {
        "job_id": str(row["job_id"]),
        "status": row["status"],
        "created_at": str(row["created_at"]),
    }
