import { useEffect, useState } from 'react'
import { Cpu, Save, Info, ShieldCheck } from 'lucide-react'
import { Card, Btn } from '../components/ui'
import { getRagToggles, updateRagToggle } from '../api/client'
import { canManage } from '../components/rbac'

/**
 * MES AI 기법 설정 화면 — 중앙 guardia-rag 최신 기법 토글(솔루션별 격리, mes_setting 저장).
 *
 * - rerank·graphrag·hybrid·tool_use·structured·stream on/off + 파라미터(top_k·max_steps·temperature·model).
 * - 무거운 기법(graphrag·rerank·tool_use·stream)은 서버 RAM 제약상 기본 off — 경고 배지 표시.
 * - 변경은 MANAGER+ 권한(SecurityConfig PUT /api/mes/rag/toggles/** = MANAGER+). 그 외 조회 전용.
 */

type Toggles = {
  ragEnabled: boolean; ragAvailable: boolean
  retrievalMode: string
  rerank: boolean; graphrag: boolean; hybrid: boolean
  toolUse: boolean; structured: boolean; stream: boolean
  topK: number; maxSteps: number; temperature: number; generationModel: string
}

const HEAVY = new Set(['rag.graphrag', 'rag.rerank', 'rag.tool_use', 'rag.stream'])

export default function RagSettings() {
  const [t, setT] = useState<Toggles | null>(null)
  const [msg, setMsg] = useState(''); const [err, setErr] = useState('')
  const editable = canManage()

  const load = () =>
    getRagToggles()
      .then((d: any) => { setT(d); setErr('') })
      .catch(() => setErr('RAG 토글을 불러오지 못했습니다.'))
  useEffect(() => { load() }, [])

  const save = async (key: string, value: any) => {
    setMsg(''); setErr('')
    try { const d = await updateRagToggle(key, value); setT(d); setMsg(`'${key}' 저장됨`) }
    catch (e: any) { setErr(e?.response?.status === 403 ? '변경은 Manager+ 권한이 필요합니다.' : '저장 실패') }
  }

  if (!t) return <div className="text-slate-400 text-sm">{err || '불러오는 중…'}</div>

  const Toggle = ({ k, label, desc, on }: { k: string; label: string; desc: string; on: boolean }) => (
    <div className="flex items-start justify-between gap-3 py-2.5 border-b border-edge last:border-0">
      <div>
        <div className="text-sm font-medium flex items-center gap-2">
          {label}
          {HEAVY.has(k) && <span className="text-[10px] px-1.5 py-0.5 rounded bg-amber-500/15 text-amber-300 border border-amber-500/30">무거움</span>}
        </div>
        <div className="text-xs text-slate-400 mt-0.5">{desc}</div>
      </div>
      <button
        disabled={!editable}
        onClick={() => save(k, !on)}
        className={`shrink-0 w-11 h-6 rounded-full transition-colors relative disabled:opacity-40 ${on ? 'bg-brand' : 'bg-slate-600'}`}
        title={on ? 'ON' : 'OFF'}
      >
        <span className={`absolute top-0.5 w-5 h-5 rounded-full bg-white transition-all ${on ? 'left-5' : 'left-0.5'}`} />
      </button>
    </div>
  )

  return (
    <div>
      <div className="flex items-center justify-between mb-6">
        <div>
          <h1 className="text-xl font-bold flex items-center gap-2"><Cpu className="text-brand" size={20} /> AI 기법 설정</h1>
          <p className="text-sm text-slate-400 mt-0.5">중앙 guardia-rag 최신 기법 적용(검색 모드·리랭크·GraphRAG·에이전틱·구조화·스트리밍). 솔루션별 격리 저장.</p>
        </div>
        <span className={`flex items-center gap-1.5 text-xs px-3 py-1.5 rounded-lg border ${t.ragAvailable ? 'text-brand border-brand/30 bg-brand/10' : 'text-slate-400 border-edge bg-card'}`}>
          <span className={`w-1.5 h-1.5 rounded-full ${t.ragAvailable ? 'bg-brand' : 'bg-slate-500'}`} />
          중앙 RAG {t.ragAvailable ? '연결됨' : '미가용 (로컬 폴백)'}
        </span>
      </div>

      {msg && <div className="bg-brand/10 border border-brand/30 text-brand text-sm rounded-lg px-4 py-2.5 mb-4">{msg}</div>}
      {err && <div className="bg-rose-500/10 border border-rose-500/40 text-rose-300 text-sm rounded-lg px-4 py-2.5 mb-4">{err}</div>}
      {!editable && <div className="bg-amber-500/10 border border-amber-500/30 text-amber-300 text-sm rounded-lg px-4 py-2.5 mb-4">조회 전용입니다. 기법 변경은 Manager+ 권한이 필요합니다.</div>}

      <div className="grid grid-cols-1 lg:grid-cols-2 gap-5">
        <Card title="마스터 / 검색 모드" icon={<ShieldCheck size={15} />}>
          <Toggle k="rag.enabled" label="중앙 RAG 경유" desc="off 시 MES 결정론 로컬 폴백으로 즉시 회귀(기존 동작)." on={t.ragEnabled} />
          <div className="py-2.5 border-b border-edge">
            <div className="text-sm font-medium mb-1.5">검색 모드 (retrieval_mode)</div>
            <div className="flex gap-2">
              {['vector', 'hybrid', 'graph'].map(m => (
                <button key={m} disabled={!editable} onClick={() => save('rag.retrieval_mode', m)}
                  className={`px-3 py-1.5 text-xs rounded-lg border disabled:opacity-40 ${t.retrievalMode === m ? 'bg-brand text-ink border-brand' : 'bg-card border-edge text-slate-300 hover:border-brand'}`}>
                  {m}
                </button>
              ))}
            </div>
            <div className="text-xs text-slate-400 mt-1.5">graphrag/hybrid 토글이 켜지면 그 모드가 우선 적용됩니다.</div>
          </div>
          <Toggle k="rag.hybrid" label="하이브리드 검색" desc="BM25 키워드 + 벡터 앙상블. 검색 정확도↑(중간 비용)." on={t.hybrid} />
          <Toggle k="rag.rerank" label="리랭킹 (rerank)" desc="cross-encoder/LLM 재정렬. 상위 정밀도↑(추가 추론 비용)." on={t.rerank} />
          <Toggle k="rag.graphrag" label="GraphRAG" desc="지식그래프 기반 검색. 다중 홉 질의에 유리(고비용)." on={t.graphrag} />
        </Card>

        <Card title="에이전틱 / 출력" icon={<Info size={15} />}>
          <Toggle k="rag.tool_use" label="에이전틱 tool-use (/agent)" desc="조회 매퍼를 도구로 멀티스텝 추론. 불량 RCA·예측 해석에 활용(고비용)." on={t.toolUse} />
          <Toggle k="rag.structured" label="구조화 출력 (/structured)" desc="JSON 스키마 강제 — 결정론적 결과 객체(경량, 기본 ON 권장)." on={t.structured} />
          <Toggle k="rag.stream" label="토큰 스트리밍 (SSE)" desc="긴 답변 점진 표시. 동시성 위협 시 off 유지(고비용)." on={t.stream} />

          <div className="grid grid-cols-2 gap-3 mt-3">
            <NumField label="top_k (1~20)" value={t.topK} min={1} max={20} disabled={!editable} onSave={v => save('rag.top_k', v)} />
            <NumField label="max_steps (1~8)" value={t.maxSteps} min={1} max={8} disabled={!editable} onSave={v => save('rag.max_steps', v)} />
            <NumField label="temperature (0~1)" value={t.temperature} min={0} max={1} step={0.1} disabled={!editable} onSave={v => save('rag.temperature', v)} />
            <TextField label="생성 모델" value={t.generationModel} disabled={!editable} onSave={v => save('rag.generation_model', v)} />
          </div>
        </Card>
      </div>

      <div className="mt-4 text-xs text-slate-500">
        보안 불변: 외부 API 0 (중앙·로컬 모두 Ollama 온프레미스). 무거운 기법은 서버 RAM 제약상 기본 off — 미가용 시 결정론 폴백(degraded:true).
      </div>
    </div>
  )
}

function NumField({ label, value, min, max, step = 1, disabled, onSave }:
  { label: string; value: number; min: number; max: number; step?: number; disabled?: boolean; onSave: (v: number) => void }) {
  const [v, setV] = useState(String(value))
  useEffect(() => { setV(String(value)) }, [value])
  return (
    <div>
      <label className="text-xs text-slate-400">{label}</label>
      <div className="flex gap-1.5 mt-1">
        <input type="number" min={min} max={max} step={step} value={v} disabled={disabled}
          onChange={e => setV(e.target.value)}
          className="w-full bg-ink border border-edge rounded px-2 py-1 text-sm disabled:opacity-50" />
        <Btn size="sm" disabled={disabled} onClick={() => onSave(Number(v))}><Save size={12} /></Btn>
      </div>
    </div>
  )
}

function TextField({ label, value, disabled, onSave }:
  { label: string; value: string; disabled?: boolean; onSave: (v: string) => void }) {
  const [v, setV] = useState(value)
  useEffect(() => { setV(value) }, [value])
  return (
    <div>
      <label className="text-xs text-slate-400">{label}</label>
      <div className="flex gap-1.5 mt-1">
        <input value={v} disabled={disabled} onChange={e => setV(e.target.value)}
          className="w-full bg-ink border border-edge rounded px-2 py-1 text-sm disabled:opacity-50" />
        <Btn size="sm" disabled={disabled} onClick={() => onSave(v)}><Save size={12} /></Btn>
      </div>
    </div>
  )
}
