"""
B-4: KB 자동 업데이트 에이전트 API 라우터

엔드포인트:
  POST /api/kb-agent/run                 — 에이전트 즉시 실행 (해결 SR 일괄 처리)
  POST /api/kb-agent/analyze/{sr_id}     — 특정 SR → KB 분석 및 생성
  GET  /api/kb-agent/candidates          — KB 후보 목록 (미처리 완료 SR)
  GET  /api/kb-agent/stats               — 에이전트 처리 통계
  POST /api/kb/                          — KB 수동 생성
  PUT  /api/kb/{kb_id}                   — KB 수정
"""
from __future__ import annotations

import logging
import re
from datetime import datetime, timedelta
from typing import List, Optional

from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, Query
from pydantic import BaseModel
from sqlalchemy import desc, select, and_, func
from sqlalchemy.ext.asyncio import AsyncSession

from database import get_db
from models import KBDocument, KBDocumentOut, SRRequest, SRStatus
from core.kb_agent import (
    auto_create_kb_from_sr,
    run_kb_agent_batch,
    classify_category,
    extract_tags_rule,
    compute_similarity,
)

logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/kb-agent", tags=["kb-agent"])


# ── doc_id 생성 헬퍼 ─────────────────────────────────────────────────────────

async def _next_doc_id(db: AsyncSession) -> str:
    """KB-YYYYMMDD-NNNN 형식의 문서 ID 생성."""
    today = datetime.utcnow().strftime("%Y%m%d")
    prefix = f"KB-{today}-"
    # 오늘 생성된 최대 번호 조회
    q = select(KBDocument.doc_id).where(
        KBDocument.doc_id.like(f"{prefix}%")
    ).order_by(desc(KBDocument.doc_id)).limit(1)
    last = (await db.execute(q)).scalar()
    if last:
        try:
            seq = int(last.split("-")[-1]) + 1
        except ValueError:
            seq = 1
    else:
        seq = 1
    return f"{prefix}{seq:04d}"


# ── 에이전트 실행 ──────────────────────────────────────────────────────────────

class RunAgentRequest(BaseModel):
    days_back: int = 7
    max_sr: int = 20
    use_llm: bool = True
    model: str = "llama3"


@router.post("/run")
async def run_kb_agent(
    body: RunAgentRequest,
    background_tasks: BackgroundTasks,
    db: AsyncSession = Depends(get_db),
):
    """
    KB 자동 업데이트 에이전트 실행.
    최근 N일 완료된 SR을 분석하여 KB 문서 자동 생성.
    """
    # 동기적 실행 (최대 20건이므로 백그라운드 불필요)
    try:
        result = await run_kb_agent_batch(
            db       = db,
            days_back= body.days_back,
            max_sr   = body.max_sr,
            use_llm  = body.use_llm,
            model    = body.model,
        )
        return {
            "status": "completed",
            "run_at": datetime.utcnow().isoformat(),
            **result,
        }
    except Exception as e:
        logger.error("[B-4] 에이전트 실행 오류: %s", e)
        raise HTTPException(500, f"에이전트 실행 오류: {str(e)[:100]}")


@router.post("/analyze/{sr_id}")
async def analyze_sr(
    sr_id: str,
    use_llm: bool = Query(True),
    model: str = Query("llama3"),
    db: AsyncSession = Depends(get_db),
):
    """특정 SR을 분석하여 KB 문서 생성."""
    result = await auto_create_kb_from_sr(
        db=db, sr_id=sr_id, use_llm=use_llm, model=model
    )
    if result is None:
        raise HTTPException(404, f"SR '{sr_id}'를 찾을 수 없습니다.")

    # KB ID가 있으면 상세 반환
    if result.get("kb_id"):
        kb = (await db.execute(
            select(KBDocument).where(KBDocument.id == result["kb_id"])
        )).scalars().first()
        if kb:
            result["kb_detail"] = {
                "doc_id":   kb.doc_id,
                "title":    kb.title,
                "category": kb.category,
                "tags":     kb.tags,
            }

    return result


# ── KB 후보 목록 ──────────────────────────────────────────────────────────────

@router.get("/candidates")
async def list_kb_candidates(
    days_back: int = Query(30, ge=1, le=90),
    limit: int = Query(20, ge=1, le=100),
    db: AsyncSession = Depends(get_db),
):
    """KB 미처리 완료 SR 목록 (KB 후보)."""
    since = datetime.utcnow() - timedelta(days=days_back)

    # 이미 처리된 SR ID
    processed = (await db.execute(
        select(KBDocument.source_sr_id).where(KBDocument.source_sr_id.isnot(None))
    )).scalars().all()
    processed_set = set(processed)

    q = (
        select(SRRequest)
        .where(
            and_(
                SRRequest.status == "COMPLETED",
                SRRequest.updated_at >= since,
            )
        )
        .order_by(desc(SRRequest.updated_at))
        .limit(limit * 2)
    )
    srs = (await db.execute(q)).scalars().all()

    candidates = []
    for sr in srs:
        if sr.sr_id in processed_set:
            continue
        candidates.append({
            "sr_id":     sr.sr_id,
            "title":     sr.title,
            "sr_type":   str(sr.sr_type) if sr.sr_type else None,
            "priority":  str(sr.priority) if sr.priority else None,
            "completed_at": sr.updated_at.isoformat() if sr.updated_at else None,
        })
        if len(candidates) >= limit:
            break

    return {
        "total":      len(candidates),
        "candidates": candidates,
    }


# ── KB 수동 생성 / 수정 ───────────────────────────────────────────────────────

class KBCreateRequest(BaseModel):
    title:    str
    category: Optional[str] = "일반"
    symptoms: Optional[str] = None
    cause:    Optional[str] = None
    solution: Optional[str] = None
    commands: Optional[str] = None
    tags:     Optional[str] = None
    sr_type:  Optional[str] = None
    source_sr_id: Optional[str] = None


@router.post("/kb", response_model=KBDocumentOut, status_code=201,
             tags=["kb"])
async def create_kb(
    body: KBCreateRequest,
    db: AsyncSession = Depends(get_db),
):
    """KB 문서 수동 생성."""
    doc_id = await _next_doc_id(db)

    # 자동 태그 보강
    auto_tags = extract_tags_rule(
        body.title, body.symptoms or "", body.solution or ""
    )
    existing_tags = body.tags or ""
    merged_tags = existing_tags + (" " if existing_tags and auto_tags else "") + " ".join(auto_tags)

    kb = KBDocument(
        doc_id    = doc_id,
        title     = body.title,
        category  = body.category or classify_category(body.title, body.symptoms or ""),
        symptoms  = body.symptoms,
        cause     = body.cause,
        solution  = body.solution,
        commands  = body.commands,
        tags      = merged_tags.strip(),
        sr_type   = body.sr_type,
        source_sr_id = body.source_sr_id,
        author    = "user",
        published = False,
        created_at= datetime.utcnow(),
    )
    db.add(kb)
    await db.commit()
    await db.refresh(kb)
    return kb


class KBUpdateRequest(BaseModel):
    title:    Optional[str] = None
    category: Optional[str] = None
    symptoms: Optional[str] = None
    cause:    Optional[str] = None
    solution: Optional[str] = None
    commands: Optional[str] = None
    tags:     Optional[str] = None
    published: Optional[bool] = None


@router.put("/kb/{kb_id}", response_model=KBDocumentOut, tags=["kb"])
async def update_kb(
    kb_id: int,
    body: KBUpdateRequest,
    db: AsyncSession = Depends(get_db),
):
    """KB 문서 수정."""
    kb = (await db.execute(
        select(KBDocument).where(KBDocument.id == kb_id)
    )).scalars().first()
    if not kb:
        raise HTTPException(404, f"KB {kb_id}를 찾을 수 없습니다.")

    for field, val in body.model_dump(exclude_none=True).items():
        setattr(kb, field, val)
    kb.updated_at = datetime.utcnow()

    await db.commit()
    await db.refresh(kb)
    return kb


# ── 에이전트 통계 ─────────────────────────────────────────────────────────────

@router.get("/stats")
async def get_kb_agent_stats(
    db: AsyncSession = Depends(get_db),
):
    """KB 에이전트 처리 통계."""
    total_kb = (await db.execute(
        select(func.count()).select_from(KBDocument)
    )).scalar() or 0

    agent_created = (await db.execute(
        select(func.count()).select_from(KBDocument)
        .where(KBDocument.author == "kb-agent")
    )).scalar() or 0

    user_created = (await db.execute(
        select(func.count()).select_from(KBDocument)
        .where(KBDocument.author != "kb-agent")
    )).scalar() or 0

    published = (await db.execute(
        select(func.count()).select_from(KBDocument)
        .where(KBDocument.published == True)
    )).scalar() or 0

    # 완료 SR 중 KB 미생성 수
    total_completed = (await db.execute(
        select(func.count()).select_from(SRRequest)
        .where(SRRequest.status == "COMPLETED")
    )).scalar() or 0

    processed_count = (await db.execute(
        select(func.count()).select_from(KBDocument)
        .where(KBDocument.source_sr_id.isnot(None))
    )).scalar() or 0

    return {
        "total_kb_documents": total_kb,
        "agent_created":   agent_created,
        "user_created":    user_created,
        "published":       published,
        "completed_sr_total": total_completed,
        "kb_coverage_pct": round(processed_count / max(total_completed, 1) * 100, 1),
    }
