"""Column metadata API endpoints — CRUD and Keboola push."""

import logging
import os
from typing import List, Optional

import duckdb
import httpx
from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel

from app.auth.access import require_admin
from app.auth.dependencies import get_current_user, _get_db
from src.repositories.column_metadata import ColumnMetadataRepository
from src.repositories.table_registry import TableRegistryRepository

logger = logging.getLogger(__name__)
router = APIRouter(tags=["metadata"])


class ColumnMetadataItem(BaseModel):
    column_name: str
    basetype: Optional[str] = None
    description: Optional[str] = None
    confidence: str = "manual"


class ColumnMetadataSave(BaseModel):
    columns: List[ColumnMetadataItem]


@router.get("/api/admin/metadata/{table_id}")
async def get_table_metadata(
    table_id: str,
    user: dict = Depends(get_current_user),
    conn: duckdb.DuckDBPyConnection = Depends(_get_db),
):
    """Return column metadata for a table."""
    repo = ColumnMetadataRepository(conn)
    columns = repo.list_for_table(table_id)
    return {"table_id": table_id, "columns": columns}


@router.post("/api/admin/metadata/{table_id}")
async def save_table_metadata(
    table_id: str,
    body: ColumnMetadataSave,
    user: dict = Depends(require_admin),
    conn: duckdb.DuckDBPyConnection = Depends(_get_db),
):
    """Save column metadata for a table. Admin only."""
    repo = ColumnMetadataRepository(conn)
    for item in body.columns:
        repo.save(
            table_id=table_id,
            column_name=item.column_name,
            basetype=item.basetype,
            description=item.description,
            confidence=item.confidence,
        )
    return {"status": "ok", "count": len(body.columns)}


@router.post("/api/admin/metadata/{table_id}/push")
async def push_metadata_to_source(
    table_id: str,
    user: dict = Depends(require_admin),
    conn: duckdb.DuckDBPyConnection = Depends(_get_db),
):
    """Push column metadata to Keboola Storage API. Admin only."""
    registry_repo = TableRegistryRepository(conn)
    table = registry_repo.get(table_id)
    if not table:
        raise HTTPException(status_code=404, detail=f"Table not found: {table_id}")

    source_type = table.get("source_type", "")
    if source_type != "keboola":
        raise HTTPException(
            status_code=400,
            detail=f"Push is only supported for keboola tables (table source_type={source_type!r})",
        )

    source_table = table.get("source_table") or table_id
    stack_url = os.environ.get("KBC_STACK_URL", "").rstrip("/")
    token = os.environ.get("KBC_STORAGE_TOKEN", "")

    if not stack_url or not token:
        raise HTTPException(
            status_code=500,
            detail="KBC_STACK_URL and KBC_STORAGE_TOKEN must be set",
        )

    metadata_repo = ColumnMetadataRepository(conn)
    columns = metadata_repo.list_for_table(table_id)
    if not columns:
        return {"status": "ok", "pushed": 0, "message": "No column metadata to push"}

    pushed = 0
    errors = []

    async with httpx.AsyncClient() as client:
        for col in columns:
            column_name = col["column_name"]
            metadata_payload = []

            if col.get("basetype"):
                metadata_payload.append({"key": "KBC.datatype.basetype", "value": col["basetype"]})
            if col.get("description"):
                metadata_payload.append({"key": "KBC.description", "value": col["description"]})

            if not metadata_payload:
                continue

            endpoint = f"{stack_url}/v2/storage/tables/{source_table}/columns/{column_name}/metadata"
            try:
                resp = await client.post(
                    endpoint,
                    headers={"X-StorageApi-Token": token},
                    json={"provider": "ai-metadata-enrichment", "metadata": metadata_payload},
                    timeout=30,
                )
                if resp.status_code in (200, 201):
                    pushed += 1
                else:
                    errors.append(f"{column_name}: {resp.status_code} {resp.text[:200]}")
            except httpx.RequestError as e:
                errors.append(f"{column_name}: request error — {e}")

    result = {"status": "ok", "pushed": pushed}
    if errors:
        result["errors"] = errors
    return result
