import { useState } from 'react'

type EnvType = 'closed' | 'open'
type SystemType = 'itsm' | 'manager' | 'messenger' | 'all'

const S = {
  page:    { padding: '24px 28px', maxWidth: 1100 },
  tabBar:  { display: 'flex', gap: 4, marginBottom: 24, borderBottom: '2px solid #e2e8f0', paddingBottom: 0 },
  tab:     (active: boolean): React.CSSProperties => ({
    padding: '10px 20px', border: 'none', background: 'none', cursor: 'pointer',
    fontSize: 14, fontWeight: active ? 700 : 400,
    color: active ? '#003366' : '#64748b',
    borderBottom: active ? '2px solid #003366' : '2px solid transparent',
    marginBottom: -2,
  }),
  card:    { background: '#fff', border: '1px solid #e2e8f0', borderRadius: 10, padding: 20, marginBottom: 16 },
  step:    (color: string): React.CSSProperties => ({
    display: 'flex', gap: 0, marginBottom: 20,
  }),
  stepNum: (color: string): React.CSSProperties => ({
    width: 32, height: 32, borderRadius: '50%', background: color, color: '#fff',
    fontWeight: 800, fontSize: 14, display: 'flex', alignItems: 'center',
    justifyContent: 'center', flexShrink: 0, marginRight: 16, marginTop: 2,
  }),
  code:    { background: '#0f172a', color: '#e2e8f0', borderRadius: 8, padding: '12px 16px',
             fontSize: 12, fontFamily: 'monospace', lineHeight: 1.8,
             overflowX: 'auto' as const, whiteSpace: 'pre' as const, margin: '8px 0 0' },
  warn:    { background: '#fef3c7', border: '1px solid #fcd34d', borderRadius: 8, padding: 12, marginBottom: 16, fontSize: 12 },
  info:    { background: '#eff6ff', border: '1px solid #bfdbfe', borderRadius: 8, padding: 12, marginBottom: 16, fontSize: 12 },
  danger:  { background: '#fef2f2', border: '1px solid #fca5a5', borderRadius: 8, padding: 12, marginBottom: 16, fontSize: 12 },
  success: { background: '#f0fdf4', border: '1px solid #bbf7d0', borderRadius: 8, padding: 12, marginBottom: 16, fontSize: 12 },
  badge:   (color: string): React.CSSProperties => ({
    display: 'inline-block', padding: '2px 8px', borderRadius: 8, fontSize: 11,
    fontWeight: 700, background: color, color: '#fff', marginLeft: 8,
  }),
  h2:      { fontSize: 18, fontWeight: 800, color: '#003366', margin: '0 0 4px' },
  h3:      { fontSize: 15, fontWeight: 700, color: '#1e293b', margin: '16px 0 8px' },
  tag:     (c: string, bg: string): React.CSSProperties => ({
    padding: '3px 10px', borderRadius: 10, fontSize: 11, fontWeight: 700,
    color: c, background: bg, display: 'inline-block',
  }),
}

// ── 단계 컴포넌트 ──────────────────────────────────────────────────────────────
function Step({ num, title, color, children }: { num: number; title: string; color: string; children: React.ReactNode }) {
  return (
    <div style={S.step(color)}>
      <div style={S.stepNum(color)}>{num}</div>
      <div style={{ flex: 1 }}>
        <div style={{ fontWeight: 700, fontSize: 14, color: '#1e293b', marginBottom: 8 }}>{title}</div>
        {children}
      </div>
    </div>
  )
}

function Code({ children }: { children: string }) {
  const [copied, setCopied] = useState(false)
  const copy = () => {
    navigator.clipboard?.writeText(children).then(() => { setCopied(true); setTimeout(() => setCopied(false), 2000) })
  }
  return (
    <div style={{ position: 'relative' }}>
      <pre style={S.code}>{children}</pre>
      <button onClick={copy} style={{
        position: 'absolute', top: 8, right: 8, padding: '3px 8px',
        background: copied ? '#16a34a' : '#334155', color: '#fff', border: 'none',
        borderRadius: 4, fontSize: 11, cursor: 'pointer',
      }}>{copied ? '✓ 복사됨' : '복사'}</button>
    </div>
  )
}

function Req() {
  return (
    <div style={{ ...S.card, borderLeft: '4px solid #003366' }}>
      <div style={S.h3}>📋 시스템 요구사항</div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(200px, 1fr))', gap: 10, marginTop: 8 }}>
        {[
          { k: 'OS',      v: 'Ubuntu 22.04 LTS / RHEL 8+' },
          { k: 'CPU',     v: '8코어 이상 (4코어 최소)' },
          { k: 'RAM',     v: '16GB 이상 권장' },
          { k: 'GPU',     v: '8GB VRAM (파인튜닝 선택)' },
          { k: 'Storage', v: '100GB SSD 이상' },
          { k: 'Python',  v: '3.11 이상' },
          { k: 'Node.js', v: '20 LTS 이상' },
          { k: 'PostgreSQL', v: '16 이상' },
        ].map(r => (
          <div key={r.k} style={{ background: '#f8fafc', borderRadius: 8, padding: '8px 12px', border: '1px solid #e2e8f0' }}>
            <div style={{ fontWeight: 700, fontSize: 12, color: '#003366' }}>{r.k}</div>
            <div style={{ fontSize: 12, color: '#374151', marginTop: 2 }}>{r.v}</div>
          </div>
        ))}
      </div>
      <div style={{ ...S.info, marginTop: 12, marginBottom: 0 }}>
        <strong>내부망 필수 포트:</strong> ITSM 8443(HTTPS), Manager 8090(HTTPS), Webmail 8025, API 9001, Ollama 11434, PostgreSQL 5432, Gitea 3000, Jenkins 8080
      </div>
    </div>
  )
}

// ── 폐쇄망 설치 ───────────────────────────────────────────────────────────────
function ClosedNetwork({ system }: { system: SystemType }) {
  const COLORS = ['#003366','#005A8C','#1d4ed8','#7c3aed','#059669','#dc2626','#d97706','#0891b2']
  return (
    <div>
      <div style={S.danger}>
        <strong>🔒 폐쇄망 보안 주의사항</strong><br/>
        • 설치 파일 SHA-256 무결성 검증 필수 — 변조 여부 반드시 확인<br/>
        • USB·이동식 미디어 반입 시 보안 부서 승인 및 바이러스 검사 선행<br/>
        • 설치 중 root 계정 사용 후 반드시 비활성화, opsagent 전용 계정으로 운영<br/>
        • 설치 완료 즉시 기본 admin 비밀번호 변경 (초기값 사용 금지)<br/>
        • 자격증명(IP·비밀번호·SSH 키)을 설치 로그·화면에 노출 금지
      </div>

      <Req />

      {/* STEP 1: 오프라인 패키지 준비 */}
      <Step num={1} title="오프라인 패키지 준비 (외부망 PC에서 수행)" color={COLORS[0]}>
        <div style={S.info}>외부 인터넷이 가능한 PC에서 아래 작업 후 폐쇄망으로 이전합니다.</div>
        <Code>{`# Python 패키지 다운로드
mkdir guardia-offline && cd guardia-offline
pip download fastapi sqlalchemy asyncpg pgvector httpx \\
  paramiko cryptography pydantic uvicorn gunicorn \\
  pillow qrcode --dest ./packages/

# Node.js 패키지 다운로드 (npm pack)
npm pack @vitejs/plugin-react react react-dom axios zustand --pack-destination ./npm-packages/

# Ollama 바이너리 다운로드
curl -Lo ollama-linux-amd64 https://ollama.ai/download/ollama-linux-amd64
chmod +x ollama-linux-amd64

# Ollama 모델 다운로드 (약 20GB)
ollama pull llama3       # 일반 NLP (4.7GB)
ollama pull llava:7b     # 비전·이미지 분석 (4.7GB)
ollama pull nomic-embed-text  # 임베딩 (0.27GB)
ollama pull codellama:7b      # 코드 분석 (3.8GB)

# Ollama 모델 파일 압축
tar czf ollama-models.tar.gz ~/.ollama/models/

# GUARDiA 소스코드 압축
git clone https://github.com/zio/guardia-itsm.git
tar czf guardia-src.tar.gz guardia-itsm/

# 무결성 체크섬 생성 (필수)
sha256sum packages/* ollama-models.tar.gz guardia-src.tar.gz > SHA256SUMS.txt
cat SHA256SUMS.txt`}</Code>
      </Step>

      {/* STEP 2: 보안 반입 */}
      <Step num={2} title="폐쇄망 반입 및 무결성 검증" color={COLORS[1]}>
        <div style={S.warn}>승인된 이동식 미디어 또는 내부망 파일 서버를 통해서만 반입합니다.</div>
        <Code>{`# 폐쇄망 서버에서 수행
# 1. 파일 수신 후 무결성 검증 (필수!)
sha256sum -c SHA256SUMS.txt
# "OK" 출력 확인 — FAILED 시 즉시 중단

# 2. 작업 디렉토리 설정
mkdir -p /opt/guardia/{app,venv,logs,uploads,backups}
mkdir -p /var/www/{manager,zioinfo,mail}
chmod 750 /opt/guardia

# 3. 파일 압축 해제
tar xzf guardia-src.tar.gz -C /opt/guardia/
tar xzf ollama-models.tar.gz -C ~/`}</Code>
      </Step>

      {/* STEP 3: 시스템 패키지 */}
      <Step num={3} title="시스템 패키지 설치 (오프라인 deb/rpm)" color={COLORS[2]}>
        <Code>{`# Ubuntu 22.04 — 오프라인 패키지 (USB에 미리 다운로드)
apt install --no-install-recommends \\
  ./postgresql-16_amd64.deb \\
  ./python3.11_amd64.deb \\
  ./nodejs_20_amd64.deb \\
  ./nginx_amd64.deb

# PostgreSQL 초기화
systemctl enable --now postgresql
su postgres -c "createuser guardia"
su postgres -c "createdb guardia_db -O guardia"
su postgres -c "psql -c \\"ALTER USER guardia PASSWORD 'G@urd1a_2026!'\\""

# pgvector 확장 설치 (오프라인 빌드 또는 패키지)
su postgres -c "psql -d guardia_db -c 'CREATE EXTENSION IF NOT EXISTS vector;'"

# Python 가상환경 + 오프라인 패키지 설치
python3 -m venv /opt/guardia/venv
/opt/guardia/venv/bin/pip install --no-index \\
  --find-links=/opt/guardia-offline/packages/ \\
  fastapi sqlalchemy asyncpg pgvector httpx \\
  paramiko cryptography pydantic uvicorn`}</Code>
      </Step>

      {/* STEP 4: Ollama */}
      <Step num={4} title="Ollama AI 엔진 오프라인 설치" color={COLORS[3]}>
        <div style={S.info}>Ollama는 외부 API 없이 온프레미스에서 완전히 동작합니다. 인터넷 연결 불필요.</div>
        <Code>{`# Ollama 바이너리 설치
cp ./ollama-linux-amd64 /usr/local/bin/ollama
chmod +x /usr/local/bin/ollama

# systemd 서비스 등록
cat > /etc/systemd/system/ollama.service << 'EOF'
[Unit]
Description=Ollama AI Engine
After=network.target

[Service]
ExecStart=/usr/local/bin/ollama serve
Restart=always
Environment=OLLAMA_HOST=0.0.0.0
Environment=OLLAMA_MODELS=/root/.ollama/models

[Install]
WantedBy=multi-user.target
EOF

# 오프라인 모델 복원 (USB에서 복사한 모델)
# 모델 파일은 이미 ~/.ollama/models/ 에 위치해야 함
systemctl enable --now ollama

# 모델 등록 확인 (자동 인식)
sleep 3 && ollama list
# 출력 예시:
# NAME                 SIZE
# llama3:8b            4.7 GB
# llava:7b             4.7 GB
# nomic-embed-text     0.27 GB`}</Code>
      </Step>

      {/* STEP 5: ITSM 설정 */}
      {(system === 'itsm' || system === 'all') && (
        <Step num={5} title="GUARDiA ITSM 설치 및 설정" color={COLORS[4]}>
          <Code>{`# 소스 복사
cp -r /opt/guardia/guardia-itsm/. /opt/guardia/app/

# 환경변수 설정 (폐쇄망 전용)
cat > /opt/guardia/app/.env << 'EOF'
# ── 네트워크 모드 ──
GUARDIA_NETWORK_MODE=closed   # 폐쇄망 모드

# ── 데이터베이스 ──
DATABASE_URL=postgresql+asyncpg://guardia:G%40urd1a_2026%21@localhost:5432/guardia_db

# ── 보안 키 (반드시 랜덤 값으로 교체) ──
SECRET_KEY=$(openssl rand -hex 32)
AES_KEY=$(openssl rand -hex 16)
AES_IV=$(openssl rand -hex 8)

# ── Ollama (온프레미스, 외부 API 완전 차단) ──
OLLAMA_BASE_URL=http://localhost:11434
OLLAMA_MODEL=llama3
OLLAMA_VISION_MODEL=llava:7b

# ── 서버 설정 ──
HOST=127.0.0.1
PORT=9001
WORKERS=4
EOF

# systemd 서비스 등록
cat > /etc/systemd/system/guardia.service << 'EOF'
[Unit]
Description=GUARDiA ITSM Platform
After=network.target postgresql.service ollama.service

[Service]
User=root
WorkingDirectory=/opt/guardia/app
EnvironmentFile=/opt/guardia/app/.env
ExecStart=/opt/guardia/venv/bin/uvicorn main:app \\
  --host 127.0.0.1 --port 9001 --workers 4
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF

systemctl enable --now guardia
sleep 4 && systemctl is-active guardia`}</Code>
        </Step>
      )}

      {/* STEP 6: Manager */}
      {(system === 'manager' || system === 'all') && (
        <Step num={6} title="GUARDiA Manager 설치" color={COLORS[5]}>
          <Code>{`# Manager 소스 복사 및 빌드 (오프라인 npm)
cp -r /opt/guardia/guardia-manager/. /opt/manager/src/
cd /opt/manager/src/frontend

# 오프라인 npm 패키지 설치
npm install --prefer-offline --legacy-peer-deps

# 빌드
npm run build
cp -r dist/. /var/www/manager/

# Manager 백엔드 서비스
cat > /etc/systemd/system/guardia-manager.service << 'EOF'
[Unit]
Description=GUARDiA Manager Backend
After=network.target guardia.service

[Service]
User=root
WorkingDirectory=/opt/manager/src/backend
ExecStart=/opt/guardia/venv/bin/uvicorn main:app \\
  --host 127.0.0.1 --port 8002 --workers 2
Restart=on-failure
EOF

systemctl enable --now guardia-manager`}</Code>
        </Step>
      )}

      {/* STEP 7: Messenger */}
      {(system === 'messenger' || system === 'all') && (
        <Step num={7} title="GUARDiA Messenger 앱 배포 (APK QR 방식)" color={COLORS[6]}>
          <div style={S.info}>
            <strong>💡 앱스토어 없이 배포:</strong> Manager → 📱 앱 배포 → APK 업로드 → QR 생성 → 사용자 스캔 → 설치
          </div>
          <Code>{`# EAS 빌드 APK를 내부망 서버에 복사
cp GUARDiA_Messenger_v1.0.0.apk /opt/guardia/app/uploads/apk/

# Manager에서 APK 등록 (API)
curl -X POST https://localhost:8443/api/app/upload \\
  -H "Authorization: Bearer <ADMIN_TOKEN>" \\
  -F "file=@/opt/guardia/app/uploads/apk/GUARDiA_Messenger_v1.0.0.apk" \\
  -F "version=1.0.0" \\
  -F "release_notes=초기 배포"

# QR 코드 생성 확인
# Manager → 앱 배포 → QR 이미지 → 사용자에게 공유

# 사용자 설치 순서:
# 1. Android 기기에서 QR 스캔
# 2. 랜딩 페이지 → "Android 다운로드" 클릭
# 3. 설정 → 보안 → "알 수 없는 출처" 허용 (최초 1회)
# 4. APK 설치 → 서버 주소 입력 → 로그인`}</Code>
        </Step>
      )}

      {/* STEP 8: nginx + SSL */}
      <Step num={system === 'all' ? 8 : 5} title="nginx 리버스 프록시 + SSL 설정" color={COLORS[7]}>
        <div style={S.warn}>폐쇄망에서는 내부 CA(Certificate Authority)가 발급한 인증서를 사용합니다.</div>
        <Code>{`# 내부 CA로 인증서 생성 (이미 CA가 있는 경우 해당 CA 사용)
openssl req -x509 -newkey rsa:4096 -keyout /etc/ssl/guardia/server.key \\
  -out /etc/ssl/guardia/server.crt -days 3650 -nodes \\
  -subj "/C=KR/ST=Seoul/O=Your-Org/CN=guardia.internal"

# nginx 설정
cat > /etc/nginx/sites-available/guardia << 'EOF'
# ITSM (8443)
server {
  listen 8443 ssl;
  ssl_certificate     /etc/ssl/guardia/server.crt;
  ssl_certificate_key /etc/ssl/guardia/server.key;
  ssl_protocols TLSv1.2 TLSv1.3;

  location / { root /opt/guardia/app/static; try_files $uri /index.html; }
  location /api/ { proxy_pass http://127.0.0.1:9001; }
  location /ws   { proxy_pass http://127.0.0.1:9001; proxy_http_version 1.1;
                   proxy_set_header Upgrade $http_upgrade;
                   proxy_set_header Connection "upgrade"; }
}

# Manager (8090)
server {
  listen 8090 ssl;
  ssl_certificate     /etc/ssl/guardia/server.crt;
  ssl_certificate_key /etc/ssl/guardia/server.key;
  root /var/www/manager;
  location / { try_files $uri /index.html; }
  location /api/  { proxy_pass http://127.0.0.1:8002; }
  location /guardia-api/ { proxy_pass http://127.0.0.1:9001/; }
}
EOF

ln -sf /etc/nginx/sites-available/guardia /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx`}</Code>
      </Step>

      {/* STEP 9: 방화벽 */}
      <Step num={system === 'all' ? 9 : 6} title="방화벽 설정 (내부망 IP만 허용)" color="#dc2626">
        <div style={S.danger}>
          <strong>⚠️ 보안 필수:</strong> 관리 포트는 허가된 관리자 IP에서만 접근 허용. 외부 인터넷 차단 확인.
        </div>
        <Code>{`# UFW 방화벽 (Ubuntu)
ufw default deny incoming
ufw default allow outgoing

# SSH — 관리자 전용 (IP 제한)
ufw allow from <관리자-IP>/32 to any port 22

# ITSM — 내부망 허용
ufw allow from <내부망-CIDR> to any port 8443

# Manager — 내부망 허용
ufw allow from <내부망-CIDR> to any port 8090

# Webmail — 내부망 허용
ufw allow from <내부망-CIDR> to any port 8025

# Messenger 앱 API (선택)
ufw allow from <내부망-CIDR> to any port 8443

# 외부 인터넷 차단 확인 (폐쇄망 필수)
ufw deny out to any port 80   # HTTP 외부 차단
ufw deny out to any port 443  # HTTPS 외부 차단

ufw enable
ufw status verbose`}</Code>
      </Step>

      {/* 완료 확인 */}
      <div style={{ ...S.success, marginTop: 8 }}>
        <strong>✅ 설치 완료 후 필수 점검 사항</strong><br/>
        □ 기본 admin 비밀번호 변경 완료<br/>
        □ SSL 인증서 적용 및 브라우저 경고 없음<br/>
        □ 방화벽 규칙 검토 (ufw status verbose)<br/>
        □ Ollama 모델 정상 로드 (ollama list)<br/>
        □ ITSM 헬스체크: <code>curl -k https://localhost:8443/health</code><br/>
        □ 감사 로그 경로 확인 (/opt/guardia/logs/)<br/>
        □ PostgreSQL 자동 백업 설정 (crontab)<br/>
        □ CSAP 보안 점검 실행 (Manager → CSAP 점검)
      </div>
    </div>
  )
}

// ── 개방망 설치 ───────────────────────────────────────────────────────────────
function OpenNetwork({ system }: { system: SystemType }) {
  const COLORS = ['#059669','#0891b2','#7c3aed','#d97706','#dc2626','#003366','#16a34a','#9333ea']
  return (
    <div>
      <div style={S.warn}>
        <strong>⚠️ 개방망 보안 주의사항</strong><br/>
        • HTTPS 반드시 적용 — HTTP는 자격증명 노출 위험<br/>
        • 관리 포트(8443, 8090) 방화벽으로 허가 IP만 허용<br/>
        • Ollama는 localhost에서만 동작 (외부 노출 금지)<br/>
        • 정기 보안 패치 적용 (Ubuntu: unattended-upgrades 권장)<br/>
        • 기본 자격증명 설치 후 즉시 변경
      </div>

      <Req />

      <Step num={1} title="시스템 초기 설정" color={COLORS[0]}>
        <Code>{`# Ubuntu 22.04 기준
apt update && apt upgrade -y
apt install -y curl wget git unzip software-properties-common \\
  build-essential libssl-dev libffi-dev python3-dev

# Python 3.11
add-apt-repository ppa:deadsnakes/ppa -y
apt install -y python3.11 python3.11-venv python3.11-dev

# Node.js 20 LTS
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt install -y nodejs

# PostgreSQL 16
sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" \\
  > /etc/apt/sources.list.d/pgdg.list'
curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -
apt update && apt install -y postgresql-16 postgresql-16-pgvector

# PostgreSQL 초기화
systemctl enable --now postgresql
su postgres -c "createuser guardia -P"  # 비밀번호 입력
su postgres -c "createdb guardia_db -O guardia"
su postgres -c "psql -d guardia_db -c 'CREATE EXTENSION IF NOT EXISTS vector;'"`}</Code>
      </Step>

      <Step num={2} title="Ollama 설치 및 AI 모델 다운로드" color={COLORS[1]}>
        <div style={S.info}>Ollama는 온프레미스 전용 — 외부 API 호출 없이 서버 내부에서만 동작합니다.</div>
        <Code>{`# Ollama 설치
curl -fsSL https://ollama.ai/install.sh | sh
systemctl enable --now ollama

# 필수 AI 모델 설치 (총 약 15GB, 시간 소요)
ollama pull llama3         # 일반 NLP (4.7GB)
ollama pull llava:7b       # 비전·이미지·스크린샷 분석 (4.7GB)
ollama pull nomic-embed-text  # 임베딩·RAG 검색 (0.27GB)
ollama pull codellama:7b   # 코드·CSS 생성 (3.8GB)

# 서비스 확인
curl http://localhost:11434/api/tags | python3 -c \\
  "import sys,json; [print(m['name']) for m in json.load(sys.stdin)['models']]"

# GPU 가속 설정 (NVIDIA GPU 있는 경우)
# CUDA toolkit 설치 후 Ollama 자동 감지`}</Code>
      </Step>

      <Step num={3} title="GUARDiA ITSM 설치" color={COLORS[2]}>
        <Code>{`# Gitea에서 소스 클론 (개방망)
git clone https://zioinfo.co.kr:3000/zio/guardia-itsm.git /opt/guardia/app
# 또는
git clone <내부-Gitea-URL>/zio/guardia-itsm.git /opt/guardia/app

# Python 가상환경
python3.11 -m venv /opt/guardia/venv
/opt/guardia/venv/bin/pip install -r /opt/guardia/app/requirements.txt

# 환경변수 설정
cat > /opt/guardia/app/.env << 'ENVEOF'
GUARDIA_NETWORK_MODE=open
DATABASE_URL=postgresql+asyncpg://guardia:<비밀번호>@localhost:5432/guardia_db
SECRET_KEY=$(python3 -c "import secrets; print(secrets.token_hex(32))")
AES_KEY=$(python3 -c "import secrets; print(secrets.token_hex(16))")
AES_IV=$(python3 -c "import secrets; print(secrets.token_hex(8))")
OLLAMA_BASE_URL=http://localhost:11434
GUARDIA_ALLOWED_ORIGINS=https://<도메인>:8443,https://<도메인>:8090
ENVEOF

# DB 마이그레이션 및 초기 데이터
cd /opt/guardia/app
/opt/guardia/venv/bin/python3 -c "
from database import engine, Base
import asyncio
asyncio.run(engine.begin().__aenter__())
print('DB 초기화 완료')
"

# systemd 등록 및 시작
cp deploy/guardia.service /etc/systemd/system/
systemctl daemon-reload && systemctl enable --now guardia
sleep 5 && curl http://127.0.0.1:9001/health`}</Code>
      </Step>

      <Step num={4} title="GUARDiA Manager 설치" color={COLORS[3]}>
        <Code>{`# Manager 소스
git clone <Gitea-URL>/zio/guardia-manager.git /opt/manager/src

# Frontend 빌드
cd /opt/manager/src/frontend
npm ci --legacy-peer-deps
npm run build
cp -r dist/. /var/www/manager/

# Backend
cd /opt/manager/src/backend
/opt/guardia/venv/bin/pip install -r requirements.txt
cat > .env << 'EOF'
GUARDIA_ITSM_URL=http://127.0.0.1:9001
SECRET_KEY=$(python3 -c "import secrets; print(secrets.token_hex(32))")
EOF

# 서비스 등록
cp deploy/guardia-manager.service /etc/systemd/system/
systemctl enable --now guardia-manager`}</Code>
      </Step>

      <Step num={5} title="HTTPS 인증서 설정" color={COLORS[4]}>
        <div style={S.warn}>공인 도메인이 있는 경우 Let's Encrypt, 없으면 자체 서명 인증서를 사용합니다.</div>
        <Code>{`# 방법 1: Let's Encrypt (공인 도메인 있는 경우)
apt install -y certbot
certbot certonly --standalone \\
  -d guardia.your-domain.go.kr \\
  --agree-tos --email admin@your-org.go.kr

# 인증서 경로
# /etc/letsencrypt/live/guardia.your-domain.go.kr/fullchain.pem
# /etc/letsencrypt/live/guardia.your-domain.go.kr/privkey.pem

# 방법 2: 자체 서명 인증서 (도메인 없는 경우)
mkdir -p /etc/ssl/guardia
openssl req -x509 -newkey rsa:4096 \\
  -keyout /etc/ssl/guardia/server.key \\
  -out /etc/ssl/guardia/server.crt \\
  -days 3650 -nodes \\
  -subj "/C=KR/O=Your-Org/CN=<서버-IP-또는-도메인>"

# 자동 갱신 (Let's Encrypt)
echo "0 3 * * * certbot renew --quiet && systemctl reload nginx" | crontab -`}</Code>
      </Step>

      <Step num={6} title="nginx 리버스 프록시 설정" color={COLORS[5]}>
        <Code>{`apt install -y nginx

cat > /etc/nginx/sites-available/guardia << 'NGINXEOF'
# ── GUARDiA ITSM (8443) ──────────────────────────────
server {
    listen 8443 ssl http2;
    server_name _;

    ssl_certificate     /etc/ssl/guardia/server.crt;
    ssl_certificate_key /etc/ssl/guardia/server.key;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;
    ssl_session_cache   shared:SSL:10m;

    # 정적 파일 (React SPA)
    root /opt/guardia/app/static;
    location / { try_files $uri /index.html; }

    # API 프록시
    location /api/ {
        proxy_pass         http://127.0.0.1:9001;
        proxy_set_header   Host $host;
        proxy_set_header   X-Forwarded-Proto https;
        proxy_read_timeout 300s;
    }

    # WebSocket (실시간 알림)
    location /ws {
        proxy_pass         http://127.0.0.1:9001;
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection "upgrade";
    }
}

# ── GUARDiA Manager (8090) ──────────────────────────
server {
    listen 8090 ssl http2;
    ssl_certificate     /etc/ssl/guardia/server.crt;
    ssl_certificate_key /etc/ssl/guardia/server.key;

    root /var/www/manager;
    location / { try_files $uri /index.html; }
    location /api/         { proxy_pass http://127.0.0.1:8002; }
    location /guardia-api/ { proxy_pass http://127.0.0.1:9001/; }
}

# ── Webmail (8025) ──────────────────────────────────
server {
    listen 8025 ssl;
    ssl_certificate     /etc/ssl/guardia/server.crt;
    ssl_certificate_key /etc/ssl/guardia/server.key;

    root /var/www/mail;
    location / { try_files $uri /index.html; }
    location /api/ { proxy_pass http://127.0.0.1:8026; }
}
NGINXEOF

ln -sf /etc/nginx/sites-available/guardia /etc/nginx/sites-enabled/
nginx -t && systemctl enable --now nginx`}</Code>
      </Step>

      <Step num={7} title="방화벽 설정" color={COLORS[6]}>
        <Code>{`# UFW 방화벽
ufw default deny incoming
ufw default allow outgoing

# SSH (관리자 IP만)
ufw allow from <관리자-IP> to any port 22

# ITSM/Manager/Webmail (허가 IP 대역만)
ufw allow from <허용-IP-대역>/24 to any port 8443
ufw allow from <허용-IP-대역>/24 to any port 8090
ufw allow from <허용-IP-대역>/24 to any port 8025

# Ollama는 localhost만 (외부 노출 금지!)
# PostgreSQL은 localhost만
# Gitea, Jenkins (선택)
ufw allow from <내부망-CIDR> to any port 3000
ufw allow from <내부망-CIDR> to any port 8080

ufw enable
ufw status numbered`}</Code>
      </Step>

      <Step num={8} title="서비스 시작 및 최종 확인" color={COLORS[7]}>
        <Code>{`# 전체 서비스 상태 확인
systemctl is-active guardia guardia-manager ollama postgresql nginx

# API 헬스체크
curl -sk https://localhost:8443/health      | python3 -m json.tool
curl -sk https://localhost:8090/api/health  | python3 -m json.tool

# Ollama 모델 확인
ollama list

# 초기 admin 로그인 (즉시 비밀번호 변경!)
# URL: https://<서버IP>:8443
# ID: admin  PW: 1111  ← 즉시 변경 필수!

# 보안 점검 실행
curl -sk https://localhost:8443/api/n2sf/checklist \\
  -H "Authorization: Bearer <TOKEN>" | python3 -m json.tool`}</Code>
      </Step>

      <div style={{ ...S.success, marginTop: 8 }}>
        <strong>✅ 개방망 설치 완료 체크리스트</strong><br/>
        □ admin 기본 비밀번호 변경 완료<br/>
        □ HTTPS 인증서 적용 (브라우저 자물쇠 확인)<br/>
        □ 방화벽 규칙 검토 (ufw status numbered)<br/>
        □ Ollama 외부 노출 없음 (curl http://외부IP:11434 실패 확인)<br/>
        □ PostgreSQL 외부 노출 없음<br/>
        □ Let's Encrypt 자동 갱신 설정<br/>
        □ 보안 패치 자동화 (unattended-upgrades)<br/>
        □ 백업 스케줄 설정 (PostgreSQL + 파일)
      </div>
    </div>
  )
}

// ── 메인 페이지 ───────────────────────────────────────────────────────────────
export default function InstallGuide() {
  const [env, setEnv] = useState<EnvType>('closed')
  const [sys, setSys] = useState<SystemType>('all')

  return (
    <div style={S.page}>
      <h1 style={{ fontSize: 22, fontWeight: 800, margin: '0 0 4px', color: '#003366' }}>
        📦 GUARDiA 설치 가이드
      </h1>
      <p style={{ color: '#64748b', marginBottom: 24, fontSize: 13 }}>
        폐쇄망(공공기관 내부망)과 개방망 환경별 단계별 설치 방법
      </p>

      {/* 환경 선택 */}
      <div style={{ display: 'flex', gap: 16, marginBottom: 20 }}>
        <div>
          <div style={{ fontSize: 12, fontWeight: 600, color: '#374151', marginBottom: 6 }}>설치 환경</div>
          <div style={{ display: 'flex', gap: 4 }}>
            {([['closed','🔒 폐쇄망','공공기관 내부망·인터넷 차단'],['open','🌐 개방망','인터넷 연결 가능']] as const).map(([v,label,desc])=>(
              <button key={v} onClick={() => setEnv(v as EnvType)} style={{
                padding: '10px 16px', border: `2px solid ${env===v?'#003366':'#e2e8f0'}`,
                borderRadius: 10, background: env===v?'#003366':'#fff',
                color: env===v?'#fff':'#374151', cursor: 'pointer',
                fontWeight: env===v?700:400, fontSize: 13, textAlign: 'left' as const,
              }}>
                <div>{label}</div>
                <div style={{ fontSize: 11, opacity: .7 }}>{desc}</div>
              </button>
            ))}
          </div>
        </div>

        <div>
          <div style={{ fontSize: 12, fontWeight: 600, color: '#374151', marginBottom: 6 }}>설치 대상</div>
          <div style={{ display: 'flex', gap: 4 }}>
            {([['all','전체','ITSM+Manager+Messenger'],['itsm','ITSM','API 서버'],['manager','Manager','관제 포털'],['messenger','Messenger','모바일 앱']] as const).map(([v,label,desc])=>(
              <button key={v} onClick={() => setSys(v as SystemType)} style={{
                padding: '10px 16px', border: `2px solid ${sys===v?'#003366':'#e2e8f0'}`,
                borderRadius: 10, background: sys===v?'#003366':'#fff',
                color: sys===v?'#fff':'#374151', cursor: 'pointer',
                fontWeight: sys===v?700:400, fontSize: 13, textAlign: 'left' as const,
              }}>
                <div>{label}</div>
                <div style={{ fontSize: 11, opacity: .7 }}>{desc}</div>
              </button>
            ))}
          </div>
        </div>
      </div>

      {/* 선택 배지 */}
      <div style={{ ...S.info, marginBottom: 20 }}>
        현재 선택: <strong>{env === 'closed' ? '🔒 폐쇄망' : '🌐 개방망'}</strong>
        &nbsp;+&nbsp;
        <strong>{sys === 'all' ? '전체 시스템' : `GUARDiA ${sys.toUpperCase()}`}</strong>
        &nbsp;설치 가이드를 표시합니다.
      </div>

      {/* 설치 가이드 렌더링 */}
      {env === 'closed'
        ? <ClosedNetwork system={sys} />
        : <OpenNetwork system={sys} />
      }

      {/* 지원 문의 */}
      <div style={{ ...S.card, borderTop: '3px solid #003366', textAlign: 'center', padding: 24 }}>
        <div style={{ fontSize: 16, fontWeight: 700, color: '#003366', marginBottom: 8 }}>
          설치 지원이 필요하신가요?
        </div>
        <p style={{ fontSize: 13, color: '#64748b', margin: '0 0 12px' }}>
          지오정보기술 전문 엔지니어가 기관 환경에 맞는 설치를 지원합니다.
        </p>
        <div style={{ display: 'flex', gap: 8, justifyContent: 'center', flexWrap: 'wrap' as const }}>
          {[
            { label: '📞 기술 지원 전화', val: '02-0000-0000' },
            { label: '📧 이메일 문의', val: 'support@zioinfo.co.kr' },
            { label: '🌐 홈페이지', val: 'www.zioinfo.co.kr' },
          ].map(c => (
            <div key={c.label} style={{ background: '#f8fafc', border: '1px solid #e2e8f0', borderRadius: 8, padding: '8px 16px', fontSize: 13 }}>
              <span style={{ color: '#64748b' }}>{c.label}: </span>
              <strong style={{ color: '#003366' }}>{c.val}</strong>
            </div>
          ))}
        </div>
      </div>
    </div>
  )
}
