import { useEffect, useState } from 'react'
import { useAuth, jget, jsend } from './auth'
import LoginGate from './AdminLogin'
import { won, box, cell, th, MiniTable, buildPacs008, Row } from './util'

export default function AdminPanel() {
  const { token, user, logout } = useAuth()
  const [summary, setSummary] = useState<any>(null)
  const [transfers, setTransfers] = useState<Row[]>([])
  const [journal, setJournal] = useState<Row[]>([])
  const [views, setViews] = useState<Row[]>([])
  const [insts, setInsts] = useState<Row[]>([])
  const [codes, setCodes] = useState<Row[]>([])
  const [users, setUsers] = useState<Row[]>([])
  const [services, setServices] = useState<any>(null)
  const [svcLog, setSvcLog] = useState<{ id: string; lines: string[] } | null>(null)
  const [busySvc, setBusySvc] = useState<string | null>(null)
  const [msg, setMsg] = useState<string | null>(null)
  const [err, setErr] = useState<string | null>(null)

  // 폼 상태
  const [inst, setInst] = useState({ code: '', name: '', balance: 1000000000 })
  const [user2, setUser2] = useState({ username: '', displayName: '', role: 'ORG_S', orgCode: '' })

  // 테스트 실행(B6)
  const [test, setTest] = useState({ bmiStart: '2026071099000000000001', count: 50 })
  const [testRun, setTestRun] = useState<{ running: boolean; done: number; sent: number; rcvd: number; rjct: number; err: number } | null>(null)

  const loadAll = async () => {
    setErr(null)
    try {
      const [s, t, jn, v, ins, cd, us] = await Promise.all([
        jget('/admin/summary'), jget('/admin/ledger/transfers?limit=15'), jget('/admin/ledger/journal?limit=15'),
        jget('/admin/ledger/views?limit=15'), jget('/admin/institutions'), jget('/admin/status-codes'), jget('/admin/users'),
      ])
      setSummary(s); setTransfers(t); setJournal(jn); setViews(v); setInsts(ins); setCodes(cd); setUsers(us)
    } catch (e: any) { setErr('관리자 데이터 로드 실패: ' + e.message) }
  }
  const loadServices = async () => { try { setServices(await jget('/admin/services')) } catch { /* 폴링 실패 무시 */ } }
  useEffect(() => { if (token) loadAll() }, [token])
  useEffect(() => {
    if (!token) return
    loadServices()
    const t = setInterval(loadServices, 4000)
    return () => clearInterval(t)
  }, [token])

  // 서비스 제어(기동/중지/재기동)
  const svcAction = async (id: string, action: 'start' | 'stop' | 'restart', name: string) => {
    if ((action === 'stop' || action === 'restart') && !confirm(`${name} ${action === 'stop' ? '중지' : '재기동'}할까요?`)) return
    setBusySvc(id + action); setMsg(null); setErr(null)
    try {
      const r = await jsend(`/admin/services/${id}/${action}`)
      if (r.ok === false) setErr(r.message || '제어 실패'); else setMsg(r.message || '완료')
    } catch (e: any) { setErr('제어 실패: ' + e.message) }
    finally { setBusySvc(null); setTimeout(loadServices, 900) }
  }
  const showLog = async (id: string) => {
    try { const r = await jget(`/admin/services/${id}/log?lines=150`); setSvcLog({ id, lines: r.lines || [] }) }
    catch (e: any) { setErr('로그 조회 실패: ' + e.message) }
  }
  const ctlBtn = (bg: string, disabled: boolean): React.CSSProperties => ({
    padding: '4px 10px', background: disabled ? '#ccc' : bg, color: '#fff', border: 0, borderRadius: 5,
    cursor: disabled ? 'default' : 'pointer', fontSize: 12,
  })

  const doReset = async () => {
    if (!confirm('정말 초기화할까요?\n거래/저널/조회사본/원전문을 모두 비우고 계좌 잔액을 각 10억으로 되돌립니다.')) return
    setMsg(null); setErr(null)
    try { const r = await jsend('/admin/reset'); setMsg(`초기화 완료: 계좌 ${r.accountsReset}개 리셋, 원장 비움`); await loadAll() }
    catch (e: any) { setErr('초기화 실패: ' + e.message) }
  }
  const saveInst = async () => {
    if (!/^[0-9]{4}$/.test(inst.code)) { setErr('기관코드는 숫자 4자리'); return }
    try { await jsend('/admin/institutions', inst); setMsg(`기관 저장: ${inst.code}`); await loadAll() } catch (e: any) { setErr('' + e.message) }
  }
  const delInst = async (code: string) => { if (confirm(`기관 ${code} 삭제?`)) { await jsend('/admin/institutions/' + code, undefined, 'DELETE'); await loadAll() } }
  const saveUser = async () => {
    if (!user2.username) { setErr('사용자ID 필수'); return }
    try { await jsend('/admin/users', { ...user2, orgCode: user2.orgCode || null }); setMsg(`사용자 저장: ${user2.username}`); await loadAll() } catch (e: any) { setErr('' + e.message) }
  }
  const delUser = async (u: string) => { if (confirm(`사용자 ${u} 삭제?`)) { await jsend('/admin/users/' + u, undefined, 'DELETE'); await loadAll() } }

  // B6: 테스트 이체 대량 생성(송/수신 랜덤, 금액 1,000~1,000,000 랜덤, BMI 시작번호부터 순번 증가)
  const BANKS_FALLBACK = ['1001', '1002', '1003', '1004', '1005', '1006', '1007', '1008', '1009', '1010']
  const runTest = async () => {
    setErr(null); setMsg(null)
    const n = Number(test.count)
    if (!n || n < 1) { setErr('건수를 1 이상 입력하세요'); return }
    let base: bigint
    try { base = BigInt((test.bmiStart || '').trim()) } catch { setErr('BMI 시작번호는 숫자여야 합니다'); return }
    const banks = insts.length ? insts.map((a) => String(a.code)) : BANKS_FALLBACK
    const st = { running: true, done: 0, sent: n, rcvd: 0, rjct: 0, err: 0 }
    setTestRun({ ...st })
    const one = async (i: number) => {
      const from = banks[Math.floor(Math.random() * banks.length)]
      let to = from, guard = 0
      while (to === from && guard++ < 20) to = banks[Math.floor(Math.random() * banks.length)]
      const amt = 1000 + Math.floor(Math.random() * (1000000 - 1000 + 1))
      const bmi = (base + BigInt(i)).toString().padStart(22, '0')
      try {
        const r = await fetch('/pay/customer', { method: 'POST', headers: { 'Content-Type': 'application/xml' }, body: buildPacs008(bmi, from, to, amt) })
        const txt = await r.text()
        if (txt.includes('RCVD')) st.rcvd++; else st.rjct++
      } catch { st.err++ }
      st.done++
      if (st.done % 10 === 0 || st.done === n) setTestRun({ ...st })
    }
    const CONC = 20 // 브라우저 동시요청 배치
    for (let i = 0; i < n; i += CONC) {
      await Promise.all(Array.from({ length: Math.min(CONC, n - i) }, (_, k) => one(i + k)))
    }
    st.running = false; setTestRun({ ...st })
    setMsg(`테스트 완료: 접수 ${st.rcvd} · 반려 ${st.rjct} · 오류 ${st.err} (완결은 대시보드 새로고침으로 확인)`)
    await loadAll()
  }

  const totalOk = summary && summary.totalBalance === (summary.accounts * 1000000000)

  return (
    <LoginGate>
    <div>
      <div style={{ textAlign: 'right', color: '#666', fontSize: 13, marginTop: 8 }}>
        👤 <b>{user}</b> (ADMIN) <button onClick={logout} style={{ fontSize: 12, marginLeft: 8 }}>로그아웃</button>
      </div>
      {/* 서비스 제어 (기동/중지/재기동 · 하트비트 상태 · 4초 갱신) */}
      <section style={{ ...box, background: '#f7fff7' }}>
        <h2 style={{ marginTop: 0 }}>🖥️ 서비스 제어 <span style={{ fontSize: 12, color: '#888' }}>(기동·중지·재기동 · 하트비트 기반 · 4초 자동 갱신)</span></h2>
        {services?.controlEnabled === false && <p style={{ color: '#b58900', margin: '4px 0' }}>⚠ 제어 비활성화(rtgs.control.enabled=false) — 상태 조회만 가능</p>}
        {!services && <span style={{ color: '#888' }}>상태 수집 대기…</span>}
        {services && (
          <table style={{ borderCollapse: 'collapse', width: '100%' }}>
            <thead><tr>
              <th style={th}>상태</th><th style={th}>서비스</th><th style={th}>포트</th><th style={th}>PID</th><th style={th}>제어</th>
            </tr></thead>
            <tbody>
              {(services.services ?? []).map((s: any) => (
                <tr key={s.id}>
                  <td style={cell}>
                    {s.status === 'UP' ? '🟢 UP' : '🔴 DOWN'}
                    {s.status === 'UP' && s.ageMs != null && <span style={{ color: '#888', fontSize: 11 }}> · {Math.round(s.ageMs / 1000)}s</span>}
                  </td>
                  <td style={{ ...cell, fontWeight: 600 }}>{s.name}</td>
                  <td style={{ ...cell, fontFamily: 'monospace' }}>:{s.port}</td>
                  <td style={{ ...cell, fontFamily: 'monospace', color: '#888' }}>{s.pid ?? '-'}</td>
                  <td style={cell}>
                    {s.controllable ? (
                      <span style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
                        <button disabled={s.status === 'UP' || busySvc !== null} onClick={() => svcAction(s.id, 'start', s.name)} style={ctlBtn('#1a7f37', s.status === 'UP' || busySvc !== null)}>기동</button>
                        <button disabled={s.status !== 'UP' || busySvc !== null} onClick={() => svcAction(s.id, 'stop', s.name)} style={ctlBtn('#c0392b', s.status !== 'UP' || busySvc !== null)}>중지</button>
                        <button disabled={s.status !== 'UP' || busySvc !== null} onClick={() => svcAction(s.id, 'restart', s.name)} style={ctlBtn('#2d6cdf', s.status !== 'UP' || busySvc !== null)}>재기동</button>
                        <button disabled={busySvc !== null} onClick={() => showLog(s.id)} style={ctlBtn('#666', busySvc !== null)}>로그</button>
                      </span>
                    ) : <span style={{ color: '#999', fontSize: 12 }}>선행 필수(스크립트로 기동)</span>}
                  </td>
                </tr>
              ))}
              {(services.infra ?? []).map((f: any) => (
                <tr key={f.id} style={{ background: '#fafafa' }}>
                  <td style={cell}>{f.reachable ? '🟢 UP' : '🔴 DOWN'}</td>
                  <td style={{ ...cell, fontWeight: 600 }}>{f.name} <span style={{ fontSize: 11, color: '#999' }}>(인프라)</span></td>
                  <td style={{ ...cell, fontFamily: 'monospace' }}>:{f.port}</td>
                  <td style={cell}>-</td>
                  <td style={{ ...cell, color: '#999', fontSize: 12 }}>선행 필수(스크립트로 기동)</td>
                </tr>
              ))}
            </tbody>
          </table>
        )}
        {svcLog && (
          <details open style={{ marginTop: 10 }}>
            <summary style={{ cursor: 'pointer', fontWeight: 600 }}>📜 {svcLog.id}.log (최근 {svcLog.lines.length}줄) <button onClick={() => setSvcLog(null)} style={{ fontSize: 11, marginLeft: 8 }}>닫기</button></summary>
            <pre style={{ background: '#0d1117', color: '#c9d1d9', padding: 12, marginTop: 8, maxHeight: 300, overflow: 'auto', fontSize: 12 }}>{svcLog.lines.join('\n') || '(로그 없음)'}</pre>
          </details>
        )}
      </section>

      {/* 대사 대시보드 */}
      <section style={{ ...box, background: '#f7fbff' }}>
        <h2 style={{ marginTop: 0 }}>📊 대사(정합성) 대시보드 <button onClick={loadAll} style={{ fontSize: 12 }}>새로고침</button></h2>
        {summary && (
          <div style={{ display: 'flex', gap: 20, flexWrap: 'wrap' }}>
            <div>총 거래: <b>{summary.transfers}</b></div>
            <div>최대 전역순번: <b>{summary.maxSeq}</b></div>
            <div>계좌수: <b>{summary.accounts}</b></div>
            <div>총액: <b style={{ fontFamily: 'monospace' }}>{won(summary.totalBalance)}</b> {totalOk ? <span style={{ color: '#1a7f37' }}>✓ 보존</span> : <span style={{ color: '#c00' }}>⚠ 확인</span>}</div>
            <div>상태분포: {summary.byStatus?.map((b: any) => <span key={b.status} style={{ marginRight: 8 }}><code>{b.status}</code> {b.cnt}</span>)}</div>
          </div>
        )}
        <MiniTable title="원장(transfer) — Dior 접수→Hermes 결제→Prada 완결"
          cols={[['global_seq', '순번'], ['bmi', 'BMI'], ['status', '상태'], ['sender_code', '송신'], ['receiver_code', '수신'], ['amount', '금액'], ['updated_at', '최종수정']]}
          rows={transfers} timeCols={['updated_at']} />
        <MiniTable title="선저널(journal_log) — Hermes write-ahead"
          cols={[['global_seq', '순번'], ['bmi', 'BMI'], ['applied', '적용']]} rows={journal} />
        <MiniTable title="조회사본(settlement_view) — Prada"
          cols={[['global_seq', '순번'], ['bmi', 'BMI'], ['final_status', '최종상태'], ['debtor_balance_after', '송신잔액'], ['creditor_balance_after', '수신잔액'], ['finalized_at', '완결시각']]}
          rows={views} timeCols={['finalized_at']} />
      </section>

      {/* DB 초기화 */}
      <section style={box}>
        <h2 style={{ marginTop: 0 }}>♻️ 테스트용 DB 초기화</h2>
        <p style={{ color: '#555' }}>거래/저널/조회사본/원전문을 모두 비우고 계좌 잔액을 각 10억으로 되돌립니다. (Kafka 저널 이력은 보존)</p>
        <button onClick={doReset} style={{ padding: '10px 20px', background: '#c0392b', color: '#fff', border: 0, borderRadius: 6, cursor: 'pointer' }}>DB 초기화 실행</button>
      </section>

      {/* 기관/코드 관리 */}
      <section style={box}>
        <h2 style={{ marginTop: 0 }}>🏛 코드 관리 — 참가기관 마스터</h2>
        <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', alignItems: 'flex-end', marginBottom: 8 }}>
          <label>기관코드(4자리)<br /><input value={inst.code} onChange={(e) => setInst({ ...inst, code: e.target.value })} style={{ padding: 6, width: 100, fontFamily: 'monospace' }} /></label>
          <label>기관명<br /><input value={inst.name} onChange={(e) => setInst({ ...inst, name: e.target.value })} style={{ padding: 6, width: 160 }} /></label>
          <label>초기잔액<br /><input type="number" value={inst.balance} onChange={(e) => setInst({ ...inst, balance: Number(e.target.value) })} style={{ padding: 6, width: 140 }} /></label>
          <button onClick={saveInst} style={{ padding: '8px 16px' }}>추가/수정</button>
        </div>
        <table style={{ borderCollapse: 'collapse', width: '100%' }}>
          <thead><tr><th style={th}>코드</th><th style={th}>기관명</th><th style={{ ...th, textAlign: 'right' }}>잔액</th><th style={th}></th></tr></thead>
          <tbody>{insts.map((a) => (
            <tr key={a.code}>
              <td style={{ ...cell, fontFamily: 'monospace' }}>{a.code}</td><td style={cell}>{a.name}</td>
              <td style={{ ...cell, textAlign: 'right', fontFamily: 'monospace' }}>{won(a.balance)}</td>
              <td style={cell}><button onClick={() => setInst({ code: a.code, name: a.name, balance: a.balance })} style={{ fontSize: 11 }}>편집</button> <button onClick={() => delInst(a.code)} style={{ fontSize: 11, color: '#c00' }}>삭제</button></td>
            </tr>))}</tbody>
        </table>
        <MiniTable title="처리상태 코드(데이터 사전)" cols={[['code', '코드'], ['name', '한글명'], ['desc', '설명']]} rows={codes} />
      </section>

      {/* 사용자 권한 관리 */}
      <section style={box}>
        <h2 style={{ marginTop: 0 }}>👤 사용자 권한 관리 <span style={{ fontSize: 12, color: '#888' }}>(관리 마스터 · ADMIN 로그인 적용됨)</span></h2>
        <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', alignItems: 'flex-end', marginBottom: 8 }}>
          <label>사용자ID<br /><input value={user2.username} onChange={(e) => setUser2({ ...user2, username: e.target.value })} style={{ padding: 6, width: 120 }} /></label>
          <label>사용자명<br /><input value={user2.displayName} onChange={(e) => setUser2({ ...user2, displayName: e.target.value })} style={{ padding: 6, width: 140 }} /></label>
          <label>역할<br /><select value={user2.role} onChange={(e) => setUser2({ ...user2, role: e.target.value })} style={{ padding: 6 }}>
            <option value="ADMIN">ADMIN(관리자)</option><option value="ORG_S">ORG_S(송신기관)</option><option value="ORG_R">ORG_R(수신기관)</option>
          </select></label>
          <label>매핑기관<br /><input value={user2.orgCode} onChange={(e) => setUser2({ ...user2, orgCode: e.target.value })} placeholder="1001" style={{ padding: 6, width: 90, fontFamily: 'monospace' }} /></label>
          <button onClick={saveUser} style={{ padding: '8px 16px' }}>추가/수정</button>
        </div>
        <table style={{ borderCollapse: 'collapse', width: '100%' }}>
          <thead><tr><th style={th}>사용자ID</th><th style={th}>사용자명</th><th style={th}>역할</th><th style={th}>매핑기관</th><th style={th}></th></tr></thead>
          <tbody>{users.map((u) => (
            <tr key={u.username}>
              <td style={{ ...cell, fontFamily: 'monospace' }}>{u.username}</td><td style={cell}>{u.displayName}</td>
              <td style={cell}><b>{u.role}</b></td><td style={{ ...cell, fontFamily: 'monospace' }}>{u.orgCode ?? '-'}</td>
              <td style={cell}><button onClick={() => delUser(u.username)} style={{ fontSize: 11, color: '#c00' }}>삭제</button></td>
            </tr>))}</tbody>
        </table>
      </section>

      {/* 테스트 실행 (B6) */}
      <section style={box}>
        <h2 style={{ marginTop: 0 }}>🧪 테스트 실행 — 이체 대량 생성</h2>
        <p style={{ color: '#555' }}>송신/수신기관 <b>랜덤</b>, 금액 <b>1,000~1,000,000원 랜덤</b>, BMI는 시작번호부터 순번 증가.
          (Chanel 직접 호출 — 관문/인증 우회. k6 대체용 간이 도구)</p>
        <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', alignItems: 'flex-end', marginBottom: 8 }}>
          <label>BMI 시작번호<br /><input value={test.bmiStart} onChange={(e) => setTest({ ...test, bmiStart: e.target.value })} style={{ padding: 6, width: 220, fontFamily: 'monospace' }} /></label>
          <label>건수<br /><input type="number" value={test.count} onChange={(e) => setTest({ ...test, count: Number(e.target.value) })} style={{ padding: 6, width: 100 }} /></label>
          <button onClick={runTest} disabled={testRun?.running} style={{ padding: '8px 16px', background: '#2d6cdf', color: '#fff', border: 0, borderRadius: 6, cursor: 'pointer' }}>{testRun?.running ? '실행 중…' : '실행'}</button>
        </div>
        {testRun && (
          <div style={{ fontFamily: 'monospace', fontSize: 13 }}>
            진행 <b>{testRun.done}/{testRun.sent}</b> · 접수(RCVD) {testRun.rcvd} · 반려(RJCT) {testRun.rjct} · 오류 {testRun.err}
          </div>
        )}
      </section>

      {msg && <p style={{ color: '#1a7f37', marginTop: 12 }}>{msg}</p>}
      {err && <p style={{ color: '#c00', marginTop: 12 }}>{err}</p>}
    </div>
    </LoginGate>
  )
}
