"""
통합 검색 API (모바일 기능 #50).

  GET /api/search/?q={query}&types=sr,server,kb,institution

SR, 서버(CMDB), KB 문서, 기관을 동시에 검색하여 타입별 결과를 반환.
보안: 서버 결과는 ServerOut 안전 필드만 반환(ip_addr/ssh_user/os_pw_enc 제외).
      CUSTOMER 역할은 자신의 기관 SR/서버만 조회.
"""
from __future__ import annotations

from typing import Optional

from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy import select, or_
from sqlalchemy.ext.asyncio import AsyncSession

from core.auth import get_current_user
from database import get_db
from models import (
    Institution, KBDocument, Server, SRRequest, User, UserRole,
)

router = APIRouter(prefix="/api/search", tags=["Search"])

_PER_TYPE_LIMIT = 5


async def _customer_inst_id(user: User, db: AsyncSession) -> Optional[int]:
    """CUSTOMER 역할이면 소속 기관 id 반환, 아니면 None."""
    if user.role == UserRole.CUSTOMER and user.inst_code:
        inst = (await db.execute(
            select(Institution).where(Institution.inst_code == user.inst_code)
        )).scalars().first()
        return inst.id if inst else -1
    return None


@router.get("/")
async def global_search(
    q: str = Query(..., min_length=1, description="검색어"),
    types: str = Query("sr,server,kb,institution", description="콤마 구분 검색 대상"),
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """SR + 서버 + KB + 기관 통합 검색."""
    wanted = {t.strip() for t in types.split(",") if t.strip()}
    if not wanted:
        raise HTTPException(422, "types에 최소 하나의 검색 대상을 지정하세요.")

    like = f"%{q}%"
    results: dict = {}
    cust_inst_id = await _customer_inst_id(current_user, db)

    # ── SR 검색 ──────────────────────────────────────────────────────────
    if "sr" in wanted:
        sr_q = select(SRRequest).where(
            or_(SRRequest.title.ilike(like),
                SRRequest.description.ilike(like),
                SRRequest.sr_id.ilike(like))
        )
        if cust_inst_id is not None:
            sr_q = sr_q.where(SRRequest.inst_id == cust_inst_id)
        sr_q = sr_q.order_by(SRRequest.created_at.desc()).limit(_PER_TYPE_LIMIT)
        srs = (await db.execute(sr_q)).scalars().all()
        results["sr"] = [
            {
                "sr_id": s.sr_id,
                "title": s.title,
                "status": s.status,
                "priority": s.priority,
                "sr_type": s.sr_type,
            }
            for s in srs
        ]

    # ── 서버(CMDB) 검색 — 자격증명 필드 절대 제외 ──────────────────────────
    if "server" in wanted:
        srv_q = select(Server).where(
            or_(Server.server_name.ilike(like),
                Server.server_role.ilike(like),
                Server.os_type.ilike(like))
        )
        if cust_inst_id is not None:
            srv_q = srv_q.where(Server.inst_id == cust_inst_id)
        srv_q = srv_q.limit(_PER_TYPE_LIMIT)
        servers = (await db.execute(srv_q)).scalars().all()
        results["server"] = [
            {
                "id": s.id,
                "server_name": s.server_name,
                "server_role": s.server_role,
                "os_type": s.os_type,
                "inst_id": s.inst_id,
                # ip_addr / ssh_user / os_pw_enc 절대 미포함
            }
            for s in servers
        ]

    # ── KB 검색 ──────────────────────────────────────────────────────────
    if "kb" in wanted:
        kb_q = select(KBDocument).where(
            or_(KBDocument.title.ilike(like),
                KBDocument.symptoms.ilike(like),
                KBDocument.tags.ilike(like))
        ).limit(_PER_TYPE_LIMIT)
        kbs = (await db.execute(kb_q)).scalars().all()
        results["kb"] = [
            {
                "doc_id": k.doc_id,
                "title": k.title,
                "category": k.category,
                "tags": k.tags,
            }
            for k in kbs
        ]

    # ── 기관 검색 ────────────────────────────────────────────────────────
    if "institution" in wanted:
        inst_q = select(Institution).where(
            or_(Institution.inst_name.ilike(like),
                Institution.inst_code.ilike(like))
        )
        if cust_inst_id is not None and cust_inst_id != -1:
            inst_q = inst_q.where(Institution.id == cust_inst_id)
        inst_q = inst_q.limit(_PER_TYPE_LIMIT)
        insts = (await db.execute(inst_q)).scalars().all()
        results["institution"] = [
            {
                "id": i.id,
                "inst_code": i.inst_code,
                "inst_name": i.inst_name,
            }
            for i in insts
        ]

    total = sum(len(v) for v in results.values())
    return {"query": q, "total": total, "results": results}
