// app/admin.jsx — 업체(테넌트)단위 관리자 화면 (실 영속화)
// 좌: 업체 목록(선택 가능) · 우: 선택 업체의 설정 폼.
// 로드: GET /api/admin/config(백엔드 영속본) → 실패 시 window.RibbonData.TENANT_CONFIGS 시드 폴백(정적 열람).
// 저장: POST /api/admin/config → 파일 영속(.alpaca-admin.json). serve.ts 가 챗 시 이 설정으로 LLM 을 고른다.
// window.RibbonAdmin 로 노출.

const { useState: useStateA, useEffect: useEffectA } = React;
const { Icon: IconA } = window.RibbonChat;

// 관리자 설정 로드/저장 (백엔드 영속). 정적(file://)으로 열면 fetch 실패 → 시드 폴백.
async function adminLoad() {
  const res = await fetch('/api/admin/config');
  if (!res.ok) throw new Error('admin api ' + res.status);
  return res.json(); // { catalog, configs, store }
}
async function adminSave(tenantId, config) {
  const res = await fetch('/api/admin/config', {
    method: 'POST', headers: { 'content-type': 'application/json' },
    body: JSON.stringify({ tenant_id: tenantId, config }),
  });
  if (!res.ok) throw new Error((await res.json().catch(() => ({}))).error || ('admin save ' + res.status));
  return res.json(); // { ok, tenant_id, config }
}

// LLM 제공자 / 가드레일 정책 옵션
// 사내 kfx-llm 제외(D9/docs/52 §3) — 백엔드 LlmProviderName("openai"|"claude")과 정합.
const AD_PROVIDERS = [
  { value: 'openai', label: 'OpenAI (gpt-4o 기본)' },
  { value: 'claude', label: 'Claude (Anthropic)' },
];
const AD_GUARDRAILS = [
  { value: 'default', label: 'default (기본)' },
  { value: 'strict', label: 'strict (보수적)' },
  { value: 'relaxed', label: 'relaxed (완화)' },
];

// 공용 입력 스타일 (디자인 토큰)
const AD_INPUT = {
  height: 38, padding: '0 12px', borderRadius: 'var(--radius-md)', border: '1px solid var(--border-hairline)',
  background: 'var(--surface-page)', fontFamily: 'var(--font-sans)', fontSize: 13.5, color: 'var(--text-heading)', outline: 'none',
};

// ── 스위치(토글) ────────────────────────────────────────────
function AdSwitch({ on, onChange }) {
  return (
    <button type="button" role="switch" aria-checked={!!on} onClick={() => onChange(!on)}
      style={{ position: 'relative', width: 40, height: 23, borderRadius: 999, border: 'none', cursor: 'pointer', padding: 0, flexShrink: 0,
        background: on ? 'var(--accent)' : 'var(--surface-card-strong)', transition: 'background .15s' }}>
      <span style={{ position: 'absolute', top: 2, left: on ? 19 : 2, width: 19, height: 19, borderRadius: '50%',
        background: '#fff', boxShadow: '0 1px 2px rgba(0,0,0,.25)', transition: 'left .15s' }} />
    </button>
  );
}

// ── 설정 행(라벨 + 컨트롤) ──────────────────────────────────
function AdRow({ label, hint, children }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 16, padding: '14px 0', borderBottom: '1px solid var(--border-hairline-soft)' }}>
      <div style={{ width: 190, flexShrink: 0 }}>
        <div style={{ fontSize: 13.5, fontWeight: 600, color: 'var(--text-heading)' }}>{label}</div>
        {hint && <div style={{ fontSize: 11.5, color: 'var(--text-faint)', marginTop: 2, lineHeight: 1.4 }}>{hint}</div>}
      </div>
      <div style={{ flex: 1, minWidth: 0, display: 'flex', alignItems: 'center', gap: 10 }}>{children}</div>
    </div>
  );
}

// ── 섹션 헤딩 ───────────────────────────────────────────────
function AdSection({ label, first }) {
  return (
    <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.6px', color: 'var(--text-faint)', textTransform: 'uppercase',
      margin: first ? '18px 0 0' : '26px 0 0' }}>{label}</div>
  );
}

// ── 업체단위 관리자 화면 ────────────────────────────────────
function TenantAdmin() {
  const D = window.RibbonData;
  const tenants = D.TENANTS;
  // 초기 시드(정적 폴백). 마운트 시 백엔드 영속본으로 덮어쓴다.
  const [configs, setConfigs] = useStateA(() => {
    const seed = {};
    for (const tn of tenants) seed[tn.id] = JSON.parse(JSON.stringify(D.TENANT_CONFIGS[tn.id]));
    return seed;
  });
  const [selectedId, setSelectedId] = useStateA(tenants[0].id);
  const [saved, setSaved] = useStateA(false);
  const [busy, setBusy] = useStateA(false);
  const [source, setSource] = useStateA('seed'); // 'seed' | 'persisted' | 'error'

  // 마운트: 백엔드 영속 설정 로드(실패 시 시드 유지).
  useEffectA(() => {
    let alive = true;
    adminLoad()
      .then(({ configs: persisted }) => { if (alive && persisted) { setConfigs(persisted); setSource('persisted'); } })
      .catch(() => { if (alive) setSource('error'); });
    return () => { alive = false; };
  }, []);

  const tenant = tenants.find(tn => tn.id === selectedId) || tenants[0];
  const cfg = configs[selectedId];

  // 로컬 편집(깊은 복사 뮤테이션). 실 저장은 save() 가 백엔드 POST.
  function patch(mut) {
    setConfigs(cs => {
      const next = JSON.parse(JSON.stringify(cs[selectedId]));
      mut(next);
      return { ...cs, [selectedId]: next };
    });
    setSaved(false);
  }
  function selectTenant(id) { setSelectedId(id); setSaved(false); }
  const toList = (s) => s.split(',').map(x => x.trim()).filter(Boolean);

  async function save() {
    setBusy(true);
    try {
      const { config } = await adminSave(selectedId, configs[selectedId]);
      setConfigs(cs => ({ ...cs, [selectedId]: config })); // 서버 병합본으로 정합
      setSource('persisted');
      setSaved(true);
    } catch (e) {
      alert('저장 실패: ' + e.message);
    } finally {
      setBusy(false);
    }
  }

  return (
    <div style={{ flex: 1, minHeight: 0, display: 'flex', background: 'var(--surface-soft)', fontFamily: 'var(--font-sans)' }}>
      {/* 좌: 업체 목록 */}
      <div style={{ width: 300, flexShrink: 0, borderRight: '1px solid var(--border-hairline)', background: 'var(--surface-soft)',
        display: 'flex', flexDirection: 'column', height: '100%' }}>
        <div style={{ padding: '18px 18px 12px' }}>
          <div style={{ fontFamily: 'var(--font-display)', fontSize: 18, letterSpacing: '-0.3px', color: 'var(--text-heading)' }}>업체 관리</div>
          <div style={{ fontSize: 12, color: 'var(--text-faint)', marginTop: 2 }}>업체를 선택해 설정을 편집합니다</div>
        </div>
        <div style={{ flex: 1, overflowY: 'auto', padding: '4px 12px 16px' }}>
          {tenants.map(tn => {
            const on = tn.id === selectedId;
            const isPilot = configs[tn.id].pilot;
            return (
              <button key={tn.id} onClick={() => selectTenant(tn.id)}
                style={{ width: '100%', textAlign: 'left', display: 'flex', alignItems: 'center', gap: 11, padding: '11px 12px',
                  borderRadius: 'var(--radius-md)', marginBottom: 3, cursor: 'pointer',
                  background: on ? 'var(--surface-page)' : 'transparent', border: on ? '1px solid var(--border-hairline)' : '1px solid transparent' }}>
                <div style={{ width: 34, height: 34, borderRadius: 9, flexShrink: 0, display: 'flex', alignItems: 'center', justifyContent: 'center',
                  background: on ? 'var(--accent)' : 'var(--surface-card-strong)', fontSize: 13, fontWeight: 700, color: on ? '#fff' : 'var(--text-body)' }}>{tn.name.slice(0, 1)}</div>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: 13.5, fontWeight: 600, color: 'var(--text-heading)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{tn.name}</div>
                  <div style={{ fontSize: 11.5, color: 'var(--text-muted)', marginTop: 1 }}>{tn.region} · {tn.sys_code}/{tn.corp_code}</div>
                </div>
                {isPilot &&
                  <span style={{ fontSize: 10, fontWeight: 700, letterSpacing: '0.3px', color: '#3f8a52', background: 'rgba(93,184,114,0.14)',
                    padding: '2px 7px', borderRadius: 'var(--radius-pill)', flexShrink: 0 }}>파일럿</span>}
              </button>
            );
          })}
        </div>
      </div>

      {/* 우: 선택 업체 설정 폼 */}
      <div style={{ flex: 1, minWidth: 0, overflowY: 'auto', background: 'var(--surface-page)' }}>
        <div style={{ maxWidth: 680, margin: '0 auto', padding: '24px 28px 40px' }}>
          {/* 헤더 + 저장 */}
          <div style={{ display: 'flex', alignItems: 'center', gap: 14, paddingBottom: 18, borderBottom: '1px solid var(--border-hairline)' }}>
            <div>
              <div style={{ fontFamily: 'var(--font-display)', fontSize: 22, letterSpacing: '-0.4px', color: 'var(--text-heading)' }}>{tenant.name}</div>
              <div style={{ fontSize: 12.5, color: 'var(--text-faint)', marginTop: 2 }}>
                {tenant.region} · 키 {tenant.sys_code}/{tenant.corp_code} · 모자이카 {tenant.mosaicar_yn === 'Y' ? '구독' : '미구독'}</div>
            </div>
            <div style={{ marginLeft: 'auto', display: 'flex', alignItems: 'center', gap: 10 }}>
              {source === 'error' &&
                <span style={{ fontSize: 11.5, color: 'var(--text-faint)' }}>정적 열람(백엔드 미연결)</span>}
              {saved && source === 'persisted' &&
                <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, fontSize: 12, fontWeight: 600, color: 'var(--color-success)' }}>
                  <IconA d="M20 6L9 17l-5-5" size={15} color="var(--color-success)" />저장됨</span>}
              <button onClick={save} disabled={busy}
                style={{ height: 38, padding: '0 18px', borderRadius: 'var(--radius-md)', border: 'none', background: 'var(--accent)', color: '#fff',
                  fontFamily: 'var(--font-sans)', fontSize: 13.5, fontWeight: 600, cursor: busy ? 'default' : 'pointer', opacity: busy ? 0.6 : 1 }}>
                {busy ? '저장 중…' : '저장'}</button>
            </div>
          </div>

          {/* LLM */}
          <AdSection label="LLM 설정" first />
          <AdRow label="제공자" hint="응답 생성 LLM 제공자">
            <select value={cfg.llm.provider} onChange={e => patch(c => { c.llm.provider = e.target.value; })}
              style={{ ...AD_INPUT, cursor: 'pointer', minWidth: 240 }}>
              {AD_PROVIDERS.map(p => <option key={p.value} value={p.value}>{p.label}</option>)}
            </select>
          </AdRow>
          <AdRow label="모델" hint="예: gpt-4o · claude-3-5-sonnet">
            <input value={cfg.llm.model} onChange={e => patch(c => { c.llm.model = e.target.value; })}
              placeholder="gpt-4o" style={{ ...AD_INPUT, flex: 1 }} />
          </AdRow>

          {/* 가드레일 */}
          <AdSection label="가드레일" />
          <AdRow label="정책 참조" hint="가격 가드레일(floor/ceiling·승인) 정책">
            <select value={cfg.guardrail_policy_ref} onChange={e => patch(c => { c.guardrail_policy_ref = e.target.value; })}
              style={{ ...AD_INPUT, cursor: 'pointer', minWidth: 240 }}>
              {AD_GUARDRAILS.map(g => <option key={g.value} value={g.value}>{g.label}</option>)}
            </select>
          </AdRow>

          {/* 운영 */}
          <AdSection label="운영" />
          <AdRow label="파일럿" hint="제주 파일럿 대상 여부">
            <AdSwitch on={cfg.pilot} onChange={v => patch(c => { c.pilot = v; })} />
            <span style={{ fontSize: 12.5, color: 'var(--text-muted)' }}>{cfg.pilot ? '파일럿 운영 중' : '비활성'}</span>
          </AdRow>
          <AdRow label="홀드아웃 지점" hint="실험 제외 지점(쉼표로 구분)">
            <input value={cfg.holdout.branches.join(', ')} onChange={e => patch(c => { c.holdout.branches = toList(e.target.value); })}
              placeholder="예: 강남점, 판교점" style={{ ...AD_INPUT, flex: 1 }} />
          </AdRow>
          <AdRow label="홀드아웃 차종" hint="실험 제외 차급(쉼표로 구분)">
            <input value={cfg.holdout.vehicle_classes.join(', ')} onChange={e => patch(c => { c.holdout.vehicle_classes = toList(e.target.value); })}
              placeholder="예: SUV, 승합" style={{ ...AD_INPUT, flex: 1 }} />
          </AdRow>

          {/* 피처 플래그 */}
          <AdSection label="피처 플래그" />
          <AdRow label="플릿 최적화" hint="fleet_optimization">
            <AdSwitch on={cfg.feature_flags.fleet_optimization} onChange={v => patch(c => { c.feature_flags.fleet_optimization = v; })} />
            <span style={{ fontSize: 12.5, color: 'var(--text-muted)' }}>{cfg.feature_flags.fleet_optimization ? 'ON' : 'OFF'}</span>
          </AdRow>
          <AdRow label="자동 적용" hint="auto_apply — 승인 없이 가격 자동 반영">
            <AdSwitch on={cfg.feature_flags.auto_apply} onChange={v => patch(c => { c.feature_flags.auto_apply = v; })} />
            <span style={{ fontSize: 12.5, color: 'var(--text-muted)' }}>{cfg.feature_flags.auto_apply ? 'ON' : 'OFF'}</span>
          </AdRow>
        </div>
      </div>
    </div>
  );
}

// ── 관리자 허브: [업체 설정 | 문제제기 접수함] 탭 ────────────
function AdminHub() {
  const [tab, setTab] = useStateA('tenant'); // 'tenant' | 'feedback'
  const { FeedbackAdmin } = window.RibbonFeedback;
  const TABS = [['tenant', '업체 설정'], ['feedback', '문제제기 접수함']];
  return (
    <div style={{ flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column', fontFamily: 'var(--font-sans)' }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 4, padding: '8px 18px', borderBottom: '1px solid var(--border-hairline)', background: 'var(--surface-page)', flexShrink: 0 }}>
        {TABS.map(([v, label]) => (
          <button key={v} onClick={() => setTab(v)}
            style={{ padding: '7px 14px', borderRadius: 'var(--radius-md)', border: 'none', cursor: 'pointer', fontFamily: 'var(--font-sans)',
              fontSize: 12.5, fontWeight: 600, transition: 'all .12s',
              background: tab === v ? 'var(--surface-soft)' : 'transparent',
              color: tab === v ? 'var(--text-heading)' : 'var(--text-muted)' }}>{label}</button>
        ))}
      </div>
      {tab === 'tenant' ? <TenantAdmin /> : <FeedbackAdmin />}
    </div>
  );
}

window.RibbonAdmin = { TenantAdmin, AdminHub };
