const { useState, useEffect } = React;

// ✅ LocalStorage 기반 영구 저장소 (레거시, 링크 데이터 등에 사용)
const storage = {
  get: (key) => {
    try {
      const value = localStorage.getItem(key);
      return value ? { value } : null;
    } catch (error) {
      console.error('LocalStorage get failed', {
        key,
        errorName: error.name,
        errorMessage: error.message
      });
      return null;
    }
  },
  set: (key, value) => {
    const valueToStore = typeof value === 'string' ? value : JSON.stringify(value);
    try {
      localStorage.setItem(key, valueToStore);
      return true;
    } catch (error) {
      console.error('LocalStorage set failed', {
        key,
        valueType: typeof value,
        valueLength: valueToStore?.length || 0,
        errorName: error.name,
        errorMessage: error.message
      });
      // QuotaExceededError 체크
      if (error.name === 'QuotaExceededError') {
        // 용량 확인
        const totalSize = Object.keys(localStorage).reduce((acc, k) => {
          return acc + (localStorage.getItem(k)?.length || 0);
        }, 0);
      }
      return false;
    }
  },
  remove: (key) => {
    try {
      localStorage.removeItem(key);
      return true;
    } catch (error) {
      return false;
    }
  }
};

// ✅ D1 Database API 헬퍼 함수들
function getAuthHeaders() {
  const token = localStorage.getItem('psy_token');
  return token ? { 'Authorization': `Bearer ${token}` } : {};
}

const api = {
  // 상담사 가입
  async registerCounselor(phone, name, counselorType, password) {
    const response = await fetch('/api/counselor/register', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ phone, name, counselorType, password })
    });
    return await response.json();
  },
  
  // 상담사 승인 (관리자)
  async approveCounselor(phone) {
    const response = await fetch('/api/counselor/approve', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json', ...getAuthHeaders() },
      body: JSON.stringify({ phone })
    });
    return await response.json();
  },
  
  // 대기 중인 상담사 목록
  async getPendingCounselors() {
    const response = await fetch('/api/counselor/pending', { headers: { ...getAuthHeaders() } });
    return await response.json();
  },
  
  // 승인된 상담사 목록
  async getApprovedCounselors() {
    const response = await fetch('/api/counselor/approved', { headers: { ...getAuthHeaders() } });
    return await response.json();
  },
  
  // 상담사 쿼터 조정 (관리자용)
  async updateCounselorQuota(phone, quotaTotal) {
    const response = await fetch('/api/counselor/update-quota', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json', ...getAuthHeaders() },
      body: JSON.stringify({ phone, quotaTotal })
    });
    return await response.json();
  },
  
  // 구독 정보 조회
  async getSubscription(phone) {
    const response = await fetch(`/api/subscription/${phone}`);
    return await response.json();
  },
  
  // 구독 생성/업데이트
  async createSubscription(phone, planType, autoRenewal = true) {
    const response = await fetch('/api/subscription', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ phone, planType, autoRenewal })
    });
    return await response.json();
  },
  
  // 쿼터 소비
  async consumeQuota(phone, linkId, testType, amount = 1) {
    const response = await fetch('/api/quota/consume', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ phone, linkId, testType, amount })
    });
    return await response.json();
  },
  
  // 사용 기록 조회
  async getUsageHistory(phone, limit = 50) {
    const response = await fetch(`/api/usage/${phone}?limit=${limit}`);
    return await response.json();
  },
  
  // 결제 처리 (가상)
  async processPayment(phone, planType, amount) {
    const response = await fetch('/api/payment', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ phone, planType, amount })
    });
    return await response.json();
  },

  // 상담사 로그인 (D1 + 비밀번호 해시 검증)
  async loginCounselor(phone, password) {
    const response = await fetch('/api/counselor/login', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ phone, password })
    });
    return await response.json();
  },

  // 비밀번호 변경
  async changePassword(phone, currentPassword, newPassword) {
    const response = await fetch('/api/counselor/change-password', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ phone, currentPassword, newPassword })
    });
    return await response.json();
  },

  // 비밀번호 초기 설정 (레거시 계정)
  async setPassword(phone, newPassword) {
    const response = await fetch('/api/counselor/set-password', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ phone, newPassword })
    });
    return await response.json();
  }
};



// ── NotificationBell 컴포넌트 ──────────────────────────────────────────
function NotificationBell({ phone }) {
  const [count, setCount] = React.useState(0);
  React.useEffect(() => {
    if (!phone) return;
    const token = localStorage.getItem('psy_token') || '';
    fetch(`/api/notifications?target=${encodeURIComponent(phone)}`, {
      headers: token ? { 'Authorization': 'Bearer ' + token } : {}
    })
      .then(r => r.json())
      .then(d => { if (d.success) setCount((d.data || []).filter(n => !n.is_read).length); })
      .catch(() => {});
  }, [phone]);
  if (count === 0) return null;
  return (
    <div style={{position:'relative',display:'inline-block'}}>
      <span style={{fontSize:'20px'}}>🔔</span>
      <span style={{position:'absolute',top:'-6px',right:'-6px',background:'#ef4444',color:'white',
        borderRadius:'50%',width:'16px',height:'16px',fontSize:'10px',
        display:'flex',alignItems:'center',justifyContent:'center',fontWeight:'700'}}>
        {count > 9 ? '9+' : count}
      </span>
    </div>
  );
}


// ── MonthlyStatsCard 컴포넌트 ─────────────────────────────────────
function MonthlyStatsCard({ authFetch }) {
  const [monthlyStats, setMonthlyStats] = React.useState(null);
  const [statsLoading, setStatsLoading] = React.useState(false);

  const loadStats = async () => {
    setStatsLoading(true);
    try {
      const res = await authFetch('/api/stats/monthly');
      const data = await res.json();
      if (data.success) setMonthlyStats(data.data);
    } catch (e) { console.error('통계 로드 실패', e); }
    finally { setStatsLoading(false); }
  };

  React.useEffect(() => { loadStats(); }, []);

  return (
    <div className="bg-white rounded-xl shadow p-6">
      <div className="flex items-center justify-between mb-5">
        <h2 className="text-lg font-bold">📈 월별 추이 (최근 6개월)</h2>
        <div className="flex gap-2">
          {monthlyStats && (
            <button
              onClick={() => {
                const rows = [
                  '월,검사건수',
                  ...(monthlyStats.sessions || []).map(s => `${s.month},${s.count}`),
                  '', '월,신규가입',
                  ...(monthlyStats.signups || []).map(s => `${s.month},${s.count}`),
                  '', '검사유형,건수',
                  ...(monthlyStats.typeStats || []).map(t => `${t.test_type},${t.count}`),
                ];
                const csv = '\uFEFF' + rows.join('\n');
                const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
                const a = document.createElement('a'); a.href = URL.createObjectURL(blob);
                a.download = `stats_${new Date().toISOString().slice(0,10)}.csv`; a.click();
              }}
              className="text-xs bg-green-600 text-white px-3 py-1.5 rounded hover:bg-green-700 font-bold">
              📥 CSV
            </button>
          )}
          <button onClick={loadStats} disabled={statsLoading}
            className="text-xs bg-gray-100 text-gray-600 px-3 py-1.5 rounded hover:bg-gray-200 disabled:opacity-50">
            {statsLoading ? '로딩...' : '🔄 새로고침'}
          </button>
        </div>
      </div>
      {statsLoading && <div className="text-center py-8 text-gray-400 text-sm">로딩 중...</div>}
      {!statsLoading && monthlyStats && (
        <div className="space-y-5">
          <div>
            <p className="text-xs font-semibold text-gray-600 mb-3">📋 월별 검사 건수</p>
            {monthlyStats.sessions.length === 0
              ? <p className="text-xs text-gray-400">데이터 없음</p>
              : (() => {
                  const maxCount = Math.max(...monthlyStats.sessions.map(s => s.count), 1);
                  return (
                    <div className="space-y-2">
                      {monthlyStats.sessions.map((s, i) => (
                        <div key={i} className="flex items-center gap-3">
                          <span className="text-xs text-gray-500 w-16 shrink-0">{s.month}</span>
                          <div className="flex-1 bg-gray-100 rounded-full h-5">
                            <div className="bg-indigo-500 h-5 rounded-full transition-all"
                              style={{width: `${Math.max(s.count/maxCount*100, 4)}%`}} />
                          </div>
                          <span className="text-xs font-bold text-indigo-700 w-12 text-right">{s.count}건</span>
                        </div>
                      ))}
                    </div>
                  );
                })()
            }
          </div>
          <div>
            <p className="text-xs font-semibold text-gray-600 mb-3">👨‍⚕️ 월별 신규 상담사 가입</p>
            {monthlyStats.signups.length === 0
              ? <p className="text-xs text-gray-400">데이터 없음</p>
              : (() => {
                  const maxCount = Math.max(...monthlyStats.signups.map(s => s.count), 1);
                  return (
                    <div className="space-y-2">
                      {monthlyStats.signups.map((s, i) => (
                        <div key={i} className="flex items-center gap-3">
                          <span className="text-xs text-gray-500 w-16 shrink-0">{s.month}</span>
                          <div className="flex-1 bg-gray-100 rounded-full h-5">
                            <div className="bg-green-500 h-5 rounded-full transition-all"
                              style={{width: `${Math.max(s.count/maxCount*100, 4)}%`}} />
                          </div>
                          <span className="text-xs font-bold text-green-700 w-12 text-right">{s.count}명</span>
                        </div>
                      ))}
                    </div>
                  );
                })()
            }
          </div>
          {monthlyStats.typeStats.length > 0 && (
            <div>
              <p className="text-xs font-semibold text-gray-600 mb-3">🧪 전체 검사 유형별 분포</p>
              <div className="flex flex-wrap gap-2">
                {monthlyStats.typeStats.map((t, i) => {
                  const total = monthlyStats.typeStats.reduce((a, x) => a + x.count, 0);
                  const pct = total > 0 ? Math.round(t.count / total * 100) : 0;
                  const colors = ['bg-indigo-100 text-indigo-700','bg-blue-100 text-blue-700','bg-rose-100 text-rose-700',
                    'bg-orange-100 text-orange-700','bg-amber-100 text-amber-700','bg-teal-100 text-teal-700','bg-red-100 text-red-700'];
                  return (
                    <div key={i} className={`${colors[i % colors.length]} rounded-xl px-3 py-2 text-center min-w-16`}>
                      <div className="text-xs font-bold">{t.test_type}</div>
                      <div className="text-base font-bold">{t.count}</div>
                      <div className="text-xs opacity-70">{pct}%</div>
                    </div>
                  );
                })}
              </div>
            </div>
          )}
        </div>
      )}
    </div>
  );
}

// ── PasswordChangeForm 컴포넌트 ───────────────────────────────────
function PasswordChangeForm({ masterInfo, authFetch }) {
  const [pwForm, setPwForm] = React.useState({ currentPw: '', newPw: '', confirmPw: '' });
  const [pwMsg, setPwMsg] = React.useState({ type: '', text: '' });
  const [pwLoading, setPwLoading] = React.useState(false);

  const changePw = async () => {
    if (!pwForm.newPw || pwForm.newPw.length < 8) {
      setPwMsg({ type: 'error', text: '비밀번호는 8자 이상이어야 합니다.' }); return;
    }
    if (pwForm.newPw !== pwForm.confirmPw) {
      setPwMsg({ type: 'error', text: '비밀번호가 일치하지 않습니다.' }); return;
    }
    setPwLoading(true);
    try {
      const token = localStorage.getItem('psy_token') || '';
      const res = await fetch('/api/master/change-password', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` },
        body: JSON.stringify({ phone: masterInfo?.phone, newPassword: pwForm.newPw, currentPassword: pwForm.currentPw || undefined })
      });
      const data = await res.json();
      if (data.success) {
        setPwMsg({ type: 'success', text: '✅ 비밀번호가 변경되었습니다.' });
        setPwForm({ currentPw: '', newPw: '', confirmPw: '' });
      } else {
        setPwMsg({ type: 'error', text: '❌ ' + (data.error || '변경 실패') });
      }
    } catch (e) {
      setPwMsg({ type: 'error', text: '❌ 서버 오류' });
    } finally {
      setPwLoading(false);
    }
  };

  return (
    <div className="max-w-sm space-y-3">
      <div>
        <label className="block text-xs font-semibold text-gray-700 mb-1">현재 비밀번호</label>
        <input type="password" value={pwForm.currentPw}
          onChange={e => setPwForm(f => ({ ...f, currentPw: e.target.value }))}
          placeholder="현재 비밀번호 입력"
          className="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm outline-none focus:border-gray-500" />
      </div>
      <div>
        <label className="block text-xs font-semibold text-gray-700 mb-1">새 비밀번호 (8자 이상)</label>
        <input type="password" value={pwForm.newPw}
          onChange={e => setPwForm(f => ({ ...f, newPw: e.target.value }))}
          placeholder="새 비밀번호 입력"
          className="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm outline-none focus:border-gray-500" />
      </div>
      <div>
        <label className="block text-xs font-semibold text-gray-700 mb-1">새 비밀번호 확인</label>
        <input type="password" value={pwForm.confirmPw}
          onChange={e => setPwForm(f => ({ ...f, confirmPw: e.target.value }))}
          placeholder="새 비밀번호 재입력"
          className="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm outline-none focus:border-gray-500" />
      </div>
      {pwMsg.text && (
        <p className={`text-xs font-semibold ${pwMsg.type === 'success' ? 'text-green-600' : 'text-red-600'}`}>
          {pwMsg.text}
        </p>
      )}
      <button onClick={changePw} disabled={pwLoading}
        className="w-full bg-gray-800 text-white py-2 rounded-lg text-sm font-bold hover:bg-gray-900 disabled:opacity-60">
        {pwLoading ? '변경 중...' : '비밀번호 변경'}
      </button>
    </div>
  );
}

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false, error: null };
  }
  static getDerivedStateFromError(error) {
    return { hasError: true, error };
  }
  componentDidCatch(error, info) {
    console.error('[앱 오류]', error, info);
  }
  render() {
    if (this.state.hasError) {
      return (
        <div style={{display:'flex',alignItems:'center',justifyContent:'center',minHeight:'100vh',background:'#fef2f2',flexDirection:'column',gap:'12px',padding:'20px',fontFamily:'sans-serif'}}>
          <div style={{fontSize:'48px'}}>⚠️</div>
          <h2 style={{color:'#991b1b',fontSize:'18px',fontWeight:'700',margin:0}}>앱 오류가 발생했습니다</h2>
          <p style={{color:'#7f1d1d',fontSize:'13px',background:'#fee2e2',padding:'12px 16px',borderRadius:'8px',maxWidth:'500px',wordBreak:'break-all',margin:0}}>
            {this.state.error?.message || '알 수 없는 오류'}
          </p>
          <button
            onClick={() => { localStorage.clear(); window.location.reload(); }}
            style={{background:'#dc2626',color:'white',border:'none',padding:'10px 20px',borderRadius:'8px',fontWeight:'700',cursor:'pointer',fontSize:'14px'}}>
            초기화 후 새로고침
          </button>
          <p style={{color:'#9ca3af',fontSize:'11px',margin:0}}>위 버튼을 누르면 로컬 데이터가 삭제되고 새로고침됩니다</p>
        </div>
      );
    }
    return this.props.children;
  }
}

function PsychologicalTestSystem() {

  // ── JWT 토큰 헬퍼 ──────────────────────────────────────────
  function getToken() { return localStorage.getItem('psy_token') || ''; }
  function saveToken(tok) { localStorage.setItem('psy_token', tok); }
  function clearToken() { localStorage.removeItem('psy_token'); }
  function authFetch(url, options = {}) {
    const token = getToken();
    const headers = {
      'Content-Type': 'application/json',
      ...(options.headers || {}),
      ...(token ? { 'Authorization': `Bearer ${token}` } : {})
    };
    return fetch(url, { ...options, headers });
  }

  const [view, setView] = useState("login");
  const [activeLinkId, setActiveLinkId] = useState(null);
  const [activeLinkData, setActiveLinkData] = useState(null);
  const [userInfo, setUserInfo] = useState({ phone: "", password: "" });
  const [isAdmin, setIsAdmin] = useState(false);
  const [isMaster, setIsMaster] = useState(false);
  const [isOrgAdmin, setIsOrgAdmin] = useState(false);
  const [masterInfo, setMasterInfo] = useState(null);   // { phone, name }
  const [masterTab, setMasterTab] = useState('orgs'); // 'orgs' | 'counselors' | 'settings'
  const [masterSessions, setMasterSessions] = useState([]);
  const [masterSessionsLoading, setMasterSessionsLoading] = useState(false);
  const [masterPwForm, setMasterPwForm] = useState({ current: '', newPw: '', confirm: '' });
  const [masterPwMsg, setMasterPwMsg] = useState({ type: '', text: '' });
  const [counselorSearch, setCounselorSearch] = useState('');
  const [counselorFilterOrg, setCounselorFilterOrg] = useState('all');
  const [counselorFilterType, setCounselorFilterType] = useState('all');
  const [counselorFilterStatus, setCounselorFilterStatus] = useState('all');
  const [isCounselor, setIsCounselor] = useState(false);
  const [counselorPhone, setCounselorPhone] = useState("");
  const [orgAdminInfo, setOrgAdminInfo] = useState(null); // { phone, name, org_id, org_name }
  const [organizations, setOrganizations] = useState([]);
  const [orgCounselors, setOrgCounselors] = useState([]);
  const [orgAdminTab, setOrgAdminTab] = useState('counselors'); // 'counselors' | 'sessions'
  const [showOrgForm, setShowOrgForm] = useState(false);
  const [orgForm, setOrgForm] = useState({ _editId: null, name: '', description: '', org_type: 'general', admin_phone: '', subscription_type: 'org_small', billing_cycle: 'monthly' });
  const [orgMsg, setOrgMsg] = useState({ type: '', text: '' });
  const [orgLoading, setOrgLoading] = useState(false);
  const [showNoticeForm, setShowNoticeForm] = useState(false);
  const [noticeForm, setNoticeForm] = useState({ id: null, title: '', content: '', target: 'all', pinned: false, send_notification: false });
  const [noticeMsg, setNoticeMsg] = useState({ type: '', text: '' });
  const [notices, setNotices] = useState([]);
  const [loginMsg, setLoginMsg] = useState({ type: "", text: "" });
  const [loginLoading, setLoginLoading] = useState(false);
  const [counselorForm, setCounselorForm] = useState({
    name: "", phone: "", password: "", certification: "", education: "", experience: ""
  });
  const [linkForm, setLinkForm] = useState({ clientName: "", clientPhone: "", testTypes: ["SCT"], counselingType: "psychological" });
  const [generatedLinks, setGeneratedLinks] = useState([]);
  const [copiedId, setCopiedId] = useState(null);
  const [showLinkId, setShowLinkId] = useState(null);
  // 멀티 검사: 남은 검사 큐 (내담자 진행 중 상태)
  const [pendingTests, setPendingTests] = useState([]);
  const [currentTestIndex, setCurrentTestIndex] = useState(0);
  const [multiSessionIds, setMultiSessionIds] = useState([]); // 완료된 세션ID 목록
  const [sctResponses, setSctResponses] = useState({});
  const [sctSummaries, setSctSummaries] = useState({});
  const [loadingSummary, setLoadingSummary] = useState({});
  const [dsiResponses, setDsiResponses] = useState({});
  const [dsiRec, setDsiRec] = useState("");
  const [loadingRec, setLoadingRec] = useState(false);
  const [phq9Responses, setPhq9Responses] = useState({});
  const [gad7Responses, setGad7Responses] = useState({});
  const [dass21Responses, setDass21Responses] = useState({});
  const [big5Responses, setBig5Responses] = useState({});
  const [burnoutResponses, setBurnoutResponses] = useState({});
  const [lostResponses, setLostResponses] = useState({});
  const [aiAnalysis, setAiAnalysis] = useState({});
  const [aiLoading, setAiLoading] = useState({});
  const [aiError, setAiError] = useState({});
  // 무료 플랜 AI 분석 사용 횟수 (localStorage 연동)
  const [aiUsageCount, setAiUsageCount] = useState(0);
  const FREE_AI_LIMIT = 5;
  const [saveStatus, setSaveStatus] = useState("");
  const [sessionId, setSessionId] = useState(() => genId("session"));
  const [submitted, setSubmitted] = useState([]);
  const [pendingCounselors, setPendingCounselors] = useState([]);
  const [approvedCounselors, setApprovedCounselors] = useState([]);
  const [quotaEditingPhone, setQuotaEditingPhone] = useState(null); // 쿼터 수정 중인 상담사 전화번호
  const [quotaEditingValue, setQuotaEditingValue] = useState(''); // 쿼터 수정 값
  // API 설정 관리 state
  const [apiSettings, setApiSettings] = useState([]);
  const [apiSettingForm, setApiSettingForm] = useState({ key_name: 'ANTHROPIC_API_KEY', key_value: '', description: 'Claude AI 심리분석용 API 키' });
  const [apiSettingMsg, setApiSettingMsg] = useState({ type: '', text: '' });
  const [apiSettingLoading, setApiSettingLoading] = useState(false);
  const [apiTestLoading, setApiTestLoading] = useState(false);
  const [apiTestResult, setApiTestResult] = useState({ type: '', text: '' });
  const [showApiKeyInput, setShowApiKeyInput] = useState(false);
  
  // 성경적 상담 참고자료 state
  const BIBLICAL_CATEGORIES = [
    { value: 'general',          label: '🌐 전체 공통 (모든 검사 적용)' },
    { value: 'sct_mother',       label: '👩 SCT - 어머니 관계' },
    { value: 'sct_father',       label: '👨 SCT - 아버지 관계' },
    { value: 'sct_family',       label: '🏠 SCT - 가족 관계' },
    { value: 'sct_relationship', label: '💑 SCT - 이성 관계' },
    { value: 'sct_friend',       label: '👥 SCT - 친구/대인관계' },
    { value: 'sct_authority',    label: '👔 SCT - 권위자 관계' },
    { value: 'sct_fear',         label: '😨 SCT - 두려움' },
    { value: 'sct_guilt',        label: '😔 SCT - 죄책감' },
    { value: 'sct_ability',      label: '💪 SCT - 능력/자아' },
    { value: 'sct_future',       label: '🔮 SCT - 미래/희망' },
    { value: 'sct_goal',         label: '🎯 SCT - 목표/비전' },
    { value: 'dsi',              label: '🔍 DSI - 자아분화' },
    { value: 'phq9',             label: '😔 PHQ-9 - 우울' },
    { value: 'gad7',             label: '😰 GAD-7 - 불안' },
    { value: 'dass21',           label: '📊 DASS-21' },
    { value: 'big5',             label: '🌟 Big5 - 성격' },
    { value: 'burnout',          label: '🔥 K-MBI+ - 번아웃' },
    { value: 'lost',             label: '🧭 LOST - 행동 운영체계' },
  ];
  const [biblicalRefs, setBiblicalRefs] = useState([]);
  const [biblicalForm, setBiblicalForm] = useState({ id: null, title: '', category: 'general', content: '', sort_order: 0 });
  const [biblicalMsg, setBiblicalMsg] = useState({ type: '', text: '' });
  const [biblicalLoading, setBiblicalLoading] = useState(false);
  const [showBiblicalForm, setShowBiblicalForm] = useState(false);
  const [biblicalFilter, setBiblicalFilter] = useState('all');
  
  // AI 상담 채팅 state
  const [chatOpen, setChatOpen] = useState(false);
  const [chatMessages, setChatMessages] = useState([]); // [{role, content, id}]
  const [chatInput, setChatInput] = useState('');
  const [chatStreaming, setChatStreaming] = useState(false);
  const [chatError, setChatError] = useState('');
  
  const [formMsg, setFormMsg] = useState({ type: "", text: "" });
  const [linkInput, setLinkInput] = useState("");
  // 구독 정보 state
  const [subscription, setSubscription] = useState(null);

  // ✅ 로그인 상태 저장
  function saveLoginState(loginData) {
    storage.set("current_login", JSON.stringify(loginData));
  }

  // ✅ 로그인 상태 복원
  async function restoreLoginState() {
    const loginData = storage.get("current_login");
    if (!loginData) return false;
    
    try {
      const data = JSON.parse(loginData.value);
      
      if (data.type === "admin" || data.type === "master") {
        setIsAdmin(true);
        if (data.type === "master") {
          setIsMaster(true);
          setMasterInfo({ phone: data.phone, name: data.name });
          try { await loadMasterData(); } catch(e) { /* API 오류여도 화면 진입 */ }
          setView("masterDashboard");
        } else {
          setView("admin");
          loadAllSubmitted();
          try {
            const pendingResult = await api.getPendingCounselors();
            if (pendingResult.success) setPendingCounselors(pendingResult.data);
          } catch (err) {}
          try {
            const approvedResult = await api.getApprovedCounselors();
            if (approvedResult.success) setApprovedCounselors(approvedResult.data);
          } catch (err) {}
          await loadApiSettings();
        }
        return true;
      } else if (data.type === "orgAdmin" || data.type === "org_admin") {
        setIsOrgAdmin(true);
        setOrgAdminInfo({
          phone: data.phone,
          name: data.name,
          org_id: data.org_id,
          org_name: data.org_name
        });
        setView("orgAdminDashboard");
        
        // 조직 상담사 목록 로드
        try { await loadOrgCounselors(data.org_id); } catch(e) {}
        
        return true;
      } else if (data.type === "counselor") {
        setIsCounselor(true);
        setCounselorPhone(data.phone);
        
        // D1에서 구독 정보 가져오기
        try {
          const result = await api.getSubscription(data.phone);
          if (result.success) {
            setSubscription(result.data);
          } else {
          }
        } catch (err) {
        }
        
        // AI 분석 사용 횟수 복원 (무료 플랜 제한용)
        const savedAiCount = parseInt(localStorage.getItem("ai_usage_" + data.phone) || "0", 10);
        setAiUsageCount(savedAiCount);
        
        const lr = storage.get("counselor_links_" + data.phone);
        const links = lr ? JSON.parse(lr.value) : [];
        setGeneratedLinks(links);
        loadAllSubmitted();
        setView("counselorDashboard");
        return true;
      }
    } catch (error) {
      // JSON 파싱 오류만 current_login 제거 (API 일시 오류는 보존)
      if (error instanceof SyntaxError) {
        storage.remove("current_login");
      }
    }
    return false;
  }

  // ✅ 로그아웃 시 상태 제거
  function clearLoginState() {
    storage.remove("current_login");
  }

  function genId(prefix) {
    return prefix + "_" + Date.now() + "_" + Math.random().toString(36).slice(2, 9);
  }

  const counselingKw = [
    "상담심리", "상담학", "심리상담", "임상심리", "상담복지", "상담교육", "상담치료", "심리치료", "정신건강", "심리학",
    "청소년상담", "가족상담", "아동상담", "부부상담", "집단상담", "진로상담", "다문화상담", "중독상담", "재활상담",
    "기독교상담", "목회상담", "코칭상담", "긍정심리", "치유상담", "사회복지", "특수교육", "아동학", "아동복지",
    "교육심리", "청소년학", "교육상담", "정신보건", "미술치료", "음악치료", "놀이치료", "모래놀이", "심리재활",
    "정신건강사회복지", "중독재활", "상담코칭", "심리코칭",
  ];
  
  function checkEdu(edu) {
    if (!edu) return { ok: false, kws: [] };
    const kws = counselingKw.filter(k => edu.toLowerCase().includes(k));
    return { ok: kws.length > 0, kws };
  }

  const sctCategories = {
    "① 어머니에 대한 태도": [13, 26, 39, 49], "② 아버지에 대한 태도": [2, 19, 29, 50],
    "③ 가족에 대한 태도": [12, 24, 35, 48], "④ 여성에 대한 태도": [9, 25],
    "⑤ 남성에 대한 태도": [8, 20, 36], "⑥ 이성에 대한 태도": [10, 23],
    "⑦ 친구나 친지에 대한 태도": [6, 22, 32, 44], "⑧ 권위자에 대한 태도": [3, 31],
    "⑨ 두려움에 대한 태도": [5, 21, 40, 43], "⑩ 죄책감에 대한 태도": [14, 17, 27, 46],
    "⑪ 자신의 능력에 대한 태도": [1, 15, 34, 38], "⑫ 과거에 대한 태도": [7, 33, 45],
    "⑬ 미래에 대한 태도": [4, 11, 16, 18, 28], "⑭ 목표에 대한 태도": [30, 41, 42],
  };
  
  const sctQ = {
    1: "나에게 이상한 일이 생겼을 때", 2: "내 생각에 가끔 아버지는", 3: "우리 윗사람들은",
    4: "나의 장래는", 5: "어리석게도 내가 두려워하는 것은", 6: "내 생각에 참다운 친구는",
    7: "내가 어렸을 때는", 8: "남자에 대해서 무엇보다 좋지 않게 생각하는 것은", 9: "내가 바라는 여인상은",
    10: "남녀가 같이 있는 것을 볼 때", 11: "내가 늘 원하기는", 12: "다른 가정과 비교해서 우리 집안은",
    13: "나의 어머니는", 14: "무슨 일을 해서라도 잊고 싶은 것은", 15: "내가 믿고 있는 내 능력은",
    16: "내가 정말 행복할 수 있으려면", 17: "어렸을 때 잘못했다고 느끼는 것은", 18: "내가 보는 나의 앞날은",
    19: "대개 아버지들이란", 20: "내 생각에 남자들이란", 21: "다른 친구들이 모르는 나만의 두려움은",
    22: "내가 싫어하는 사람은", 23: "결혼 생활에 대한 나의 생각은", 24: "우리 가족이 나에 대해서",
    25: "내 생각에 여자들이란", 26: "어머니와 나는", 27: "내가 저지른 가장 큰 잘못은",
    28: "언젠가 나는", 29: "내가 바라기에 아버지는", 30: "나의 야망은",
    31: "윗사람이 오는 것을 보면 나는", 32: "내가 제일 좋아하는 사람은", 33: "내가 다시 젊어진다면",
    34: "나의 가장 큰 결점은", 35: "내가 아는 대부분의 집안은", 36: "완전한 남성상(男性像)은",
    37: "내가 성관계를 했다면", 38: "행운이 나를 외면했을 때", 39: "대개 어머니들이란",
    40: "내가 잊고 싶은 두려움은", 41: "내가 평생 가장 하고 싶은 일은", 42: "내가 늙으면",
    43: "때때로 두려운 생각이 나를 휩쌀 때", 44: "내가 없을 때 친구들은", 45: "생생한 어린 시절의 기억은",
    46: "무엇보다도 좋지 않게 여기는 것은", 47: "나의 성생활은", 48: "내가 어렸을 때 우리 가족은",
    49: "나는 어머니를 좋아했지만", 50: "아버지와 나는",
  };

  const dsiQ = [
    { num: 1, content: "중요한 결정을 내릴 때 마음 내키는 대로 결정하는 일이 많다.", rev: true, area: "인지적 기능" },
    { num: 2, content: "말부터 해 놓고 나중에 후회하는 일이 많다.", rev: true, area: "인지적 기능" },
    { num: 3, content: "비교적 내 감정을 잘 통제해 나가는 편이다.", rev: false, area: "인지적 기능" },
    { num: 4, content: "다른 사람의 기대에 맞추려고 노력한다.", rev: true, area: "인지적 기능" },
    { num: 5, content: "가족의 의견에 쉽게 동요된다.", rev: true, area: "인지적 기능" },
    { num: 6, content: "스트레스 받을 때 충동적으로 행동한다.", rev: true, area: "인지적 기능" },
    { num: 7, content: "문제를 논리적으로 분석해 해결한다.", rev: false, area: "인지적 기능" },
    { num: 8, content: "자신의 가치관을 일관되게 유지한다.", rev: false, area: "자아통합" },
    { num: 9, content: "중요한 결정은 스스로 내린다.", rev: false, area: "자아통합" },
    { num: 10, content: "타인의 압력에도 원칙을 지킨다.", rev: false, area: "자아통합" },
    { num: 11, content: "가족 문제에 과도하게 개입한다.", rev: true, area: "자아통합" },
    { num: 12, content: "가족 기대 때문에 자신의 길을 바꾼다.", rev: true, area: "자아통합" },
    { num: 13, content: "자기 목표를 명확히 추구한다.", rev: false, area: "자아통합" },
    { num: 14, content: "어릴 적 부모의 갈등이 나에게 영향을 줬다.", rev: true, area: "가족투사" },
    { num: 15, content: "부모 중 한 명에게 더 의존했다.", rev: true, area: "가족투사" },
    { num: 16, content: "형제 중 특정 한 명이 문제 자녀였다.", rev: true, area: "가족투사" },
    { num: 17, content: "가족 문제가 나의 선택에 영향을 줬다.", rev: true, area: "가족투사" },
    { num: 18, content: "가족의 기대를 저버린 적이 거의 없다.", rev: true, area: "가족투사" },
    { num: 19, content: "부모의 불화가 내 삶에 남아있다.", rev: true, area: "가족투사" },
    { num: 20, content: "가족과 적절한 거리를 유지한다.", rev: false, area: "정서적 단절" },
    { num: 21, content: "가족 갈등 시 멀리 도망간다.", rev: true, area: "정서적 단절" },
    { num: 22, content: "가족과 연락을 최소화한다.", rev: true, area: "정서적 단절" },
    { num: 23, content: "가족 모임에 불편함을 느낀다.", rev: true, area: "정서적 단절" },
    { num: 24, content: "가족 문제에 무관심하다.", rev: true, area: "정서적 단절" },
    { num: 25, content: "가족 전체가 스트레스 시 퇴행한다.", rev: true, area: "가족퇴행" },
    { num: 26, content: "가족 모임에서 합리적으로 행동한다.", rev: false, area: "가족퇴행" },
    { num: 27, content: "가족이 나의 독립을 존중한다.", rev: false, area: "가족퇴행" },
    { num: 28, content: "가족 갈등을 논리적으로 해결한다.", rev: false, area: "가족퇴행" },
    { num: 29, content: "가족 내 역할이 명확하다.", rev: false, area: "가족퇴행" },
    { num: 30, content: "가족이 서로 자율성을 가진다.", rev: false, area: "가족퇴행" },
    { num: 31, content: "가족 스트레스 시 침착하다.", rev: false, area: "가족퇴행" },
    { num: 32, content: "가족 관계가 안정적이다.", rev: false, area: "가족퇴행" },
    { num: 33, content: "우리 가족은 서로 과잉보호적이다.", rev: true, area: "가족퇴행" },
    { num: 34, content: "가족이 감정적으로 의지한다.", rev: true, area: "가족퇴행" },
    { num: 35, content: "가족 모임이 피곤하다.", rev: true, area: "가족퇴행" },
    { num: 36, content: "우리 가족들은 서로에 대해 별 관심이 없었다.", rev: true, area: "가족퇴행" },
  ];

  // PHQ-9: 우울증 선별도구 (Patient Health Questionnaire-9)
  // 공개 도메인 - 출처: Pfizer Inc. (무료 사용 가능)
  const phq9Q = [
    { num: 1, content: "기분이 가라앉거나, 우울하거나, 희망이 없다고 느꼈다" },
    { num: 2, content: "평소 하던 일에 대한 흥미가 없어지거나 즐거움을 느끼지 못했다" },
    { num: 3, content: "잠들기가 어렵거나 자주 깼다 / 혹은 너무 많이 잤다" },
    { num: 4, content: "피곤하다고 느끼거나 기력이 거의 없었다" },
    { num: 5, content: "식욕이 줄었다 / 혹은 평소보다 많이 먹었다" },
    { num: 6, content: "내 자신이 실패자라고 느꼈다 / 혹은 자신과 가족을 실망시켰다고 느꼈다" },
    { num: 7, content: "신문을 읽거나 TV를 보는 것과 같은 일에 집중하기가 어려웠다" },
    { num: 8, content: "다른 사람들이 알아챌 정도로 평소보다 말과 행동이 느려졌다 / 혹은 너무 안절부절 못해서 가만히 앉아 있을 수 없었다" },
    { num: 9, content: "차라리 죽는 것이 낫겠다고 생각했다 / 혹은 자해할 생각을 했다" },
  ];

  // GAD-7: 범불안장애 선별도구 (Generalized Anxiety Disorder-7)
  // 공개 도메인 - 출처: Pfizer Inc. (무료 사용 가능)
  const gad7Q = [
    { num: 1, content: "초조하거나 불안하거나 조마조마하게 느낀다" },
    { num: 2, content: "걱정하는 것을 멈추거나 조절할 수가 없다" },
    { num: 3, content: "여러 가지 것들에 대해 걱정을 너무 많이 한다" },
    { num: 4, content: "편하게 있기가 어렵다" },
    { num: 5, content: "너무 안절부절 못해서 가만히 있기 힘들다" },
    { num: 6, content: "쉽게 짜증이 나거나 쉽게 성을 낸다" },
    { num: 7, content: "마치 끔찍한 일이 생길 것처럼 두렵게 느낀다" },
  ];

  // DASS-21: 우울/불안/스트레스 척도 (Depression Anxiety Stress Scale-21)
  // 공개 도메인 - 출처: Lovibond & Lovibond (무료 사용 가능)
  const dass21Q = [
    { num: 1, content: "나는 안정을 취하기 힘들었다", scale: "스트레스" },
    { num: 2, content: "입이 바싹 마르는 느낌이 들었다", scale: "불안" },
    { num: 3, content: "어떤 것에도 긍정적인 감정을 느낄 수가 없었다", scale: "우울" },
    { num: 4, content: "호흡 곤란을 경험했다 (예: 과도하게 빠른 호흡, 힘든 일을 하지 않았는데도 숨이 참)", scale: "불안" },
    { num: 5, content: "무언가를 해야겠다는 의욕이 들지 않았다", scale: "우울" },
    { num: 6, content: "사소한 일에도 과민반응을 보이는 경향이 있었다", scale: "스트레스" },
    { num: 7, content: "손이 떨렸다 (예: 글을 쓸 때)", scale: "불안" },
    { num: 8, content: "신경을 많이 쓰고 있다는 느낌이 들었다", scale: "스트레스" },
    { num: 9, content: "나쁜 일이 일어날까봐 걱정스러웠다", scale: "불안" },
    { num: 10, content: "삶에 대해 열정을 느낄 수 없었다", scale: "우울" },
    { num: 11, content: "쉽게 동요하게 되었다", scale: "스트레스" },
    { num: 12, content: "긴장을 풀기 어려웠다", scale: "스트레스" },
    { num: 13, content: "우울하고 슬펐다", scale: "우울" },
    { num: 14, content: "내가 좋아하는 것을 방해받는 것에 대해 참을 수 없었다", scale: "스트레스" },
    { num: 15, content: "공황상태에 빠질 것만 같았다", scale: "불안" },
    { num: 16, content: "어떤 것에도 기대할 것이 없었다", scale: "우울" },
    { num: 17, content: "나 자신이 가치가 없는 사람으로 느껴졌다", scale: "우울" },
    { num: 18, content: "사소한 일에도 쉽게 언짢아졌다", scale: "스트레스" },
    { num: 19, content: "심장이 이유 없이 두근거렸다 (예: 심장 박동수가 증가하거나 빠르게 뛰는 느낌)", scale: "불안" },
    { num: 20, content: "이유 없이 무서웠다", scale: "불안" },
    { num: 21, content: "삶이 무의미하게 느껴졌다", scale: "우울" },
  ];

  // Big5 성격검사 (50문항 버전 - IPIP 공개 버전 기반)
  // 공개 도메인 - 출처: International Personality Item Pool (무료 사용 가능)
  const big5Q = [
    // 외향성 (Extraversion) - 10문항
    { num: 1, content: "나는 파티의 주인공이다", factor: "외향성", rev: false },
    { num: 2, content: "나는 다른 사람들과 대화하는 것을 좋아하지 않는다", factor: "외향성", rev: true },
    { num: 3, content: "나는 편안하게 사람들과 어울린다", factor: "외향성", rev: false },
    { num: 4, content: "나는 배경에 머물러 있다", factor: "외향성", rev: true },
    { num: 5, content: "나는 대화를 시작한다", factor: "외향성", rev: false },
    { num: 6, content: "나는 많은 사람들에게 말을 거의 하지 않는다", factor: "외향성", rev: true },
    { num: 7, content: "나는 많은 사람들과 대화하는 것이 좋다", factor: "외향성", rev: false },
    { num: 8, content: "나는 대화를 시작하는 것을 어려워한다", factor: "외향성", rev: true },
    { num: 9, content: "나는 관심의 중심이 되는 것을 좋아한다", factor: "외향성", rev: false },
    { num: 10, content: "나는 낯선 사람과 말하고 싶지 않다", factor: "외향성", rev: true },
    
    // 친화성 (Agreeableness) - 10문항
    { num: 11, content: "나는 다른 사람들의 감정에 관심이 있다", factor: "친화성", rev: false },
    { num: 12, content: "나는 다른 사람들의 감정에 관심이 없다", factor: "친화성", rev: true },
    { num: 13, content: "나는 다른 사람들을 편안하게 해준다", factor: "친화성", rev: false },
    { num: 14, content: "나는 다른 사람들을 모욕한다", factor: "친화성", rev: true },
    { num: 15, content: "나는 사람들의 마음을 부드럽게 한다", factor: "친화성", rev: false },
    { num: 16, content: "나는 다른 사람들에게 별 관심이 없다", factor: "친화성", rev: true },
    { num: 17, content: "나는 다른 사람들에게 시간을 내준다", factor: "친화성", rev: false },
    { num: 18, content: "나는 다른 사람들의 문제에 신경 쓰지 않는다", factor: "친화성", rev: true },
    { num: 19, content: "나는 다른 사람들을 느끼고 이해한다", factor: "친화성", rev: false },
    { num: 20, content: "나는 다른 사람들에게 차갑고 무관심하다", factor: "친화성", rev: true },
    
    // 성실성 (Conscientiousness) - 10문항
    { num: 21, content: "나는 항상 준비되어 있다", factor: "성실성", rev: false },
    { num: 22, content: "나는 내 물건을 어질러 놓는다", factor: "성실성", rev: true },
    { num: 23, content: "나는 세부사항에 주의를 기울인다", factor: "성실성", rev: false },
    { num: 24, content: "나는 종종 물건을 어디에 두었는지 잊어버린다", factor: "성실성", rev: true },
    { num: 25, content: "나는 일을 제때 끝낸다", factor: "성실성", rev: false },
    { num: 26, content: "나는 일을 망치곤 한다", factor: "성실성", rev: true },
    { num: 27, content: "나는 일에 진지하게 임한다", factor: "성실성", rev: false },
    { num: 28, content: "나는 내 의무를 회피한다", factor: "성실성", rev: true },
    { num: 29, content: "나는 계획을 따른다", factor: "성실성", rev: false },
    { num: 30, content: "나는 즉시 일을 시작하지 않는다", factor: "성실성", rev: true },
    
    // 신경성 (Neuroticism) - 10문항
    { num: 31, content: "나는 쉽게 스트레스를 받는다", factor: "신경성", rev: false },
    { num: 32, content: "나는 쉽게 진정한다", factor: "신경성", rev: true },
    { num: 33, content: "나는 변화에 쉽게 동요한다", factor: "신경성", rev: false },
    { num: 34, content: "나는 거의 걱정하지 않는다", factor: "신경성", rev: true },
    { num: 35, content: "나는 쉽게 짜증이 난다", factor: "신경성", rev: false },
    { num: 36, content: "나는 대부분의 경우 편안하다", factor: "신경성", rev: true },
    { num: 37, content: "나는 긴장감을 자주 느낀다", factor: "신경성", rev: false },
    { num: 38, content: "나는 두려움을 거의 느끼지 않는다", factor: "신경성", rev: true },
    { num: 39, content: "나는 작은 일에도 걱정한다", factor: "신경성", rev: false },
    { num: 40, content: "나는 항상 여유롭다", factor: "신경성", rev: true },
    
    // 개방성 (Openness) - 10문항
    { num: 41, content: "나는 풍부한 어휘력을 가지고 있다", factor: "개방성", rev: false },
    { num: 42, content: "나는 추상적인 아이디어를 이해하기 어렵다", factor: "개방성", rev: true },
    { num: 43, content: "나는 생생한 상상력을 가지고 있다", factor: "개방성", rev: false },
    { num: 44, content: "나는 새로운 것에 관심이 없다", factor: "개방성", rev: true },
    { num: 45, content: "나는 많은 것에 대해 생각한다", factor: "개방성", rev: false },
    { num: 46, content: "나는 예술에 관심이 없다", factor: "개방성", rev: true },
    { num: 47, content: "나는 철학적 논의를 즐긴다", factor: "개방성", rev: false },
    { num: 48, content: "나는 복잡한 것을 좋아하지 않는다", factor: "개방성", rev: true },
    { num: 49, content: "나는 빠른 이해력을 가지고 있다", factor: "개방성", rev: false },
    { num: 50, content: "나는 창의적인 해결책을 찾기 어렵다", factor: "개방성", rev: true },
  ];

  // 번아웃 검사 (K-MBI+) 50문항
  const burnoutQ = [
    // I. 정서적 소진 (12문항)
    { num: 1, content: "업무로 인해 감정적으로 완전히 소진된 느낌이 든다", domain: "EE", rev: false },
    { num: 2, content: "퇴근 후에도 업무 생각으로 머리가 꽉 차 있다", domain: "EE", rev: false },
    { num: 3, content: "아침에 출근할 생각만 해도 기력이 없고 피곤하다", domain: "EE", rev: false },
    { num: 4, content: "하루 종일 일하고 나면 극도로 지쳐 아무것도 하기 싫다", domain: "EE", rev: false },
    { num: 5, content: "사람들을 응대하거나 돕는 것이 감정적으로 너무 힘들다", domain: "EE", rev: false },
    { num: 6, content: "직장 생활이 나를 내부에서 태워 없애는 느낌이 든다", domain: "EE", rev: false },
    { num: 7, content: "감정을 쏟아내다가 이제 더 이상 줄 것이 없다는 느낌이 든다", domain: "EE", rev: false },
    { num: 8, content: "업무나 동료에 대한 정서적 여유가 전혀 없다", domain: "EE", rev: false },
    { num: 9, content: "일과 중 작은 일에도 감정적으로 폭발할 것 같다", domain: "EE", rev: false },
    { num: 10, content: "직장 일이 나의 개인 삶 전체를 잠식하는 것 같다", domain: "EE", rev: false },
    { num: 11, content: "이직이나 퇴직을 진지하게 고민하고 있다", domain: "EE", rev: false },
    { num: 12, content: "업무를 마친 후에도 회복이 되지 않고 지속적으로 지쳐 있다", domain: "EE", rev: false },
    
    // II. 비인격화 (8문항)
    { num: 13, content: "고객이나 동료가 마치 무감각한 대상처럼 느껴진다", domain: "DP", rev: false },
    { num: 14, content: "요즘 들어 나 자신이 점점 냉담하고 무감각해졌다", domain: "DP", rev: false },
    { num: 15, content: "업무 관련 사람들의 문제에 무관심해지거나 귀찮아진다", domain: "DP", rev: false },
    { num: 16, content: "사람을 대하는 일이 내 에너지를 심하게 소모시킨다", domain: "DP", rev: false },
    { num: 17, content: "회사나 조직의 방향성·목표가 무의미하게 느껴진다", domain: "DP", rev: false },
    { num: 18, content: "이 직장이 나에게 아무 의미도 없다는 생각이 든다", domain: "DP", rev: false },
    { num: 19, content: "사람들의 감정적 문제에 실제로 관심이 없어졌다", domain: "DP", rev: false },
    { num: 20, content: "일하면서 점점 공감 능력을 잃어가는 것 같다", domain: "DP", rev: false },
    
    // III. 성취감 저하 (10문항, 역채점)
    { num: 21, content: "이 일을 통해 다른 사람의 삶에 긍정적인 영향을 준다고 느낀다", domain: "PA", rev: true },
    { num: 22, content: "업무에서 가치 있는 일을 해내고 있다는 보람을 느낀다", domain: "PA", rev: true },
    { num: 23, content: "어려운 문제를 스스로 해결했을 때 뿌듯함을 느낀다", domain: "PA", rev: true },
    { num: 24, content: "내 업무가 조직에 의미 있게 기여한다고 생각한다", domain: "PA", rev: true },
    { num: 25, content: "직장에서 나 자신이 성장하고 있다는 느낌이 든다", domain: "PA", rev: true },
    { num: 26, content: "업무 중 즐거움이나 몰입을 경험한다", domain: "PA", rev: true },
    { num: 27, content: "내 직업 선택이 옳았다는 확신이 있다", domain: "PA", rev: true },
    { num: 28, content: "사람들을 효과적으로 도왔다는 만족감을 느낀다", domain: "PA", rev: true },
    { num: 29, content: "이 일을 통해 내가 사회에 기여하고 있다는 자긍심이 있다", domain: "PA", rev: true },
    { num: 30, content: "현재 내 역량이 잘 발휘되고 있다고 느낀다", domain: "PA", rev: true },
    
    // IV. 업무 과부하 (10문항)
    { num: 31, content: "업무량이 나 혼자 감당하기에 너무 많다", domain: "WO", rev: false },
    { num: 32, content: "업무 마감이나 요구사항이 불합리하게 느껴진다", domain: "WO", rev: false },
    { num: 33, content: "업무 방식이나 우선순위에 대한 결정권이 없다고 느낀다", domain: "WO", rev: false },
    { num: 34, content: "야근이나 초과 근무가 일상화되어 있다", domain: "WO", rev: false },
    { num: 35, content: "모순되거나 충돌하는 업무 지시를 동시에 받는다", domain: "WO", rev: false },
    { num: 36, content: "업무 성과에 비해 인정·보상이 부족하다고 느낀다", domain: "WO", rev: false },
    { num: 37, content: "직장 내 공정성이 부족하다고 느낀다", domain: "WO", rev: false },
    { num: 38, content: "개인 삶과 업무 간의 균형을 맞추기 어렵다", domain: "WO", rev: false },
    { num: 39, content: "업무 중 지속적인 방해나 중단으로 집중이 불가능하다", domain: "WO", rev: false },
    { num: 40, content: "조직의 가치관이 내 개인 가치관과 심하게 충돌한다", domain: "WO", rev: false },
    
    // V. 신체·인지 (10문항)
    { num: 41, content: "충분히 잤는데도 개운하지 않고 지속적으로 피로하다", domain: "PC", rev: false },
    { num: 42, content: "두통, 근육 긴장, 어깨·목 통증이 자주 생긴다", domain: "PC", rev: false },
    { num: 43, content: "업무 중 기억력이나 집중력이 현저히 저하된 것 같다", domain: "PC", rev: false },
    { num: 44, content: "소화불량, 위경련, 식욕 변화 등 소화 문제가 있다", domain: "PC", rev: false },
    { num: 45, content: "잠들기 어렵거나 중간에 자꾸 깬다", domain: "PC", rev: false },
    { num: 46, content: "면역력이 떨어져 자주 감기나 잔병에 걸린다", domain: "PC", rev: false },
    { num: 47, content: "카페인·알코올·약물에 점점 더 의존하게 된다", domain: "PC", rev: false },
    { num: 48, content: "업무 외 취미·운동 등 즐기던 활동을 완전히 포기했다", domain: "PC", rev: false },
    { num: 49, content: "간단한 결정도 내리기 어렵고 판단력이 흐려졌다", domain: "PC", rev: false },
    { num: 50, content: "심장 두근거림, 식은땀, 만성 긴장감 등 신체 증상이 있다", domain: "PC", rev: false }
  ];

  // ====================================================
  // LOST: 행동 운영체계 검사 (Life Operating Style Test)
  // 6축 60문항, 5점 리커트 척도 | 이론: Big Five + HEXACO + TCI + 한국 문화 요소
  // ====================================================
  const lostQ = [
    // ── 축 1. 에너지 방향 (Energy Direction) ── E=외향 / I=내향, rev=내향 문항
    { num:1,  content:"낯선 사람들과 쉽게 어울리며 에너지를 얻는다",           axis:"E", dir:"E", rev:false },
    { num:2,  content:"혼자 조용히 지내면 오히려 마음이 편안하다",              axis:"E", dir:"I", rev:true  },
    { num:3,  content:"파티나 모임에 가면 활기가 생긴다",                       axis:"E", dir:"E", rev:false },
    { num:4,  content:"큰 모임보다 친한 친구 몇 명과 시간 보내는 것을 선호한다",axis:"E", dir:"I", rev:true  },
    { num:5,  content:"새로운 사람과 대화하면 금방 친해지는 편이다",            axis:"E", dir:"E", rev:false },
    { num:6,  content:"사람들 앞에서 이야기할 때 긴장한다",                     axis:"E", dir:"I", rev:true  },
    { num:7,  content:"친목 모임에서 주도적으로 행동하는 편이다",               axis:"E", dir:"E", rev:false },
    { num:8,  content:"오랜만에 만난 친한 친구보다 혼자 쉬는 것이 더 좋다",    axis:"E", dir:"I", rev:true  },
    { num:9,  content:"낯선 환경에서 처음 만난 사람들과 빨리 친해진다",         axis:"E", dir:"E", rev:false },
    { num:10, content:"혼자만의 시간이 부족하면 금방 지친다",                   axis:"E", dir:"I", rev:true  },

    // ── 축 2. 의사결정 방식 (Decision Style) ── T=논리 / F=감정
    { num:11, content:"결정을 내릴 때 감정보다 사실과 논리를 우선한다",         axis:"D", dir:"T", rev:false },
    { num:12, content:"데이터와 사실을 기반으로 결정을 내리는 편이다",           axis:"D", dir:"T", rev:false },
    { num:13, content:"중요한 결정을 할 때 주변 사람들의 감정도 함께 고려한다", axis:"D", dir:"F", rev:true  },
    { num:14, content:"감정이나 분위기에 따라 내 판단이 크게 달라지는 편이다",  axis:"D", dir:"F", rev:true  },
    { num:15, content:"문제를 분석할 때 감정보다 이성이 앞선다",                axis:"D", dir:"T", rev:false },
    { num:16, content:"의사결정에서 타인의 기분과 조화를 이루려 한다",           axis:"D", dir:"F", rev:true  },
    { num:17, content:"논리적 설명이 없으면 중요한 결정을 믿기 어렵다",          axis:"D", dir:"T", rev:false },
    { num:18, content:"다른 사람이 우울해 보이면 내 기분도 영향을 받는다",      axis:"D", dir:"F", rev:true  },
    { num:19, content:"객관적인 데이터가 없으면 결정을 내리기 어렵다",           axis:"D", dir:"T", rev:false },
    { num:20, content:"나를 화나게 한 사람을 쉽게 용서해 주지 못한다",          axis:"D", dir:"F", rev:false },

    // ── 축 3. 행동 속도 (Action Speed) ── P=빠름 / J=신중
    { num:21, content:"급한 일이 생기면 즉시 행동하는 편이다",                  axis:"S", dir:"P", rev:false },
    { num:22, content:"충분히 계획하지 않으면 불안해서 실행하기 어렵다",         axis:"S", dir:"J", rev:true  },
    { num:23, content:"일을 할 때 신속함보다 꼼꼼함이 더 중요하다고 생각한다",  axis:"S", dir:"J", rev:true  },
    { num:24, content:"일을 처리할 때 즉흥적으로 진행하는 것을 좋아한다",        axis:"S", dir:"P", rev:false },
    { num:25, content:"계획대로 움직이는 것보다 빠르게 결정을 바꾸는 편이다",   axis:"S", dir:"P", rev:false },
    { num:26, content:"시간이 허락할 때는 깊이 고민한 뒤 행동한다",             axis:"S", dir:"J", rev:true  },
    { num:27, content:"마감이 임박하면 효율보다 속도를 중시한다",                axis:"S", dir:"P", rev:false },
    { num:28, content:"충동적으로 결정하면 나중에 후회할 때가 많다",             axis:"S", dir:"J", rev:true  },
    { num:29, content:"빠른 실행은 중요하지만 실수가 생길까 걱정된다",           axis:"S", dir:"J", rev:true  },
    { num:30, content:"상황에 따라 행동 방식을 즉시 바꾸는 편이다",             axis:"S", dir:"P", rev:false },

    // ── 축 4. 안정성 (Stability) ── C=변화 / N=안정
    { num:31, content:"변화는 나를 설레게 한다",                                axis:"N", dir:"C", rev:false },
    { num:32, content:"익숙한 환경이 안전하다고 느낀다",                         axis:"N", dir:"N", rev:true  },
    { num:33, content:"새로운 도전이 주는 자극을 즐긴다",                        axis:"N", dir:"C", rev:false },
    { num:34, content:"안정적인 일과를 벗어나면 불안감이 크다",                  axis:"N", dir:"N", rev:true  },
    { num:35, content:"새로운 프로젝트보다 익숙한 일에 집중하는 편이다",         axis:"N", dir:"N", rev:true  },
    { num:36, content:"변화를 맞이할 때 흥미를 느낀다",                          axis:"N", dir:"C", rev:false },
    { num:37, content:"예측 가능한 환경에서 일하는 것이 편안하다",               axis:"N", dir:"N", rev:true  },
    { num:38, content:"일상의 틀에서 벗어나 새로운 방식을 시도한다",             axis:"N", dir:"C", rev:false },
    { num:39, content:"새로운 아이디어가 떠오르면 신나지만 걱정도 된다",         axis:"N", dir:"C", rev:false },
    { num:40, content:"일상의 변화가 크면 긴장한다",                             axis:"N", dir:"N", rev:true  },

    // ── 축 5. 관계 민감도 (Relation Sensitivity) ── R=관계중심 / I=독립
    { num:41, content:"팀의 목표를 위해 다른 사람과 협력하는 것을 중요하게 생각한다", axis:"R", dir:"R", rev:false },
    { num:42, content:"내 생각을 고집하기보다 주변 의견에 따라 결정을 바꾸기도 한다",  axis:"R", dir:"R", rev:false },
    { num:43, content:"혼자 일하는 것보다 팀워크가 잘 맞는 일을 좋아한다",       axis:"R", dir:"R", rev:false },
    { num:44, content:"중요한 결정은 주로 나 혼자 판단으로 한다",               axis:"R", dir:"I", rev:true  },
    { num:45, content:"동료나 친구와의 조화를 위해 양보하는 경우가 많다",        axis:"R", dir:"R", rev:false },
    { num:46, content:"자신의 의견보다 팀의 목표를 우선한다",                    axis:"R", dir:"R", rev:false },
    { num:47, content:"반드시 다른 사람의 도움 없이 처리하고 싶어 하는 편이다",  axis:"R", dir:"I", rev:true  },
    { num:48, content:"친밀한 관계를 맺는 것이 나에게 큰 의미가 있다",           axis:"R", dir:"R", rev:false },
    { num:49, content:"혼자 있을 때 오히려 더 생산적이라고 느낀다",              axis:"R", dir:"I", rev:false },
    { num:50, content:"다른 사람의 기분을 금방 파악하는 편이다",                 axis:"R", dir:"R", rev:false },

    // ── 축 6. 스트레스 반응 (Stress Response) ── A=직면 / V=회피
    { num:51, content:"문제가 생기면 즉시 피하거나 회피하려고 한다",             axis:"T", dir:"V", rev:true  },
    { num:52, content:"어려운 일이 생기면 바로 대응하면서 해결책을 찾는다",      axis:"T", dir:"A", rev:false },
    { num:53, content:"스트레스를 받으면 쉬어야만 진정될 수 있다고 느낀다",      axis:"T", dir:"V", rev:true  },
    { num:54, content:"위기 상황에서 침착하게 문제를 해결하려 노력한다",         axis:"T", dir:"A", rev:false },
    { num:55, content:"갈등 상황은 피해야 한다고 생각한다",                      axis:"T", dir:"V", rev:true  },
    { num:56, content:"문제가 생기면 적극적으로 빠르게 해결하려 한다",           axis:"T", dir:"A", rev:false },
    { num:57, content:"스트레스를 받으면 상황을 회피하고 싶어진다",              axis:"T", dir:"V", rev:true  },
    { num:58, content:"곤란한 상황에서도 당면 과제에 집중하는 편이다",           axis:"T", dir:"A", rev:false },
    { num:59, content:"문제 상황에서 주변 사람에게 도움 청하는 것을 꺼린다",     axis:"T", dir:"V", rev:true  },
    { num:60, content:"긴장되는 상황에서도 먼저 해결책을 모색한다",              axis:"T", dir:"A", rev:false },
  ];

  // LOST 16유형 정의
  const LOST_TYPES = {
    "ETPR": { name:"모험가형", icon:"🚀", eng:"Energetic Explorer",
      desc:"새로운 도전과 지식을 즐기며 행동이 빠르고 독립적인 탐험가",
      traits:["도전 지향","빠른 실행력","독립적 사고","에너지 넘침","직선적 소통"],
      strength:["위기 대응력 탁월","새로운 환경 빠른 적응","자기 주도적 성과"],
      weakness:["충동적 결정 경향","협업 과정 불편함","지속성 부족"],
      work:"빠른 의사결정이 필요한 프로젝트 리더 역할에서 강점 발휘",
      love:"파트너의 독립성을 존중하고, 함께 새로운 경험을 공유할 때 관계가 깊어짐",
      stress:"스트레스 상황에서 즉각 행동하지만 감정 소화 시간이 필요",
      match:["전략가형","분석가형"], conflict:["공감가형","조율자형"] },
    "ETPC": { name:"추진자형", icon:"⚡", eng:"Driver",
      desc:"논리적이면서 에너지 넘치고 팀 목표를 빠르게 추진하는 실행가",
      traits:["논리적 추진력","팀 지향 리더십","빠른 결단","협업 촉진","목표 집중"],
      strength:["팀 동기 부여","빠른 목표 달성","소통과 실행의 균형"],
      weakness:["감정적 측면 과소평가","팀원 부담 가능","과정보다 결과 집중"],
      work:"팀 프로젝트에서 속도와 방향을 동시에 잡는 역할",
      love:"파트너와 공동 목표를 세우고 함께 달성하는 과정에서 유대감 형성",
      stress:"팀 전체 문제로 확장해 해결하려 하며 에너지 소모 주의",
      match:["연구가형","관리자형"], conflict:["관찰자형","예술가형"] },
    "ETJR": { name:"계획가형", icon:"📋", eng:"Strategic Planner",
      desc:"분석적이고 체계적이며 목표 중심으로 계획을 세워 실천하는 유형",
      traits:["체계적 계획","분석적 사고","독립 실행","논리 우선","꼼꼼함"],
      strength:["장기 전략 수립","복잡한 문제 구조화","높은 완성도"],
      weakness:["유연성 부족","협업 시 갈등 가능","완벽주의 스트레스"],
      work:"복잡한 프로젝트 기획과 체계적 실행이 필요한 환경",
      love:"신뢰와 일관성을 중시하며 안정적인 관계 선호",
      stress:"계획 외 변수에 스트레스를 받으며 직면 방식으로 해결",
      match:["모험가형","열정가형"], conflict:["창의가형","행동가형"] },
    "ETJC": { name:"관리자형", icon:"🏛️", eng:"Manager",
      desc:"외향적 리더십과 계획력을 갖추고 조직과 협업하여 성과를 내는 유형",
      traits:["조직 리더십","전략적 협업","책임감","체계적 소통","성과 지향"],
      strength:["조직 안정화","팀 성과 극대화","체계적 의사결정"],
      weakness:["통제 욕구 강함","변화 적응 느림","유연성 제한"],
      work:"조직 관리와 팀 조율이 핵심인 리더 포지션",
      love:"파트너와 명확한 역할 분담과 계획된 일상을 선호",
      stress:"위기를 조직적으로 대응하며 팀 전체를 이끌려 함",
      match:["추진자형","연구가형"], conflict:["창의가형","관찰자형"] },
    "EFPR": { name:"행동가형", icon:"🔥", eng:"Dynamic Doer",
      desc:"감성적이지만 에너지가 넘치며 즉흥적 행동으로 실행하는 추진형",
      traits:["즉흥적 에너지","감성적 결정","독립 행동","사교적","높은 열정"],
      strength:["유연한 상황 대응","사람 동기 부여","창의적 실행"],
      weakness:["감정 기복에 따른 일관성 부족","계획성 약함","충동적 결정"],
      work:"빠른 변화와 사람 중심의 환경에서 강점 발휘",
      love:"감정 표현이 풍부하고 파트너와의 즉흥적 경험을 즐김",
      stress:"감정을 직접 표출하거나 상황을 피하는 방식이 혼재",
      match:["공감가형","조율자형"], conflict:["전략가형","분석가형"] },
    "EFPC": { name:"설득가형", icon:"🌟", eng:"Persuader",
      desc:"사교적이고 설득력 있으며 에너제틱하게 팀을 이끄는 협업가",
      traits:["강한 설득력","팀 에너지 주입","감성 소통","즉흥적 협업","사교성"],
      strength:["팀 분위기 조성","사람 간 연결","빠른 신뢰 구축"],
      weakness:["논리적 근거 부족","감정 과몰입","일관성 유지 어려움"],
      work:"세일즈, 커뮤니케이션, 팀 빌딩이 중요한 환경",
      love:"파트너를 자주 칭찬하고 감정을 솔직히 나누는 관계 선호",
      stress:"문제를 사람과 함께 해결하며 감정 공유로 해소",
      match:["관찰자형","예술가형"], conflict:["분석가형","전략가형"] },
    "EFJR": { name:"열정가형", icon:"💫", eng:"Passionate Enthusiast",
      desc:"따뜻하고 열정적이며 독립적으로 업무를 추진하는 협업형 리더",
      traits:["따뜻한 카리스마","독립적 열정","공감 능력","신중한 실행","리더십"],
      strength:["공감 기반 리더십","조직 내 조정 능력","안정적 관계망"],
      weakness:["갈등 회피 경향","독립 결정 기피 상황","과도한 양보"],
      work:"모임을 주도하되 팀원 의견을 꼼꼼히 수렴하는 역할",
      love:"깊고 진실된 관계를 원하며 파트너의 성장을 응원",
      stress:"갈등 상황에서 감정 소화 후 신중하게 직면",
      match:["분석가형","전략가형"], conflict:["모험가형","행동가형"] },
    "EFJC": { name:"조율자형", icon:"🕊️", eng:"Harmonizer",
      desc:"온화하고 대화 중심이며 집단의 조화를 중시하는 소통가",
      traits:["조화 추구","공감적 소통","팀 안정화","신중한 판단","포용력"],
      strength:["갈등 중재","팀 화합 유지","감성 리더십"],
      weakness:["자기 주장 부족","결정 지연","감정 소모 큼"],
      work:"팀 내 갈등 조정과 관계 관리가 핵심인 환경",
      love:"서로 배려하고 감정을 충분히 나누는 안정적 관계 선호",
      stress:"갈등을 최대한 피하되 불가피하면 대화로 해결",
      match:["행동가형","설득가형"], conflict:["모험가형","추진자형"] },
    "ITPR": { name:"분석가형", icon:"🔬", eng:"Analyst",
      desc:"내향적이고 논리적이며 빠른 사고로 문제의 핵심을 분석하는 유형",
      traits:["날카로운 분석","빠른 논리 처리","독립적 탐구","집중력","효율 중시"],
      strength:["복잡한 문제 핵심 파악","객관적 분석","독립 작업 효율성"],
      weakness:["감정 표현 부족","협업 어색함","공감 소통 어려움"],
      work:"데이터 분석, 연구, 기술 개발 등 집중적 탐구 환경",
      love:"지적 공감대를 형성한 파트너와의 깊은 대화를 소중히 여김",
      stress:"문제를 빠르게 분석하고 혼자 해결책을 도출",
      match:["열정가형","모험가형"], conflict:["조율자형","설득가형"] },
    "ITPC": { name:"지혜자형", icon:"🎓", eng:"Wise Expert",
      desc:"지식을 중시하며 팀 내에서 논리적 해결책을 제공하는 내성적 지성인",
      traits:["깊은 전문성","논리적 기여","협업 내 지식 제공","분석력","차분함"],
      strength:["팀 내 지식 자원","복잡한 문제 해결","신뢰성"],
      weakness:["의사소통 직접성 부족","감정 공감 제한","존재감 부각 어려움"],
      work:"전문 지식을 팀 성과로 연결하는 기술·연구 역할",
      love:"공통 관심사와 지적 교류가 있는 차분한 관계 선호",
      stress:"문제를 체계적으로 분석하고 팀과 해결책을 공유",
      match:["관리자형","추진자형"], conflict:["행동가형","설득가형"] },
    "ITJR": { name:"전략가형", icon:"♟️", eng:"Strategist",
      desc:"신중하고 분석적이며 전체적 관점에서 장기 전략을 세우는 사색가",
      traits:["장기 비전","체계적 사고","독립 전략 수립","심층 분석","신중함"],
      strength:["장기 전략 탁월","리스크 예측","논리적 설득"],
      weakness:["과분석 마비(analysis paralysis)","감정 무시 경향","행동 지연"],
      work:"장기 계획 수립과 복잡한 의사결정이 필요한 역할",
      love:"지적으로 교감하며 서로의 성장을 지지하는 파트너 선호",
      stress:"위기를 전략적으로 분석하고 단계별로 직면",
      match:["열정가형","조율자형"], conflict:["모험가형","행동가형"] },
    "ITJC": { name:"연구가형", icon:"🔭", eng:"Researcher",
      desc:"호기심이 많고 체계적인 탐구를 통해 지식을 쌓는 학구파",
      traits:["깊은 탐구심","체계적 접근","협업 내 전문성","신중한 실행","집요함"],
      strength:["심층 연구","정확성","팀 내 지식 기반 제공"],
      weakness:["완벽주의 지연","타인 의견 과수용","유연성 부족"],
      work:"연구개발, 데이터 기반 협업, 심층 분석 환경",
      love:"서로 배우고 성장하는 지적 파트너십 선호",
      stress:"문제를 체계적으로 조사하고 팀과 함께 해결",
      match:["관리자형","추진자형"], conflict:["모험가형","행동가형"] },
    "IFPR": { name:"창의가형", icon:"🎨", eng:"Innovator",
      desc:"감성이 풍부하고 상상력이 뛰어나며 독창적으로 사고하는 창의형",
      traits:["풍부한 상상력","독창적 아이디어","감성적 표현","독립 창작","유연성"],
      strength:["독창적 솔루션","예술적 감수성","비틀어 보는 시각"],
      weakness:["실행력 부족","현실 적용 어려움","체계성 부족"],
      work:"창의적 기획, 예술·디자인, 아이디어 발산이 필요한 환경",
      love:"감정과 창의성을 공유하는 독특한 파트너 선호",
      stress:"감정을 창의적 표현으로 승화하거나 잠시 회피 후 직면",
      match:["연구가형","지혜자형"], conflict:["관리자형","계획가형"] },
    "IFPC": { name:"예술가형", icon:"🌈", eng:"Artist",
      desc:"감수성이 예민하고 창의적이며 예술적 영감을 팀과 공유하는 유형",
      traits:["예술적 감수성","팀 창의 기여","감성 소통","즉흥 표현","공감"],
      strength:["팀 분위기 환기","창의적 관점 제공","감성 연결"],
      weakness:["논리적 설득 어려움","일관성 유지 힘듦","갈등 회피"],
      work:"창의 협업, 콘텐츠 제작, 문화·예술 관련 팀 환경",
      love:"감성과 창의성을 공유하며 자유로운 표현이 가능한 관계 선호",
      stress:"감정을 예술적으로 표현하거나 팀과 감정 나누기로 해소",
      match:["설득가형","지혜자형"], conflict:["전략가형","계획가형"] },
    "IFJR": { name:"관찰자형", icon:"🦉", eng:"Observer",
      desc:"조용하고 관찰력이 뛰어나며 깊은 이해로 상황을 파악하는 관찰가",
      traits:["예리한 관찰력","깊은 공감","독립적 사색","신중한 판단","내면 집중"],
      strength:["상황의 본질 파악","섬세한 감성 지원","신뢰 관계 형성"],
      weakness:["자기 표현 어려움","행동 지연","감정 억압"],
      work:"상담, 연구, 심리·교육 등 깊은 이해가 필요한 환경",
      love:"깊고 조용한 유대감을 쌓는 파트너 선호",
      stress:"감정을 내면에서 소화하며 천천히 직면",
      match:["설득가형","추진자형"], conflict:["모험가형","행동가형"] },
    "IFJC": { name:"공감가형", icon:"💚", eng:"Empath",
      desc:"다정다감하고 배려심 깊으며 타인의 심리를 이해하고 조화를 이루는 유형",
      traits:["깊은 공감","타인 배려","감성 지지","조화 추구","내면 성찰"],
      strength:["팀 심리적 안전감 조성","관계 회복력","감성 리더십"],
      weakness:["자기 감정 소홀","과도한 양보","의사 결정 지연"],
      work:"상담, 사회복지, 교육 등 사람 중심 환경",
      love:"상대방 감정을 세심히 이해하고 배려하는 따뜻한 관계 추구",
      stress:"주변 사람들과 감정을 나누며 점진적으로 문제 직면",
      match:["모험가형","추진자형"], conflict:["분석가형","전략가형"] },
  };

  // LOST 점수 계산 함수
  function calcLost() {
    const axisScores = { E:0, D:0, S:0, N:0, R:0, T:0 };
    const axisCount  = { E:0, D:0, S:0, N:0, R:0, T:0 };
    lostQ.forEach(q => {
      const r = lostResponses[q.num];
      if (r === undefined) return;
      const score = q.rev ? (6 - r) : r;
      axisScores[q.axis] += score;
      axisCount[q.axis]++;
    });
    const avg = {};
    Object.keys(axisScores).forEach(k => {
      avg[k] = axisCount[k] > 0 ? (axisScores[k] / axisCount[k]) : 3;
    });
    // 4축 유형 코드 결정 (각 축 평균 3.0 기준)
    const EI = avg.E >= 3.0 ? "E" : "I";
    const TF = avg.D >= 3.0 ? "T" : "F";
    const PJ = avg.S >= 3.0 ? "P" : "J";
    const RC = avg.R >= 3.0 ? "R" : "C";
    // 스트레스 반응 부가 축 (직면=A 또는 회피=V)
    const TV = avg.T >= 3.0 ? "A" : "V";
    // 안정성 부가 정보
    const NC = avg.N >= 3.0 ? "변화선호" : "안정선호";
    const typeCode = EI + TF + PJ + RC;
    const typeInfo = LOST_TYPES[typeCode] || LOST_TYPES["ETPR"];
    return { axisAvg: avg, typeCode, typeInfo, stressStyle: TV, stabilityStyle: NC };
  }

  // 번아웃 영역별 문항 그룹핑 함수
  const getBurnoutDomains = () => [
    { 
      id: "EE", 
      name: "정서적 소진", 
      icon: "😰",
      color: "#f97316", 
      max: 72,
      questions: burnoutQ.filter(q => q.domain === "EE")
    },
    { 
      id: "DP", 
      name: "비인격화", 
      icon: "😶",
      color: "#ef4444", 
      max: 48,
      questions: burnoutQ.filter(q => q.domain === "DP")
    },
    { 
      id: "PA", 
      name: "성취감 저하", 
      icon: "📉",
      color: "#c084fc", 
      max: 60,
      questions: burnoutQ.filter(q => q.domain === "PA")
    },
    { 
      id: "WO", 
      name: "업무 과부하", 
      icon: "⚡",
      color: "#f59e0b", 
      max: 60,
      questions: burnoutQ.filter(q => q.domain === "WO")
    },
    { 
      id: "PC", 
      name: "신체·인지", 
      icon: "🤕",
      color: "#4ade80", 
      max: 60,
      questions: burnoutQ.filter(q => q.domain === "PC")
    }
  ];

  function calcDsi() {
    let total = 0;
    const areas = { "인지적 기능": 0, "자아통합": 0, "가족투사": 0, "정서적 단절": 0, "가족퇴행": 0 };
    dsiQ.forEach(q => {
      const r = dsiResponses[q.num];
      if (r) {
        const s = q.rev ? 6 - r : r;
        total += s;
        areas[q.area] += s;
      }
    });
    return { total, areas };
  }

  // PHQ-9 계산 함수
  function calcPhq9() {
    let total = 0;
    phq9Q.forEach(q => {
      const r = phq9Responses[q.num];
      if (r) total += r;
    });
    let level = "정상";
    let color = "green";
    if (total >= 20) { level = "심한 우울"; color = "red"; }
    else if (total >= 15) { level = "중간-심도 우울"; color = "orange"; }
    else if (total >= 10) { level = "중간 우울"; color = "orange"; }
    else if (total >= 5) { level = "가벼운 우울"; color = "yellow"; }
    return { total, level, color };
  }

  // GAD-7 계산 함수
  function calcGad7() {
    let total = 0;
    gad7Q.forEach(q => {
      const r = gad7Responses[q.num];
      if (r) total += r;
    });
    let level = "정상";
    let color = "green";
    if (total >= 15) { level = "심한 불안"; color = "red"; }
    else if (total >= 10) { level = "중간 불안"; color = "orange"; }
    else if (total >= 5) { level = "가벼운 불안"; color = "yellow"; }
    return { total, level, color };
  }

  // DASS-21 계산 함수
  function calcDass21() {
    let depression = 0, anxiety = 0, stress = 0;
    dass21Q.forEach(q => {
      const r = dass21Responses[q.num];
      if (r) {
        const score = r - 1; // 0-3 범위로 변환
        if (q.scale === "우울") depression += score;
        else if (q.scale === "불안") anxiety += score;
        else if (q.scale === "스트레스") stress += score;
      }
    });
    // 곱하기 2 (DASS-42 점수로 변환)
    depression *= 2;
    anxiety *= 2;
    stress *= 2;

    const getLevel = (score, type) => {
      if (type === "우울") {
        if (score >= 28) return { level: "극도로 심함", color: "red" };
        if (score >= 21) return { level: "심함", color: "orange" };
        if (score >= 14) return { level: "중간", color: "yellow" };
        if (score >= 10) return { level: "가벼움", color: "blue" };
        return { level: "정상", color: "green" };
      } else if (type === "불안") {
        if (score >= 20) return { level: "극도로 심함", color: "red" };
        if (score >= 15) return { level: "심함", color: "orange" };
        if (score >= 10) return { level: "중간", color: "yellow" };
        if (score >= 8) return { level: "가벼움", color: "blue" };
        return { level: "정상", color: "green" };
      } else { // 스트레스
        if (score >= 34) return { level: "극도로 심함", color: "red" };
        if (score >= 26) return { level: "심함", color: "orange" };
        if (score >= 19) return { level: "중간", color: "yellow" };
        if (score >= 15) return { level: "가벼움", color: "blue" };
        return { level: "정상", color: "green" };
      }
    };

    return {
      depression: { score: depression, ...getLevel(depression, "우울") },
      anxiety: { score: anxiety, ...getLevel(anxiety, "불안") },
      stress: { score: stress, ...getLevel(stress, "스트레스") }
    };
  }

  // Big5 계산 함수
  function calcBig5() {
    const factors = { "외향성": 0, "친화성": 0, "성실성": 0, "신경성": 0, "개방성": 0 };
    const counts = { "외향성": 0, "친화성": 0, "성실성": 0, "신경성": 0, "개방성": 0 };
    
    big5Q.forEach(q => {
      const r = big5Responses[q.num];
      if (r) {
        const score = q.rev ? (6 - r) : r;
        factors[q.factor] += score;
        counts[q.factor]++;
      }
    });

    // 평균 점수 계산 (1-5 범위)
    Object.keys(factors).forEach(f => {
      if (counts[f] > 0) {
        factors[f] = (factors[f] / counts[f]).toFixed(2);
      }
    });

    return factors;
  }

  // 번아웃 계산 함수
  function calcBurnout() {
    
    let total = 0;
    const domains = {};
    
    // 영역별 초기화
    const domainConfigs = getBurnoutDomains();
    
    domainConfigs.forEach(d => {
      domains[d.id] = { name: d.name, score: 0, max: d.max, color: d.color };
    });

    burnoutQ.forEach(q => {
      const r = burnoutResponses[q.num];
      if (r !== undefined) {
        const score = q.rev ? (6 - r) : r;
        total += score;
        domains[q.domain].score += score;
      }
    });
    

    // 전체 레벨 판단 (0-240점)
    const percentage = Math.round((total / 240) * 100);
    const pct = total / 240;
    let level = "매우 낮음";
    let levelColor = "#4ade80";
    let levelDesc = "번아웃 위험이 낮습니다. 현재 상태를 잘 유지하세요.";
    
    if (pct >= 0.86) {
      level = "매우 높음";
      levelColor = "#dc2626";
      levelDesc = "매우 심각한 번아웃 상태입니다. 즉시 전문가의 도움을 받으세요.";
    } else if (pct >= 0.71) {
      level = "높음";
      levelColor = "#f97316";
      levelDesc = "높은 수준의 번아웃입니다. 전문 상담을 권장합니다.";
    } else if (pct >= 0.51) {
      level = "보통";
      levelColor = "#f59e0b";
      levelDesc = "번아웃 증상이 보통 수준입니다. 관리가 필요합니다.";
    } else if (pct >= 0.31) {
      level = "낮음";
      levelColor = "#eab308";
      levelDesc = "가벼운 번아웃 증상이 나타나고 있습니다. 주의가 필요합니다.";
    }

    // 각 영역별 레벨 판단 및 설명
    const domainList = [];
    const domainCrisis = [];
    
    Object.entries(domains).forEach(([id, d]) => {
      const domainPct = (d.score / d.max) * 100;
      d.percentage = Math.round(domainPct); // 퍼센테이지 저장
      d.id = id; // 영역 ID 저장
      
      if (domainPct >= 85) {
        d.level = "매우 높음";
        d.description = "이 영역에서 심각한 번아웃 증상을 보이고 있습니다.";
        domainCrisis.push(d.name);
      } else if (domainPct >= 70) {
        d.level = "높음";
        d.description = "이 영역에서 높은 수준의 스트레스를 경험하고 있습니다.";
      } else if (domainPct >= 50) {
        d.level = "보통";
        d.description = "이 영역에서 보통 수준의 피로를 느끼고 있습니다.";
      } else if (domainPct >= 30) {
        d.level = "낮음";
        d.description = "이 영역에서 약간의 스트레스가 있습니다.";
      } else {
        d.level = "매우 낮음";
        d.description = "이 영역은 건강한 상태입니다.";
      }
      
      domainList.push(d);
    });

    const crisis = pct >= 0.75 || domainCrisis.length > 0;

    return { 
      totalScore: total,
      percentage,
      domains: domainList, 
      level, 
      levelColor, 
      levelDesc, 
      crisis,
      domainCrisis
    };
  }

  function storeLink(d) {
    storage.set("link_" + d.linkId, JSON.stringify(d));
  }
  
  function loadLink(id) {
    const r = storage.get("link_" + id);
    return r ? JSON.parse(r.value) : null;
  }
  
  function storeSession(data) {
    storage.set("session_" + data.sessionId, JSON.stringify(data));
    
    const listRaw = storage.get("submitted_list");
    const list = listRaw ? JSON.parse(listRaw.value) : [];
    const sessionInfo = {
      sessionId: data.sessionId,
      testType: data.testType,
      userPhone: data.userPhone,
      createdAt: data.createdAt,
      linkId: data.linkId
    };
    list.unshift(sessionInfo);
    storage.set("submitted_list", JSON.stringify(list));
    
    setSubmitted(list);
  }
  
  function loadAllSubmitted() {
    const r = storage.get("submitted_list");
    const list = r ? JSON.parse(r.value) : [];
    setSubmitted(list);
  }

  async function loadOrganizations() {
    try {
      const res = await authFetch('/api/organizations');
      const data = await res.json();
      if (data.success) setOrganizations(data.data || []);
      else setOrganizations([]);
    } catch (error) { setOrganizations([]); }
  }

  async function loadMasterSessions() {
    setMasterSessionsLoading(true);
    try {
      const res = await authFetch('/api/master/sessions');
      const data = await res.json();
      if (data.success) setMasterSessions(data.data || []);
      else setMasterSessions([]);
    } catch (error) { setMasterSessions([]); }
    finally { setMasterSessionsLoading(false); }
  }

  async function loadNotifications(target = 'all') {
    try { await authFetch(`/api/notifications?target=${encodeURIComponent(target)}`); } catch (error) {}
  }

  async function loadNotices(target = 'all') {
    try {
      const res = await authFetch(`/api/notices?target=${encodeURIComponent(target)}`);
      const data = await res.json();
      if (data.success) setNotices(data.data || []);
      else setNotices([]);
    } catch (error) { setNotices([]); }
  }

  async function loadMasterData() {
    await Promise.all([loadOrganizations(), loadMasterSessions(), loadNotifications('all'), loadNotices('all')]);
    try {
      const [pendingResult, approvedResult] = await Promise.all([api.getPendingCounselors(), api.getApprovedCounselors()]);
      if (pendingResult.success) setPendingCounselors(pendingResult.data || []);
      if (approvedResult.success) setApprovedCounselors(approvedResult.data || []);
    } catch (error) {}
  }

  async function deleteSession(sessionIdentifier) {
    if (!confirm('정말 이 검사 기록을 삭제하시겠습니까?')) return;
    try {
      const res = await authFetch(`/api/master/sessions/${encodeURIComponent(sessionIdentifier)}`, { method: 'DELETE' });
      const data = await res.json();
      if (data.success) { await loadMasterSessions(); loadAllSubmitted(); alert('검사 기록을 삭제했습니다.'); }
      else alert(data.error || '삭제 실패');
    } catch (error) { alert('삭제 중 오류가 발생했습니다.'); }
  }

  async function saveOrganization() {
    setOrgLoading(true); setOrgMsg({ type: '', text: '' });
    try {
      const payload = { name: orgForm.name, description: orgForm.description, org_type: orgForm.org_type, admin_phone: orgForm.admin_phone, subscription_type: orgForm.subscription_type, billing_cycle: orgForm.billing_cycle };
      const isEdit = !!orgForm._editId;
      const res = await authFetch(isEdit ? `/api/organizations/${orgForm._editId}` : '/api/organizations', { method: isEdit ? 'PUT' : 'POST', body: JSON.stringify(payload) });
      const data = await res.json();
      if (data.success) {
        setOrgMsg({ type: 'success', text: isEdit ? '✅ 단체 정보가 수정되었습니다.' : '✅ 단체가 등록되었습니다.' });
        setShowOrgForm(false);
        setOrgForm({ _editId: null, name: '', description: '', org_type: 'general', admin_phone: '', subscription_type: 'org_small', billing_cycle: 'monthly' });
        await loadOrganizations();
      } else { setOrgMsg({ type: 'error', text: '❌ ' + (data.error || '저장 실패') }); }
    } catch (error) { setOrgMsg({ type: 'error', text: '❌ 오류' }); }
    finally { setOrgLoading(false); }
  }

  async function deleteNotice(id) {
    if (!confirm('정말 이 공지를 삭제하시겠습니까?')) return;
    try {
      const res = await authFetch(`/api/notices/${id}`, { method: 'DELETE' });
      const data = await res.json();
      if (data.success) await loadNotices('all');
      else alert(data.error || '삭제 실패');
    } catch (error) { alert('삭제 중 오류가 발생했습니다.'); }
  }

  async function toggleNoticePin(id, pinned) {
    try {
      const res = await authFetch(`/api/notices/${id}`, { method: 'PUT', body: JSON.stringify({ pinned: !pinned }) });
      const data = await res.json();
      if (data.success) await loadNotices('all');
      else alert(data.error || '고정 상태 변경 실패');
    } catch (error) { alert('고정 상태 변경 중 오류가 발생했습니다.'); }
  }

  async function saveNotice() {
    setNoticeMsg({ type: '', text: '' });
    try {
      const res = await authFetch('/api/notices', { method: 'POST', body: JSON.stringify({ title: noticeForm.title, content: noticeForm.content, target: noticeForm.target, pinned: noticeForm.pinned, send_notification: noticeForm.send_notification }) });
      const data = await res.json();
      if (data.success) {
        setNoticeMsg({ type: 'success', text: '✅ 공지가 등록되었습니다.' });
        setShowNoticeForm(false);
        setNoticeForm({ id: null, title: '', content: '', target: 'all', pinned: false, send_notification: false });
        await loadNotices('all');
      } else { setNoticeMsg({ type: 'error', text: '❌ ' + (data.error || '등록 실패') }); }
    } catch (error) { setNoticeMsg({ type: 'error', text: '❌ 오류' }); }
  }

  // 🕐 24시간 만료 체크 및 자동 삭제 함수
  function checkAndCleanExpiredSessions() {
    const listRaw = storage.get("submitted_list");
    if (!listRaw) return;
    
    const list = JSON.parse(listRaw.value);
    const now = Date.now();
    const TWENTY_FOUR_HOURS = 24 * 60 * 60 * 1000; // 24시간 (밀리초)
    
    const validSessions = [];
    let deletedCount = 0;
    
    list.forEach(session => {
      const createdTime = new Date(session.createdAt).getTime();
      const age = now - createdTime;
      
      if (age >= TWENTY_FOUR_HOURS) {
        // 24시간 경과 - 삭제
        storage.remove("session_" + session.sessionId);
        deletedCount++;
      } else {
        validSessions.push(session);
      }
    });
    
    if (deletedCount > 0) {
      storage.set("submitted_list", JSON.stringify(validSessions));
      setSubmitted(validSessions);
    } else {
    }
  }

  // ⏱️ 남은 시간 계산 (밀리초 → 시:분:초)
  function getTimeRemaining(createdAt) {
    const now = Date.now();
    const createdTime = new Date(createdAt).getTime();
    const TWENTY_FOUR_HOURS = 24 * 60 * 60 * 1000;
    const elapsed = now - createdTime;
    const remaining = TWENTY_FOUR_HOURS - elapsed;
    
    if (remaining <= 0) {
      return { expired: true, text: "만료됨", color: "text-red-600" };
    }
    
    const hours = Math.floor(remaining / (60 * 60 * 1000));
    const minutes = Math.floor((remaining % (60 * 60 * 1000)) / (60 * 1000));
    const seconds = Math.floor((remaining % (60 * 1000)) / 1000);
    
    let color = "text-green-600";
    if (hours < 3) color = "text-red-600";
    else if (hours < 6) color = "text-orange-600";
    
    return {
      expired: false,
      text: `${hours}시간 ${minutes}분 ${seconds}초`,
      color: color,
      hours: hours
    };
  }

  // 💾 JSON 파일로 검사 결과 다운로드
  function downloadSessionJson(sessionId) {
    const r = storage.get("session_" + sessionId);
    if (!r) {
      alert('❌ 검사 결과를 찾을 수 없습니다.');
      return;
    }
    
    const sessionData = JSON.parse(r.value);
    const jsonStr = JSON.stringify(sessionData, null, 2);
    const blob = new Blob([jsonStr], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `검사결과_${sessionData.testType}_${sessionId}_${Date.now()}.json`;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
    
    alert('✅ 검사 결과가 JSON 파일로 다운로드되었습니다!');
  }

  // 📂 JSON 파일에서 검사 결과 불러오기
  function handleFileUpload(event) {
    const file = event.target.files[0];
    if (!file) return;
    
    const reader = new FileReader();
    reader.onload = (e) => {
      try {
        const sessionData = JSON.parse(e.target.result);
        
        // 세션 데이터 복원
        if (sessionData.testType === "SCT") {
          setSctResponses(sessionData.responses || {});
          setSctSummaries(sessionData.summaries || {});
        } else if (sessionData.testType === "DSI") {
          setDsiResponses(sessionData.responses || {});
          setDsiRec(sessionData.recommendation || "");
        }
        
        setSessionId(sessionData.sessionId);
        setUserInfo({ phone: sessionData.userPhone || "", password: "" });
        setView(sessionData.testType === "SCT" ? "sctResult" : "dsiResult");
        
        alert(`✅ ${sessionData.testType} 검사 결과를 불러왔습니다!\n세션 ID: ${sessionData.sessionId}`);
      } catch (error) {
        alert('❌ 파일 형식이 올바르지 않습니다.');
      }
    };
    reader.readAsText(file);
  }

  function copyLink(linkId) {
    const text = linkId;
    try {
      navigator.clipboard.writeText(text).then(() => {
        setCopiedId(linkId);
        setTimeout(() => setCopiedId(null), 2500);
      }).catch(() => fallbackCopy(linkId, text));
    } catch {
      fallbackCopy(linkId, text);
    }
  }
  
  function fallbackCopy(linkId, text) {
    const ta = document.createElement("textarea");
    ta.value = text;
    ta.style.cssText = "position:fixed;top:0;left:0;opacity:0";
    document.body.appendChild(ta);
    ta.select();
    document.execCommand("copy");
    document.body.removeChild(ta);
    setCopiedId(linkId);
    setTimeout(() => setCopiedId(null), 2500);
  }

  // 📄 PDF 생성 함수들
  async function generateSctPdf(sessionData) {
    try {
      const { jsPDF } = window.jspdf;
      const doc = new jsPDF({
        orientation: 'portrait',
        unit: 'mm',
        format: 'a4'
      });

      // 한글 폰트 설정 (기본 폰트 사용)
      const pageWidth = doc.internal.pageSize.getWidth();
      const pageHeight = doc.internal.pageSize.getHeight();
      const margin = 20;
      let yPos = margin;

      // 헤더 (영문만 사용)
      doc.setFontSize(20);
      doc.setFont(undefined, 'bold');
      doc.text('SCT Test Result Report', pageWidth / 2, yPos, { align: 'center' });
      
      yPos += 15;
      doc.setFontSize(10);
      doc.setFont(undefined, 'normal');
      doc.text('Sentence Completion Test', pageWidth / 2, yPos, { align: 'center' });
      
      yPos += 15;
      doc.setDrawColor(0);
      doc.setLineWidth(0.5);
      doc.line(margin, yPos, pageWidth - margin, yPos);
      yPos += 10;

      // 기본 정보
      doc.setFontSize(11);
      doc.setFont(undefined, 'bold');
      doc.text('[ 1. Basic Information ]', margin, yPos);
      yPos += 8;
      
      doc.setFont(undefined, 'normal');
      doc.setFontSize(10);
      doc.text(`Session ID: ${sessionData.sessionId}`, margin + 5, yPos);
      yPos += 6;
      doc.text(`Test Date: ${new Date(sessionData.createdAt).toLocaleDateString('en-US')}`, margin + 5, yPos);
      yPos += 6;
      doc.text(`Phone: ${sessionData.userPhone || 'N/A'}`, margin + 5, yPos);
      yPos += 10;

      // 카테고리별 응답 (AI 분석은 제외 - 한글 문제)
      doc.setFontSize(11);
      doc.setFont(undefined, 'bold');
      doc.text('[ 2. Responses by Category ]', margin, yPos);
      yPos += 8;

      // 카테고리 이름 영문 매핑
      const categoryMap = {
        "어머니에 대한 태도": "Attitude toward Mother",
        "아버지에 대한 태도": "Attitude toward Father",
        "가족 관계": "Family Relationships",
        "이성 관계": "Romantic Relationships",
        "친구 관계": "Friendships",
        "권위자에 대한 태도": "Attitude toward Authority",
        "두려움": "Fears",
        "죄책감": "Guilt",
        "능력에 대한 인식": "Perception of Abilities",
        "과거": "Past",
        "미래": "Future",
        "목표": "Goals"
      };

      for (const cat of sctCategories) {
        // 페이지 넘김 체크
        if (yPos > pageHeight - 40) {
          doc.addPage();
          yPos = margin;
        }

        const englishCatName = categoryMap[cat.name] || cat.name;
        
        doc.setFontSize(10);
        doc.setFont(undefined, 'bold');
        doc.text(`${cat.emoji} ${englishCatName}`, margin + 5, yPos);
        yPos += 7;

        const catQs = sctQ.filter(q => q.cat === cat.name);
        doc.setFont(undefined, 'normal');
        doc.setFontSize(9);

        for (const q of catQs) {
          const answer = sessionData.responses[q.num] || '(No answer)';
          
          // 질문 (한글 제목 제외, 번호만)
          if (yPos > pageHeight - 30) {
            doc.addPage();
            yPos = margin;
          }
          
          doc.text(`Q${q.num}:`, margin + 10, yPos);
          yPos += 5;
          
          // 답변 (영문/숫자만 표시)
          const answerText = `Answer: ${answer}`;
          doc.setTextColor(0, 102, 204);
          doc.text(answerText, margin + 10, yPos);
          doc.setTextColor(0, 0, 0);
          yPos += 7;
        }

        // AI 분석은 한글 문제로 제외
        yPos += 5;
      }

      // 푸터
      const totalPages = doc.internal.pages.length - 1;
      for (let i = 1; i <= totalPages; i++) {
        doc.setPage(i);
        doc.setFontSize(8);
        doc.setTextColor(128, 128, 128);
        doc.text(
          `Page ${i} of ${totalPages} | Generated: ${new Date().toLocaleDateString('en-US')}`,
          pageWidth / 2,
          pageHeight - 10,
          { align: 'center' }
        );
      }

      // 다운로드
      const fileName = `SCT_Report_${sessionData.sessionId}_${new Date().getTime()}.pdf`;
      doc.save(fileName);
      alert('✅ SCT PDF downloaded successfully!');
    } catch (error) {
      alert('❌ PDF generation failed: ' + error.message);
    }
  }

  async function generateDsiPdf(sessionData) {
    try {
      const { jsPDF } = window.jspdf;
      const doc = new jsPDF({
        orientation: 'portrait',
        unit: 'mm',
        format: 'a4'
      });

      const pageWidth = doc.internal.pageSize.getWidth();
      const pageHeight = doc.internal.pageSize.getHeight();
      const margin = 20;
      let yPos = margin;

      // 임시로 응답 복원
      const tempDsiResponses = sessionData.responses;
      
      // 점수 계산
      let total = 0;
      const areas = { "가족불화": 0, "부모관계": 0, "형제관계": 0, "가족퇴행": 0, "투사": 0 };
      dsiQ.forEach(q => {
        const r = tempDsiResponses[q.num];
        if (r) {
          const s = q.rev ? 6 - r : r;
          total += s;
          areas[q.area] += s;
        }
      });

      // 헤더 (영문만 사용)
      doc.setFontSize(20);
      doc.setFont(undefined, 'bold');
      doc.text('DSI Test Result Report', pageWidth / 2, yPos, { align: 'center' });
      
      yPos += 15;
      doc.setFontSize(10);
      doc.setFont(undefined, 'normal');
      doc.text('Differentiation of Self Inventory', pageWidth / 2, yPos, { align: 'center' });
      
      yPos += 15;
      doc.setDrawColor(0);
      doc.setLineWidth(0.5);
      doc.line(margin, yPos, pageWidth - margin, yPos);
      yPos += 10;

      // 기본 정보
      doc.setFontSize(11);
      doc.setFont(undefined, 'bold');
      doc.text('[ 1. Basic Information ]', margin, yPos);
      yPos += 8;
      
      doc.setFont(undefined, 'normal');
      doc.setFontSize(10);
      doc.text(`Session ID: ${sessionData.sessionId}`, margin + 5, yPos);
      yPos += 6;
      doc.text(`Test Date: ${new Date(sessionData.createdAt).toLocaleString('en-US')}`, margin + 5, yPos);
      yPos += 6;
      doc.text(`Phone: ${sessionData.userPhone || 'N/A'}`, margin + 5, yPos);
      yPos += 12;

      // 종합 점수
      doc.setFontSize(11);
      doc.setFont(undefined, 'bold');
      doc.text('[ 2. Overall Score ]', margin, yPos);
      yPos += 8;

      const level = total >= 109 ? 'High' : total >= 73 ? 'Medium' : 'Low';
      const levelColor = total >= 109 ? [76, 175, 80] : total >= 73 ? [255, 193, 7] : [255, 87, 87];

      doc.setFontSize(10);
      doc.setFont(undefined, 'normal');
      doc.text(`Total Score: ${total} / 180`, margin + 5, yPos);
      yPos += 6;
      
      doc.setFont(undefined, 'bold');
      doc.setTextColor(...levelColor);
      doc.text(`Level: ${level}`, margin + 5, yPos);
      doc.setTextColor(0, 0, 0);
      yPos += 12;

      // 영역별 점수
      doc.setFontSize(11);
      doc.setFont(undefined, 'bold');
      doc.text('[ 3. Area Scores ]', margin, yPos);
      yPos += 8;

      doc.setFontSize(9);
      doc.setFont(undefined, 'normal');

      // 영역 이름을 영문으로 매핑
      const areaNameMap = {
        "가족불화": "Family Conflict",
        "부모관계": "Parent Relationship", 
        "형제관계": "Sibling Relationship",
        "가족퇴행": "Family Regression",
        "투사": "Projection"
      };

      const areaNames = Object.keys(areas);
      for (const areaName of areaNames) {
        if (yPos > pageHeight - 30) {
          doc.addPage();
          yPos = margin;
        }

        const score = areas[areaName];
        const areaQs = dsiQ.filter(q => q.area === areaName);
        const maxScore = areaQs.length * 5;
        const avgScore = (score / areaQs.length).toFixed(1);
        const englishName = areaNameMap[areaName] || areaName;

        doc.text(`${englishName}: ${score}/${maxScore} (Avg: ${avgScore})`, margin + 5, yPos);
        
        // 진행 바
        const barWidth = 100;
        const barHeight = 4;
        const fillWidth = (score / maxScore) * barWidth;
        
        doc.setDrawColor(200, 200, 200);
        doc.setLineWidth(0.3);
        doc.rect(margin + 60, yPos - 3, barWidth, barHeight);
        
        doc.setFillColor(...levelColor);
        doc.rect(margin + 60, yPos - 3, fillWidth, barHeight, 'F');
        
        yPos += 8;
      }

      yPos += 5;

      // 상세 응답
      doc.addPage();
      yPos = margin;
      
      doc.setFontSize(11);
      doc.setFont(undefined, 'bold');
      doc.text('[ 4. Detailed Responses ]', margin, yPos);
      yPos += 8;

      doc.setFontSize(8);
      doc.setFont(undefined, 'normal');

      for (const q of dsiQ) {
        if (yPos > pageHeight - 20) {
          doc.addPage();
          yPos = margin;
        }

        const answer = tempDsiResponses[q.num] || 'N/A';
        const scoreText = q.rev ? `(Reversed, Score: ${6 - parseInt(answer)})` : `(Score: ${answer})`;
        const englishArea = areaNameMap[q.area] || q.area;
        
        const questionText = `Q${q.num}. [${englishArea}]`;
        doc.text(questionText, margin + 5, yPos);
        yPos += 4;
        
        doc.setTextColor(0, 102, 204);
        doc.text(`Answer: ${answer} ${scoreText}`, margin + 5, yPos);
        doc.setTextColor(0, 0, 0);
        yPos += 6;
      }

      // AI 권장사항은 한글 지원 문제로 PDF에서 제외
      // 웹 화면에서 확인 가능

      // 푸터
      const totalPages = doc.internal.pages.length - 1;
      for (let i = 1; i <= totalPages; i++) {
        doc.setPage(i);
        doc.setFontSize(8);
        doc.setTextColor(128, 128, 128);
        doc.text(
          `Page ${i} of ${totalPages} | Generated: ${new Date().toLocaleDateString('en-US')}`,
          pageWidth / 2,
          pageHeight - 10,
          { align: 'center' }
        );
      }

      // 다운로드
      const fileName = `DSI_Report_${sessionData.sessionId}_${new Date().getTime()}.pdf`;
      doc.save(fileName);
      alert('✅ DSI PDF downloaded successfully!');
    } catch (error) {
      alert('❌ PDF generation failed: ' + error.message);
    }
  }

  

  async function generateLink() {
    if (!linkForm.clientName || !linkForm.clientPhone) {
      setFormMsg({ type: "error", text: "내담자 이름과 전화번호를 입력해주세요." });
      return;
    }
    if (!linkForm.testTypes || linkForm.testTypes.length === 0) {
      setFormMsg({ type: "error", text: "검사 유형을 1개 이상 선택해주세요." });
      return;
    }
    
    setFormMsg({ type: "info", text: "쿼터 확인 중..." });
    
    try {
      // 현재 구독 정보 새로고침
      const subResult = await api.getSubscription(counselorPhone);
      if (!subResult.success) {
        setFormMsg({ type: "error", text: "구독 정보를 불러올 수 없습니다." });
        return;
      }
      
      setSubscription(subResult.data);
      
      const remaining = subResult.data.quota_total - subResult.data.quota_used;
      
      // 쿼터 부족 체크 (멀티 검사도 링크 1개 = 쿼터 1회)
      if (remaining <= 0) {
        setFormMsg({ type: "error", text: "⚠️ 남은 쿼터가 없습니다. 플랜을 업그레이드하세요." });
        setView("pricingPlans");
        return;
      }
      
      const linkId = genId("link");
      const testTypesLabel = linkForm.testTypes.join("+");
      
      // 쿼터 차감 (묶음 검사도 1회)
      const quotaResult = await api.consumeQuota(counselorPhone, linkId, testTypesLabel, 1);
      
      if (!quotaResult.success) {
        if (quotaResult.needsPayment) {
          setFormMsg({ type: "error", text: "⚠️ " + quotaResult.error });
          setView("pricingPlans");
        } else {
          setFormMsg({ type: "error", text: "쿼터 차감 실패: " + quotaResult.error });
        }
        return;
      }
      
      // 링크 데이터 생성 (testTypes 배열로 저장)
      const data = {
        linkId,
        counselorPhone,
        clientName: linkForm.clientName,
        clientPhone: linkForm.clientPhone,
        testTypes: linkForm.testTypes,          // 배열
        testType: linkForm.testTypes[0],         // 하위 호환성 유지
        counselingType: linkForm.counselingType,
        createdAt: new Date().toISOString(),
        status: "pending"
      };
      
      storeLink(data);
      
      // 구독 정보 업데이트
      setSubscription({
        ...subResult.data,
        quota_used: quotaResult.data.used
      });
      
      setGeneratedLinks(prev => [data, ...prev]);
      setLinkForm({ clientName: "", clientPhone: "", testTypes: ["SCT"], counselingType: "psychological" });
      setFormMsg({ 
        type: "success", 
        text: `✅ 링크가 생성되었습니다! 검사 ${data.testTypes.length}개 묶음 (남은 쿼터: ${quotaResult.data.remaining}/${quotaResult.data.total})` 
      });
      setTimeout(() => setFormMsg({ type: "", text: "" }), 4000);
    } catch (error) {
      setFormMsg({ type: "error", text: "서버 오류가 발생했습니다." });
    }
  }

  function enterByLinkId() {
    const id = linkInput.trim();
    if (!id) {
      setLoginMsg({ type: "error", text: "링크 ID를 입력해주세요." });
      return;
    }
    const data = loadLink(id);
    if (!data) {
      setLoginMsg({ type: "error", text: "유효하지 않은 링크 ID입니다. 상담사에게 다시 확인하세요." });
      return;
    }
    setActiveLinkId(id);
    setActiveLinkData(data);
    setLoginMsg({ type: "", text: "" });
    setView("clientLogin");
  }

  function clientLogin() {
    if (!userInfo.phone || !userInfo.password) {
      setLoginMsg({ type: "error", text: "전화번호와 비밀번호를 모두 입력해주세요." });
      return;
    }
    if (!activeLinkData) {
      setLoginMsg({ type: "error", text: "링크 정보가 없습니다." });
      return;
    }
    const inp = userInfo.phone.replace(/-/g, "");
    const reg = activeLinkData.clientPhone.replace(/-/g, "");
    if (inp !== reg) {
      setLoginMsg({ type: "error", text: "등록된 전화번호와 일치하지 않습니다." });
      return;
    }
    setLoginMsg({ type: "", text: "" });
    setSctResponses({});
    setSctSummaries({});
    setDsiResponses({});
    setPhq9Responses({});
    setGad7Responses({});
    setDass21Responses({});
    setBig5Responses({});
    setBurnoutResponses({});
    setSessionId(genId("session"));
    setMultiSessionIds([]);
    
    // 멀티 검사 큐 초기화 (testTypes 배열 우선, 없으면 testType 단일 사용)
    const tests = activeLinkData.testTypes && activeLinkData.testTypes.length > 0
      ? activeLinkData.testTypes
      : [activeLinkData.testType || "SCT"];
    setPendingTests(tests);
    setCurrentTestIndex(0);
    
    // 첫 번째 검사 화면으로 이동
    const testViews = {
      "SCT": "sctTest", "DSI": "dsiTest", "PHQ9": "phq9Test",
      "GAD7": "gad7Test", "DASS21": "dass21Test", "BIG5": "big5Test", "BURNOUT": "burnoutTest"
    };
    setView(testViews[tests[0]] || "sctTest");
  }

  async function adminLogin() {
    // 하드코딩 비밀번호 제거 — masterLogin으로 위임
    return masterLogin();
  }

async function masterLogin() {
    if (!userInfo.phone || !userInfo.password) {
      setLoginMsg({ type: 'error', text: '전화번호와 비밀번호를 입력해주세요.' });
      return;
    }
    setLoginLoading(true);
    setLoginMsg({ type: 'info', text: '로그인 중...' });
    try {
      const res = await fetch('/api/master/login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ phone: userInfo.phone, password: userInfo.password })
      });
      const data = await res.json();
      if (data.success) {
        setIsMaster(true);
        setIsAdmin(true);
        setMasterInfo(data.data);
        saveToken(data.token);
        saveLoginState({ type: 'master', phone: data.data.phone, name: data.data.name });
        await loadMasterData();
        loadNotifications(data.data.phone);
        loadNotices('all');
        setLoginMsg({ type: '', text: '' });
        setView('masterDashboard');
      } else {
        setLoginMsg({ type: 'error', text: data.error || '로그인 실패' });
      }
    } catch (e) {
      setLoginMsg({ type: 'error', text: '서버 오류가 발생했습니다.' });
    } finally {
      setLoginLoading(false);
    }
  }

    async function orgAdminLogin() {
    if (!userInfo.phone || !userInfo.password) {
      setLoginMsg({ type: "error", text: "전화번호와 비밀번호를 입력해주세요." });
      return;
    }
    setLoginLoading(true);
    setLoginMsg({ type: "info", text: "로그인 중..." });
    try {
      const res = await fetch('/api/counselor/login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ phone: userInfo.phone, password: userInfo.password })
      });
      const data = await res.json();
      if (data.success) {
        // org_admin role 확인
        if (data.data && (data.data.role === 'org_admin' || data.data.org_id)) {
          setIsOrgAdmin(true);
          setOrgAdminInfo({
            phone: data.data.phone,
            name: data.data.name,
            org_id: data.data.org_id,
            org_name: data.data.org_name || '소속 단체'
          });
          if (data.token) saveToken(data.token);
          saveLoginState({
            type: 'org_admin',
            phone: data.data.phone,
            name: data.data.name,
            org_id: data.data.org_id,
            org_name: data.data.org_name || ''
          });
          setLoginMsg({ type: '', text: '' });
          setView('orgAdminDashboard');
        } else {
          setLoginMsg({ type: "error", text: "단체관리자 계정이 아닙니다. 상담사 로그인을 이용하세요." });
        }
      } else {
        setLoginMsg({ type: "error", text: data.error || "로그인에 실패했습니다." });
      }
    } catch (e) {
      setLoginMsg({ type: "error", text: "서버 오류가 발생했습니다." });
    } finally {
      setLoginLoading(false);
    }
  }

  async function loadOrgCounselors(orgId) {
    try {
      const response = await authFetch(`/api/organizations/${orgId}/counselors`);
      const data = await response.json();
      if (data.success) setOrgCounselors(data.data || []);
      else setOrgCounselors([]);
    } catch (error) {
    }
  }

  async function counselorLogin() {
    if (!userInfo.phone || !userInfo.password) {
      setLoginMsg({ type: "error", text: "정보를 입력해주세요." });
      return;
    }
    
    setLoginMsg({ type: "info", text: "로그인 중..." });
    
    try {
      // ✅ D1 API로 비밀번호 검증 (LocalStorage 사용 제거)
      const loginResult = await api.loginCounselor(userInfo.phone, userInfo.password);
      
      if (!loginResult.success) {
        // 레거시 계정: password_hash 미설정 안내
        if (loginResult.needsPasswordReset) {
          setLoginMsg({ type: "error", text: "비밀번호 초기 설정이 필요합니다. 관리자에게 문의하세요." });
          return;
        }
        // 미승인 계정
        if (loginResult.notApproved) {
          setLoginMsg({ type: "error", text: "관리자 승인 대기 중입니다." });
          return;
        }
        setLoginMsg({ type: "error", text: loginResult.error || "로그인 실패" });
        return;
      }
      
      const userData = loginResult.data;
      
      // 구독 정보 매핑 (D1 login 응답 → 기존 subscription 구조)
      const subscriptionData = {
        phone: userData.phone,
        name: userData.name,
        counselor_type: userData.counselorType,
        subscription_type: userData.subscriptionType,
        subscription_status: userData.subscriptionStatus,
        quota_total: userData.quotaTotal,
        quota_used: userData.quotaUsed,
        is_approved: userData.isApproved
      };
      
      // 상태 업데이트
      setIsCounselor(true);
      setCounselorPhone(userData.phone);
      setSubscription(subscriptionData);
      
      // AI 분석 사용 횟수 복원 (무료 플랜 제한용)
      const savedAiCount = parseInt(localStorage.getItem("ai_usage_" + userData.phone) || "0", 10);
      setAiUsageCount(savedAiCount);
      
      // 로그인 상태 저장
      saveLoginState({ type: "counselor", phone: userData.phone });
      
      // 상담사의 링크 목록 로드 (LocalStorage - 링크 데이터는 기존 유지)
      const lr = storage.get("counselor_links_" + userData.phone);
      const links = lr ? JSON.parse(lr.value) : [];
      setGeneratedLinks(links);
      
      loadAllSubmitted();
      setView("counselorDashboard");
      setLoginMsg({ type: "", text: "" });
    } catch (error) {
      setLoginMsg({ type: "error", text: "서버 오류가 발생했습니다." });
    }
  }

  // 💬 AI 상담 채팅 함수
  // 검사 결과 요약 텍스트 생성 (채팅 컨텍스트용)
  function buildTestSummary(testType) {
    try {
      if (testType === 'SCT') {
        const cats = Object.keys(sctCategories);
        const sampleAnswers = cats.slice(0, 5).map(cat => {
          const nums = sctCategories[cat];
          const ans = nums.map(n => sctResponses[n] || '').filter(Boolean).slice(0, 2).join(' / ');
          return ans ? `${cat}: ${ans}` : null;
        }).filter(Boolean).join('\n');
        return `검사: 문장완성검사(SCT)\n주요 응답:\n${sampleAnswers}`;
      }
      if (testType === 'DSI') {
        const { total, areas } = calcDsi();
        const level = total >= 120 ? '높음' : total >= 80 ? '보통' : '낮음';
        const areaText = Object.entries(areas).map(([k,v]) => `${k}: ${v}/36`).join(', ');
        return `검사: 자아분화검사(DSI)\n총점: ${total}/180 (${level})\n영역별: ${areaText}`;
      }
      if (testType === 'PHQ9') {
        const r = calcPhq9();
        return `검사: PHQ-9 우울증 선별\n총점: ${r.total}/27 (${r.level})`;
      }
      if (testType === 'GAD7') {
        const r = calcGad7();
        return `검사: GAD-7 범불안장애\n총점: ${r.total}/21 (${r.level})`;
      }
      if (testType === 'DASS21') {
        const r = calcDass21();
        return `검사: DASS-21\n우울: ${r.depression.score}점(${r.depression.level}), 불안: ${r.anxiety.score}점(${r.anxiety.level}), 스트레스: ${r.stress.score}점(${r.stress.level})`;
      }
      if (testType === 'BIG5') {
        const r = calcBig5();
        const factors = Object.entries(r).map(([k,v]) => `${k}: ${v}`).join(', ');
        return `검사: Big5 성격검사\n요인별: ${factors}`;
      }
      if (testType === 'BURNOUT') {
        const r = calcBurnout();
        return `검사: K-MBI+ 번아웃\n총점: ${r.totalScore}/240 (${r.percentage}%, ${r.level})`;
      }
      if (testType === 'LOST') {
        const r = calcLost();
        const axisLabel = { E:"에너지", D:"의사결정", S:"행동속도", N:"안정성", R:"관계민감도", T:"스트레스반응" };
        const axisText = Object.entries(r.axisAvg).map(([k,v]) => `${axisLabel[k]}:${Number(v).toFixed(1)}`).join(', ');
        return `검사: LOST 행동 운영체계\n유형: ${r.typeInfo.name}(${r.typeCode})\n축별 평균: ${axisText}`;
      }
      return '검사 결과';
    } catch(e) {
      return '검사 결과';
    }
  }

  // 채팅 전송 함수
  async function sendChatMessage(testType) {
    const input = chatInput.trim();
    if (!input || chatStreaming) return;

    const counselingType = activeLinkData?.counselingType || 'psychological';
    const summary = buildTestSummary(testType);
    const userMsg = { role: 'user', content: input, id: Date.now() };

    setChatMessages(prev => [...prev, userMsg]);
    setChatInput('');
    setChatStreaming(true);
    setChatError('');

    const assistantId = Date.now() + 1;
    setChatMessages(prev => [...prev, { role: 'assistant', content: '', id: assistantId, streaming: true }]);

    try {
      const history = [...chatMessages, userMsg].map(m => ({ role: m.role, content: m.content }));
      const res = await fetch('/api/ai-chat', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          messages: history,
          testContext: { testType, counselingType, summary }
        })
      });

      if (!res.ok) {
        const err = await res.json().catch(() => ({}));
        throw new Error(err.error || '서버 오류');
      }

      const reader = res.body.getReader();
      const decoder = new TextDecoder();
      let buffer = '';
      let fullText = '';

      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        buffer += decoder.decode(value, { stream: true });
        const lines = buffer.split('\n');
        buffer = lines.pop();
        for (const line of lines) {
          if (!line.startsWith('data: ')) continue;
          const data = line.slice(6).trim();
          if (data === '[DONE]') break;
          try {
            const parsed = JSON.parse(data);
            if (parsed.type === 'content_block_delta' && parsed.delta?.text) {
              fullText += parsed.delta.text;
              setChatMessages(prev => prev.map(m =>
                m.id === assistantId ? { ...m, content: fullText } : m
              ));
            }
          } catch {}
        }
      }
      // 스트리밍 완료
      setChatMessages(prev => prev.map(m =>
        m.id === assistantId ? { ...m, streaming: false } : m
      ));
    } catch(e) {
      setChatError(e.message || 'AI 채팅 중 오류가 발생했습니다.');
      setChatMessages(prev => prev.filter(m => m.id !== assistantId));
    } finally {
      setChatStreaming(false);
    }
  }

  // 채팅 초기화
  function resetChat() {
    setChatMessages([]);
    setChatInput('');
    setChatError('');
    setChatStreaming(false);
  }

  // 채팅창 컴포넌트
  function ChatBox({ testType, initialPrompts }) {
    const messagesEndRef = React.useRef(null);
    const inputRef = React.useRef(null);
    React.useEffect(() => {
      messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
    }, [chatMessages]);

    return (
      <div className="mt-6 border-2 border-blue-200 rounded-xl overflow-hidden shadow-md">
        {/* 헤더 */}
        <div
          className="flex items-center justify-between px-4 py-3 bg-gradient-to-r from-blue-600 to-indigo-600 cursor-pointer"
          onClick={() => { if (!chatOpen) resetChat(); setChatOpen(v => !v); }}
        >
          <div className="flex items-center gap-2">
            <span className="text-white text-base">💬</span>
            <span className="text-white font-bold text-sm">AI 상담 대화</span>
            <span className="text-blue-200 text-xs">검사 결과 활용 방법을 AI와 상담하세요</span>
          </div>
          <div className="flex items-center gap-2">
            {chatMessages.length > 0 && (
              <span className="bg-white text-blue-700 text-xs px-2 py-0.5 rounded-full font-bold">
                {chatMessages.filter(m => m.role === 'user').length}회 대화
              </span>
            )}
            <span className="text-white text-sm">{chatOpen ? '▲' : '▼'}</span>
          </div>
        </div>

        {chatOpen && (
          <div className="bg-white">
            {/* 빠른 질문 버튼 */}
            {chatMessages.length === 0 && (
              <div className="p-4 border-b border-gray-100">
                <p className="text-xs text-gray-500 mb-2 font-semibold">💡 자주 묻는 질문</p>
                <div className="flex flex-wrap gap-2">
                  {(initialPrompts || []).map((prompt, i) => (
                    <button
                      key={i}
                      onClick={() => { 
                        // 빠른 질문 버튼: 즉시 전송 (chatInput 우회)
                        const userMsg = { role: 'user', content: prompt, id: Date.now() };
                        setChatMessages(prev => [...prev, userMsg]);
                        setChatStreaming(true);
                        setChatError('');
                        const counselingType = activeLinkData?.counselingType || 'psychological';
                        const summary = buildTestSummary(testType);
                        const assistantId = Date.now() + 1;
                        setChatMessages(prev => [...prev, { role: 'assistant', content: '', id: assistantId, streaming: true }]);
                        
                        fetch('/api/ai-chat', {
                          method: 'POST',
                          headers: { 'Content-Type': 'application/json' },
                          body: JSON.stringify({
                            messages: [...chatMessages, userMsg].map(m => ({ role: m.role, content: m.content })),
                            testContext: { testType, counselingType, summary }
                          })
                        })
                        .then(res => {
                          if (!res.ok) throw new Error('서버 오류');
                          const reader = res.body.getReader();
                          const decoder = new TextDecoder();
                          let buffer = '';
                          let fullText = '';
                          
                          function processStream() {
                            reader.read().then(({ done, value }) => {
                              if (done) {
                                setChatMessages(prev => prev.map(m =>
                                  m.id === assistantId ? { ...m, streaming: false } : m
                                ));
                                setChatStreaming(false);
                                return;
                              }
                              buffer += decoder.decode(value, { stream: true });
                              const lines = buffer.split('\n');
                              buffer = lines.pop();
                              for (const line of lines) {
                                if (!line.startsWith('data: ')) continue;
                                const data = line.slice(6).trim();
                                if (data === '[DONE]') break;
                                try {
                                  const parsed = JSON.parse(data);
                                  if (parsed.type === 'content_block_delta' && parsed.delta?.text) {
                                    fullText += parsed.delta.text;
                                    setChatMessages(prev => prev.map(m =>
                                      m.id === assistantId ? { ...m, content: fullText } : m
                                    ));
                                  }
                                } catch {}
                              }
                              processStream();
                            });
                          }
                          processStream();
                        })
                        .catch(e => {
                          setChatError(e.message || 'AI 채팅 중 오류가 발생했습니다.');
                          setChatMessages(prev => prev.filter(m => m.id !== assistantId));
                          setChatStreaming(false);
                        });
                      }}
                      className="text-xs bg-blue-50 text-blue-700 border border-blue-200 px-3 py-1.5 rounded-full hover:bg-blue-100 transition"
                    >
                      {prompt}
                    </button>
                  ))}
                </div>
              </div>
            )}

            {/* 메시지 목록 */}
            <div className="h-80 overflow-y-auto p-4 space-y-3 bg-gray-50">
              {chatMessages.length === 0 && (
                <div className="flex flex-col items-center justify-center h-full text-center">
                  <p className="text-4xl mb-3">🤝</p>
                  <p className="text-sm font-semibold text-gray-600">검사 결과에 대해 AI와 대화해 보세요</p>
                  <p className="text-xs text-gray-400 mt-1">상담 전략, 해석 방법, 활용 방안 등을 질문하세요</p>
                </div>
              )}
              {chatMessages.map(msg => (
                <div key={msg.id} className={`flex ${msg.role === 'user' ? 'justify-end' : 'justify-start'}`}>
                  {msg.role === 'assistant' && (
                    <div className="w-7 h-7 rounded-full bg-gradient-to-br from-blue-500 to-indigo-600 flex items-center justify-center text-white text-xs font-bold mr-2 mt-0.5 shrink-0">AI</div>
                  )}
                  <div className={`max-w-xs lg:max-w-md xl:max-w-lg px-4 py-2.5 rounded-2xl text-sm leading-relaxed ${
                    msg.role === 'user'
                      ? 'bg-blue-600 text-white rounded-tr-sm'
                      : 'bg-white border border-gray-200 text-gray-800 rounded-tl-sm shadow-sm'
                  }`}>
                    {msg.content
                      ? <p className="whitespace-pre-wrap">{msg.content}{msg.streaming && <span className="inline-block w-1.5 h-4 bg-blue-400 animate-pulse ml-0.5 align-middle rounded"></span>}</p>
                      : <div className="flex gap-1 items-center py-1">
                          <div className="w-2 h-2 bg-gray-400 rounded-full animate-bounce" style={{animationDelay:'0ms'}}></div>
                          <div className="w-2 h-2 bg-gray-400 rounded-full animate-bounce" style={{animationDelay:'150ms'}}></div>
                          <div className="w-2 h-2 bg-gray-400 rounded-full animate-bounce" style={{animationDelay:'300ms'}}></div>
                        </div>
                    }
                  </div>
                  {msg.role === 'user' && (
                    <div className="w-7 h-7 rounded-full bg-gray-200 flex items-center justify-center text-gray-600 text-xs font-bold ml-2 mt-0.5 shrink-0">나</div>
                  )}
                </div>
              ))}
              {chatError && (
                <div className="bg-red-50 border border-red-200 rounded-lg p-3 text-xs text-red-700">
                  ⚠️ {chatError}
                  <button onClick={() => setChatError('')} className="ml-2 underline">닫기</button>
                </div>
              )}
              <div ref={messagesEndRef} />
            </div>

            {/* 입력창 */}
            <div className="p-3 border-t border-gray-200 bg-white">
              <div className="flex gap-2 items-end">
                <textarea
                  ref={inputRef}
                  defaultValue={chatInput}
                  onKeyDown={e => {
                    // IME 조합 중이 아닐 때만 Enter 처리 (한글 입력 문제 해결)
                    if (e.key === 'Enter' && !e.shiftKey && !e.nativeEvent.isComposing) {
                      e.preventDefault();
                      const currentValue = inputRef.current?.value || '';
                      if (currentValue.trim()) {
                        // 직접 메시지 전송 (상태 우회)
                        const userMsg = { role: 'user', content: currentValue.trim(), id: Date.now() };
                        setChatMessages(prev => [...prev, userMsg]);
                        inputRef.current.value = '';
                        setChatStreaming(true);
                        setChatError('');
                        const counselingType = activeLinkData?.counselingType || 'psychological';
                        const summary = buildTestSummary(testType);
                        const assistantId = Date.now() + 1;
                        setChatMessages(prev => [...prev, { role: 'assistant', content: '', id: assistantId, streaming: true }]);
                        
                        fetch('/api/ai-chat', {
                          method: 'POST',
                          headers: { 'Content-Type': 'application/json' },
                          body: JSON.stringify({
                            messages: [...chatMessages, userMsg].map(m => ({ role: m.role, content: m.content })),
                            testContext: { testType, counselingType, summary }
                          })
                        })
                        .then(res => {
                          if (!res.ok) throw new Error('서버 오류');
                          const reader = res.body.getReader();
                          const decoder = new TextDecoder();
                          let buffer = '';
                          let fullText = '';
                          
                          processStream();
                        })
                        .catch(e => {
                          setChatError(e.message || 'AI 채팅 중 오류가 발생했습니다.');
                          setChatMessages(prev => prev.filter(m => m.id !== assistantId));
                          setChatStreaming(false);
                        });
                      }
                    }
                  }}
                  placeholder="검사 결과 활용 방법, 상담 전략 등을 질문하세요... (Enter 전송, Shift+Enter 줄바꿈)"
                  rows={2}
                  disabled={chatStreaming}
                  className="flex-1 px-3 py-2 border border-gray-200 rounded-xl text-sm resize-none focus:outline-none focus:border-blue-400 disabled:bg-gray-50"
                />
                <div className="flex flex-col gap-1.5">
                  <button
                    onClick={() => {
                      const currentValue = inputRef.current?.value || '';
                      if (currentValue.trim() && !chatStreaming) {
                        const userMsg = { role: 'user', content: currentValue.trim(), id: Date.now() };
                        setChatMessages(prev => [...prev, userMsg]);
                        inputRef.current.value = '';
                        setChatStreaming(true);
                        setChatError('');
                        const counselingType = activeLinkData?.counselingType || 'psychological';
                        const summary = buildTestSummary(testType);
                        const assistantId = Date.now() + 1;
                        setChatMessages(prev => [...prev, { role: 'assistant', content: '', id: assistantId, streaming: true }]);
                        
                        fetch('/api/ai-chat', {
                          method: 'POST',
                          headers: { 'Content-Type': 'application/json' },
                          body: JSON.stringify({
                            messages: [...chatMessages, userMsg].map(m => ({ role: m.role, content: m.content })),
                            testContext: { testType, counselingType, summary }
                          })
                        })
                        .then(res => {
                          if (!res.ok) throw new Error('서버 오류');
                          const reader = res.body.getReader();
                          const decoder = new TextDecoder();
                          let buffer = '';
                          let fullText = '';
                          
                          processStream();
                        })
                        .catch(e => {
                          setChatError(e.message || 'AI 채팅 중 오류가 발생했습니다.');
                          setChatMessages(prev => prev.filter(m => m.id !== assistantId));
                          setChatStreaming(false);
                        });
                      }
                    }}
                    disabled={chatStreaming}
                    className="bg-blue-600 text-white px-4 py-2 rounded-xl text-sm font-bold hover:bg-blue-700 disabled:opacity-40 disabled:cursor-not-allowed transition"
                  >
                    {chatStreaming ? '•••' : '전송'}
                  </button>
                  {chatMessages.length > 0 && (
                    <button
                      onClick={resetChat}
                      className="text-xs text-gray-400 hover:text-gray-600 text-center"
                    >초기화</button>
                  )}
                </div>
              </div>
            </div>
          </div>
        )}
      </div>
    );
  }

  // 📖 성경적 상담 참고자료 관리 함수
  async function loadBiblicalRefs() {
    try {
      const res = await fetch('/api/admin/biblical-references');
      const data = await res.json();
      if (data.success) setBiblicalRefs(data.data || []);
    } catch (e) { console.error('참고자료 로드 실패:', e); }
  }

  async function saveBiblicalRef() {
    if (!biblicalForm.title.trim() || !biblicalForm.content.trim()) {
      setBiblicalMsg({ type: 'error', text: '제목과 내용을 모두 입력해주세요.' });
      return;
    }
    setBiblicalLoading(true);
    setBiblicalMsg({ type: '', text: '' });
    try {
      const res = await fetch('/api/admin/biblical-references', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(biblicalForm)
      });
      const data = await res.json();
      if (data.success) {
        setBiblicalMsg({ type: 'success', text: '✅ ' + data.message });
        setBiblicalForm({ id: null, title: '', category: 'general', content: '', sort_order: 0 });
        setShowBiblicalForm(false);
        await loadBiblicalRefs();
      } else {
        setBiblicalMsg({ type: 'error', text: '❌ ' + (data.error || '저장 실패') });
      }
    } catch (e) {
      setBiblicalMsg({ type: 'error', text: '❌ 서버 오류: ' + e.message });
    } finally {
      setBiblicalLoading(false);
    }
  }

  async function deleteBiblicalRef(id, title) {
    if (!confirm(`"${title}" 자료를 삭제하시겠습니까?`)) return;
    try {
      const res = await fetch(`/api/admin/biblical-references/${id}`, { method: 'DELETE' });
      const data = await res.json();
      if (data.success) {
        setBiblicalMsg({ type: 'success', text: '✅ 삭제되었습니다.' });
        await loadBiblicalRefs();
      }
    } catch (e) {
      setBiblicalMsg({ type: 'error', text: '❌ 삭제 실패' });
    }
  }

  async function toggleBiblicalRef(id) {
    try {
      await fetch(`/api/admin/biblical-references/${id}/toggle`, { method: 'PATCH' });
      await loadBiblicalRefs();
    } catch (e) { console.error('토글 실패:', e); }
  }

  function editBiblicalRef(ref) {
    setBiblicalForm({ id: ref.id, title: ref.title, category: ref.category, content: ref.content, sort_order: ref.sort_order || 0 });
    setShowBiblicalForm(true);
    setBiblicalMsg({ type: '', text: '' });
    window.scrollTo({ top: 0, behavior: 'smooth' });
  }

  function handleBiblicalFileUpload(e) {
    const file = e.target.files[0];
    if (!file) return;
    if (file.size > 500000) {
      setBiblicalMsg({ type: 'error', text: '❌ 파일 크기는 500KB 이내여야 합니다.' });
      return;
    }
    const reader = new FileReader();
    reader.onload = (ev) => {
      const text = ev.target.result;
      setBiblicalForm(f => ({
        ...f,
        title: f.title || file.name.replace(/\.[^.]+$/, ''),
        content: text
      }));
      setBiblicalMsg({ type: 'success', text: `✅ "${file.name}" 파일 불러오기 완료. 내용 확인 후 저장하세요.` });
    };
    reader.readAsText(file, 'UTF-8');
    e.target.value = '';
  }

  // ✅ 컴포넌트 마운트 시 데이터 로드 및 로그인 상태 복원
  useEffect(() => {
    const init = async () => {
      try {
      // 🕐 만료된 검사 결과 자동 삭제 (최우선)
      try { checkAndCleanExpiredSessions(); } catch(e) { console.error('세션 정리 오류:', e); }
      
      // ✅ 로그인 상태 복원
      const restored = await restoreLoginState();
      if (restored) {
      } else {
      }
      
      // 디버깅: LocalStorage 키 확인
      const keys = Object.keys(localStorage);
      console.log('[디버깅] LocalStorage 키:', keys.filter(k => 
        k.includes('counselor') || k.includes('submitted') || k.includes('link_') || k.includes('session_') || k.includes('login')
      ));
      
      // 승인된 상담사 수 확인
      const approvedData = storage.get("approved_counselors");
      if (approvedData) {
        const approved = JSON.parse(approvedData.value);
      }
      
      // 대기 중인 상담사 수 확인
      const pendingData = storage.get("counselor_requests");
      if (pendingData) {
        const pending = JSON.parse(pendingData.value).filter(c => c.status === "pending");
      }
      
      // 📖 성경적 참고자료 로드 (관리자만)
      if (isAdmin) {
        try { await loadBiblicalRefs(); } catch(e) {}
      }
      } catch(e) { console.error('[앱 초기화 오류]', e); }
    };
    
    init().catch(e => console.error('[init 오류]', e));
    
    // 제출된 검사 수 확인
    const submittedData = storage.get("submitted_list");
    if (submittedData) {
      const submitted = JSON.parse(submittedData.value);
    }
    
    
    // 🔄 1분마다 만료 체크 (백그라운드)
    const intervalId = setInterval(() => {
      checkAndCleanExpiredSessions();
    }, 60000); // 1분
    
    return () => clearInterval(intervalId);
  }, []); // 한 번만 실행

  useEffect(() => {
    if (isCounselor && counselorPhone) {
      storage.set("counselor_links_" + counselorPhone, JSON.stringify(generatedLinks));
    }
  }, [generatedLinks, isCounselor, counselorPhone]);

  async function counselorSignup() {
    if (!counselorForm.phone || !counselorForm.password || !counselorForm.name) {
      setFormMsg({ type: "error", text: "이름, 전화번호, 비밀번호는 필수입니다." });
      return;
    }
    
    setFormMsg({ type: "info", text: "가입 신청 중..." });
    
    try {
      // D1 API로 상담사 가입 (비밀번호 포함)
      const result = await api.registerCounselor(
        counselorForm.phone, 
        counselorForm.name,
        'psychological', // 기본값
        counselorForm.password
      );
      
      if (result.success) {
        // ✅ 비밀번호는 D1에 해시로 저장됨 - LocalStorage 저장 제거
        setFormMsg({ type: "success", text: "가입 신청 완료! 관리자 승인 후 로그인 가능합니다. (무료 5회 체험 제공)" });
        setCounselorForm({ name: "", phone: "", password: "", certification: "", education: "", experience: "" });
        
        setTimeout(() => {
          setView("counselorLogin");
          setFormMsg({ type: "", text: "" });
        }, 3000);
      } else {
        setFormMsg({ type: "error", text: result.error || "가입 신청 실패" });
      }
    } catch (error) {
      setFormMsg({ type: "error", text: "서버 오류가 발생했습니다." });
    }
  }

  async function approveCounselor(phone) {
    
    try {
      // D1 API로 승인
      const result = await api.approveCounselor(phone);
      
      if (result.success) {
        
        // 대기 중인 상담사 목록 새로고침
        const pendingResult = await api.getPendingCounselors();
        if (pendingResult.success) {
          setPendingCounselors(pendingResult.data);
        }
        
        // 승인된 상담사 목록 새로고침
        const approvedResult = await api.getApprovedCounselors();
        if (approvedResult.success) {
          setApprovedCounselors(approvedResult.data);
        }
        
        // 확인 메시지
        alert(`✅ ${phone} 상담사가 승인되었습니다! (무료 5회 체험 제공)`);
      } else {
        alert('❌ 승인 실패: ' + result.error);
      }
    } catch (error) {
      alert('❌ 서버 오류가 발생했습니다.');
    }
  }

  // 🔢 쿼터 수정 시작
  function startEditQuota(phone, currentQuota) {
    setQuotaEditingPhone(phone);
    setQuotaEditingValue(currentQuota.toString());
  }

  // 🔢 쿼터 수정 취소
  function cancelEditQuota() {
    setQuotaEditingPhone(null);
    setQuotaEditingValue('');
  }

  // 🔢 쿼터 수정 저장
  async function saveQuotaEdit(phone, name) {
    const newQuota = parseInt(quotaEditingValue, 10);
    
    // 유효성 검사
    if (isNaN(newQuota) || newQuota < 0) {
      alert('❌ 쿼터는 0 이상의 숫자여야 합니다.');
      return;
    }
    
    
    try {
      const result = await api.updateCounselorQuota(phone, newQuota);
      
      if (result.success) {
        
        // 승인된 상담사 목록 새로고침
        const approvedResult = await api.getApprovedCounselors();
        if (approvedResult.success) {
          setApprovedCounselors(approvedResult.data);
        }
        
        // 편집 모드 종료
        setQuotaEditingPhone(null);
        setQuotaEditingValue('');
        
        // 확인 메시지
        alert(`✅ ${name}(${phone}) 상담사의 쿼터가 ${newQuota}회로 변경되었습니다.\n남은 쿼터: ${result.data.quotaRemaining}회`);
      } else {
        alert('❌ 쿼터 변경 실패: ' + result.error);
      }
    } catch (error) {
      alert('❌ 서버 오류가 발생했습니다.');
    }
  }

  async function approveCounselor_OLD(phone) {
    
    try {
      // D1 API로 승인
      const result = await api.approveCounselor(phone);
      
      if (result.success) {
        
        // 대기 중인 상담사 목록 새로고침
        const pendingResult = await api.getPendingCounselors();
        if (pendingResult.success) {
          setPendingCounselors(pendingResult.data);
        }
        
        // 승인된 상담사 목록 새로고침
        const approvedResult = await api.getApprovedCounselors();
        if (approvedResult.success) {
          setApprovedCounselors(approvedResult.data);
        }
        
        // 확인 메시지
        alert(`✅ ${phone} 상담사가 승인되었습니다! (무료 5회 체험 제공)`);
      } else {
        alert('❌ 승인 실패: ' + result.error);
      }
    } catch (error) {
      alert('❌ 서버 오류가 발생했습니다.');
    }
  }
  
  async function rejectCounselor(phone) {
    
    // TODO: 거부 API 구현 필요 (현재는 LocalStorage 사용)
    const r = storage.get("counselor_requests");
    let list = r ? JSON.parse(r.value) : [];
    list = list.filter(c => c.phone !== phone);
    storage.set("counselor_requests", JSON.stringify(list));
    setPendingCounselors(list.filter(c => c.status === "pending"));
    
    alert(`❌ ${phone} 상담사를 거부했습니다.`);
  }


  // ===================================================
  // 멀티 검사 진행 헬퍼: 현재 검사 저장 후 다음으로 이동
  // ===================================================
  function advanceToNextTest(currentTestType, sessionData) {
    storeSession(sessionData);
    const completedIds = [...multiSessionIds, sessionData.sessionId];
    setMultiSessionIds(completedIds);
    const nextIndex = currentTestIndex + 1;
    if (nextIndex < pendingTests.length) {
      setCurrentTestIndex(nextIndex);
      const nextType = pendingTests[nextIndex];
      const newSessionId = genId("session");
      setSessionId(newSessionId);
      setSctResponses({}); setSctSummaries({});
      setDsiResponses({}); setDsiRec("");
      setPhq9Responses({}); setGad7Responses({});
      setDass21Responses({}); setBig5Responses({});
      setBurnoutResponses({}); setLostResponses({}); setSaveStatus("");
      const testViews = { "SCT":"sctTest","DSI":"dsiTest","PHQ9":"phq9Test","GAD7":"gad7Test","DASS21":"dass21Test","BIG5":"big5Test","BURNOUT":"burnoutTest","LOST":"lostTest" };
      const testViews2 = { "SCT":"sctTest","DSI":"dsiTest","PHQ9":"phq9Test","GAD7":"gad7Test","DASS21":"dass21Test","BIG5":"big5Test","BURNOUT":"burnoutTest","LOST":"lostTest" };
      setView(testViews2[nextType] || "sctTest");
    } else {
      if (activeLinkId) {
        const ld = loadLink(activeLinkId);
        if (ld) { ld.status = "completed"; ld.completedSessionIds = completedIds; storeLink(ld); setGeneratedLinks(prev => prev.map(l => l.linkId === activeLinkId ? { ...l, status: "completed" } : l)); }
      }
      setView("complete");
    }
  }

  function submitSct() {
    const missing = Object.keys(sctQ).filter(n => !sctResponses[n]?.trim());
    if (missing.length > 0) {
      setSaveStatus("⚠️ " + missing.length + "개 문항이 비어 있습니다.");
      return;
    }
    const data = {
      sessionId, testType: "SCT",
      responses: sctResponses, summaries: sctSummaries,
      createdAt: new Date().toISOString(),
      userPhone: userInfo.phone || "미확인", linkId: activeLinkId || null
    };
    advanceToNextTest("SCT", data);
  }
  
  function submitDsi() {
    if (Object.keys(dsiResponses).length < 36) {
      setSaveStatus("⚠️ " + (36 - Object.keys(dsiResponses).length) + "개 문항이 남아있습니다.");
      return;
    }
    const data = {
      sessionId, testType: "DSI",
      responses: dsiResponses,
      createdAt: new Date().toISOString(),
      userPhone: userInfo.phone || "미확인", linkId: activeLinkId || null
    };
    advanceToNextTest("DSI", data);
  }

  // PHQ-9 제출 함수
  function submitPhq9() {
    if (Object.keys(phq9Responses).length < 9) {
      setSaveStatus("⚠️ " + (9 - Object.keys(phq9Responses).length) + "개 문항이 남아있습니다.");
      return;
    }
    const data = {
      sessionId, testType: "PHQ9",
      responses: phq9Responses,
      createdAt: new Date().toISOString(),
      userPhone: userInfo.phone || "미확인", linkId: activeLinkId || null
    };
    advanceToNextTest("PHQ9", data);
  }

  // GAD-7 제출 함수
  function submitGad7() {
    if (Object.keys(gad7Responses).length < 7) {
      setSaveStatus("⚠️ " + (7 - Object.keys(gad7Responses).length) + "개 문항이 남아있습니다.");
      return;
    }
    const data = {
      sessionId, testType: "GAD7",
      responses: gad7Responses,
      createdAt: new Date().toISOString(),
      userPhone: userInfo.phone || "미확인", linkId: activeLinkId || null
    };
    advanceToNextTest("GAD7", data);
  }

  // DASS-21 제출 함수
  function submitDass21() {
    if (Object.keys(dass21Responses).length < 21) {
      setSaveStatus("⚠️ " + (21 - Object.keys(dass21Responses).length) + "개 문항이 남아있습니다.");
      return;
    }
    const data = {
      sessionId, testType: "DASS21",
      responses: dass21Responses,
      createdAt: new Date().toISOString(),
      userPhone: userInfo.phone || "미확인", linkId: activeLinkId || null
    };
    advanceToNextTest("DASS21", data);
  }

  // Big5 제출 함수
  function submitBig5() {
    if (Object.keys(big5Responses).length < 50) {
      setSaveStatus("⚠️ " + (50 - Object.keys(big5Responses).length) + "개 문항이 남아있습니다.");
      return;
    }
    const data = {
      sessionId, testType: "BIG5",
      responses: big5Responses,
      createdAt: new Date().toISOString(),
      userPhone: userInfo.phone || "미확인", linkId: activeLinkId || null
    };
    advanceToNextTest("BIG5", data);
  }

  function submitBurnout() {
    if (Object.keys(burnoutResponses).length < 50) {
      setSaveStatus("⚠️ " + (50 - Object.keys(burnoutResponses).length) + "개 문항이 남아있습니다.");
      return;
    }
    const data = {
      sessionId, testType: "BURNOUT",
      responses: burnoutResponses,
      createdAt: new Date().toISOString(),
      userPhone: userInfo.phone || "미확인", linkId: activeLinkId || null
    };
    advanceToNextTest("BURNOUT", data);
  }

  function submitLost() {
    if (Object.keys(lostResponses).length < 60) {
      setSaveStatus("⚠️ " + (60 - Object.keys(lostResponses).length) + "개 문항이 남아있습니다.");
      return;
    }
    const data = {
      sessionId, testType: "LOST",
      responses: lostResponses,
      createdAt: new Date().toISOString(),
      userPhone: userInfo.phone || "미확인", linkId: activeLinkId || null
    };
    advanceToNextTest("LOST", data);
  }

  function viewSession(sid, returnDataOnly = false) {
    
    const r = storage.get("session_" + sid);
    if (!r) {
      return null;
    }
    
    const data = JSON.parse(r.value);
    
    // PDF 생성을 위해 데이터만 반환하는 경우
    if (returnDataOnly) {
      return data;
    }
    
    // linkId가 있으면 링크 데이터 복원 (상담 유형 정보 포함)
    if (data.linkId) {
      const linkData = loadLink(data.linkId);
      if (linkData) {
        setActiveLinkData(linkData);
      }
    }
    
    // 일반 뷰어 모드
    if (data.testType === "SCT") {
      setSctResponses(data.responses || {});
      setSctSummaries(data.summaries || {});
    } else if (data.testType === "DSI") {
      setDsiResponses(data.responses || {});
      setDsiRec(data.recommendation || "");
    } else if (data.testType === "PHQ9") {
      setPhq9Responses(data.responses || {});
    } else if (data.testType === "GAD7") {
      setGad7Responses(data.responses || {});
    } else if (data.testType === "DASS21") {
      setDass21Responses(data.responses || {});
    } else if (data.testType === "BIG5") {
      setBig5Responses(data.responses || {});
    } else if (data.testType === "BURNOUT") {
      setBurnoutResponses(data.responses || {});
    } else if (data.testType === "LOST") {
      setLostResponses(data.responses || {});
    }
    
    setSessionId(sid);
    setUserInfo({ phone: data.userPhone || "", password: "" });
    
    // 검사 유형에 따라 결과 화면 설정
    const resultViews = {
      "SCT": "sctResult",
      "DSI": "dsiResult",
      "PHQ9": "phq9Result",
      "GAD7": "gad7Result",
      "DASS21": "dass21Result",
      "BIG5": "big5Result",
      "BURNOUT": "burnoutResult",
      "LOST": "lostResult"
    };
    const targetView = resultViews[data.testType] || "sctResult";
    setView(targetView);
    
    return data;
  }

  // ═══════════════════════════════════════════════════════
  // 🔑 API 설정 관리 함수 (관리자 전용)
  // ═══════════════════════════════════════════════════════

  // API 설정 목록 로드
  async function loadApiSettings() {
    try {
      const res = await fetch('/api/admin/api-settings');
      const data = await res.json();
      if (data.success) setApiSettings(data.data || []);
    } catch (e) {
    }
  }

  // API 키 저장
  async function saveApiSetting() {
    if (!apiSettingForm.key_value.trim()) {
      setApiSettingMsg({ type: 'error', text: 'API 키를 입력해주세요.' });
      return;
    }
    setApiSettingLoading(true);
    setApiSettingMsg({ type: '', text: '' });
    setApiTestResult({ type: '', text: '' });
    try {
      const res = await fetch('/api/admin/api-settings', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(apiSettingForm)
      });
      const data = await res.json();
      if (data.success) {
        setApiSettingMsg({ type: 'success', text: '✅ ' + data.message });
        setApiSettingForm(f => ({ ...f, key_value: '' }));
        setShowApiKeyInput(false);
        await loadApiSettings();
      } else {
        setApiSettingMsg({ type: 'error', text: '❌ ' + (data.error || '저장 실패') });
      }
    } catch (e) {
      setApiSettingMsg({ type: 'error', text: '❌ 서버 오류: ' + e.message });
    } finally {
      setApiSettingLoading(false);
    }
  }

  // API 키 연결 테스트
  async function testApiConnection() {
    setApiTestLoading(true);
    setApiTestResult({ type: '', text: '' });
    try {
      const res = await fetch('/api/admin/api-settings/test', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          key_name: apiSettingForm.key_name,
          key_value: apiSettingForm.key_value || undefined
        })
      });
      const data = await res.json();
      setApiTestResult({
        type: data.success ? 'success' : 'error',
        text: data.success ? data.message : '❌ ' + (data.error || '연결 실패')
      });
    } catch (e) {
      setApiTestResult({ type: 'error', text: '❌ 서버 오류: ' + e.message });
    } finally {
      setApiTestLoading(false);
    }
  }

  // API 키 비활성화
  async function deactivateApiKey(keyName) {
    if (!confirm(`${keyName} 키를 비활성화하시겠습니까?\nAI 분석 기능이 중단됩니다.`)) return;
    try {
      const res = await fetch(`/api/admin/api-settings/${keyName}`, { method: 'DELETE' });
      const data = await res.json();
      if (data.success) {
        setApiSettingMsg({ type: 'success', text: '✅ ' + data.message });
        await loadApiSettings();
      }
    } catch (e) {
      setApiSettingMsg({ type: 'error', text: '❌ 비활성화 실패' });
    }
  }

  // ═══════════════════════════════════════════════════════
  // 🤖 AI 실시간 분석 (Claude API 스트리밍) - 공통 함수
  // ═══════════════════════════════════════════════════════
  async function runAiAnalysis(key, testType, responses, category) {
    const counselingType = activeLinkData?.counselingType || "psychological";
    const isFree = !subscription || subscription.subscription_type === "free";

    // ── 플랜별 사용 제한 체크 ──────────────────────────────
    if (isFree) {
      if (aiUsageCount >= FREE_AI_LIMIT) {
        // 5회 초과 → 에러 상태로 업그레이드 유도
        setAiError(p => ({ ...p, [key]: "UPGRADE_REQUIRED" }));
        return;
      }
      // 무료 플랜 횟수 차감 & 저장
      const newCount = aiUsageCount + 1;
      setAiUsageCount(newCount);
      if (counselorPhone) {
        localStorage.setItem("ai_usage_" + counselorPhone, String(newCount));
      }
    }
    // ────────────────────────────────────────────────────────

    setAiLoading(p => ({ ...p, [key]: true }));
    setAiError(p => ({ ...p, [key]: "" }));
    setAiAnalysis(p => ({ ...p, [key]: "" }));
    try {
      const res = await fetch("/api/ai-analyze", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ testType, counselingType, responses, category })
      });
      if (!res.ok) {
        const err = await res.json().catch(() => ({}));
        throw new Error(err.error || "서버 오류가 발생했습니다.");
      }
      const reader = res.body.getReader();
      const decoder = new TextDecoder();
      let buffer = "";
      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        buffer += decoder.decode(value, { stream: true });
        const lines = buffer.split("\n");
        buffer = lines.pop();
        for (const line of lines) {
          if (!line.startsWith("data: ")) continue;
          const data = line.slice(6).trim();
          if (data === "[DONE]") break;
          try {
            const parsed = JSON.parse(data);
            if (parsed.type === "content_block_delta" && parsed.delta?.text) {
              setAiAnalysis(p => ({ ...p, [key]: (p[key] || "") + parsed.delta.text }));
            }
          } catch {}
        }
      }
    } catch (e) {
      setAiError(p => ({ ...p, [key]: e.message || "AI 분석 중 오류가 발생했습니다." }));
    } finally {
      setAiLoading(p => ({ ...p, [key]: false }));
    }
  }

  // AI 분석 결과 박스 컴포넌트 (인라인)
  function AiAnalysisBox({ aiKey, onRun }) {
    const text = aiAnalysis[aiKey] || "";
    const loading = aiLoading[aiKey] || false;
    const error = aiError[aiKey] || "";
    const done = !loading && text.length > 0;

    const isFree = !subscription || subscription.subscription_type === "free";
    const remainingFree = Math.max(0, FREE_AI_LIMIT - aiUsageCount);

    // ── 유료 플랜 업그레이드 유도 (5회 초과) ──────────────
    if (error === "UPGRADE_REQUIRED") {
      return (
        <div className="mt-4 bg-gradient-to-r from-amber-50 to-orange-50 border-2 border-amber-300 rounded-xl p-5">
          <div className="flex items-start gap-3">
            <span className="text-2xl">🔒</span>
            <div className="flex-1">
              <p className="font-bold text-amber-800 text-sm mb-1">무료 AI 분석 횟수를 모두 사용했습니다</p>
              <p className="text-xs text-amber-700 mb-3">
                무료 플랜은 AI 실시간 분석을 <strong>{FREE_AI_LIMIT}회</strong>까지 제공합니다.<br/>
                유료 플랜으로 업그레이드하면 <strong>무제한</strong>으로 사용할 수 있습니다.
              </p>
              <div className="flex gap-2">
                <button
                  onClick={() => setView("pricingPlans")}
                  className="bg-amber-500 hover:bg-amber-600 text-white px-4 py-2 rounded-lg text-xs font-bold transition shadow"
                >
                  💎 플랜 업그레이드
                </button>
              </div>
            </div>
          </div>
        </div>
      );
    }

    // ── 버튼 영역 ─────────────────────────────────────────
    const showButton = !text && !loading && !error;

    return (
      <div className="mt-4">
        {showButton && (
          <div className="flex items-center gap-3">
            <button
              onClick={onRun}
              className="flex items-center gap-2 bg-gradient-to-r from-violet-600 to-indigo-600 text-white px-4 py-2 rounded-lg text-sm font-bold hover:from-violet-700 hover:to-indigo-700 transition shadow"
            >
              ✨ AI 실시간 분석
            </button>
            {/* 무료 플랜 잔여 횟수 배지 */}
            {isFree && (
              <span className={`text-xs px-2.5 py-1 rounded-full font-semibold ${
                remainingFree <= 1
                  ? "bg-red-100 text-red-700"
                  : remainingFree <= 3
                  ? "bg-amber-100 text-amber-700"
                  : "bg-green-100 text-green-700"
              }`}>
                무료 {remainingFree}회 남음
              </span>
            )}
          </div>
        )}

        {/* 로딩 중 */}
        {loading && (
          <div className="bg-violet-50 border border-violet-200 rounded-xl p-4">
            <div className="flex items-center gap-2 mb-2">
              <div className="w-2 h-2 bg-violet-500 rounded-full animate-bounce" style={{animationDelay:"0ms"}}></div>
              <div className="w-2 h-2 bg-violet-500 rounded-full animate-bounce" style={{animationDelay:"150ms"}}></div>
              <div className="w-2 h-2 bg-violet-500 rounded-full animate-bounce" style={{animationDelay:"300ms"}}></div>
              <span className="text-xs text-violet-600 font-semibold">AI가 실시간으로 분석 중...</span>
            </div>
            {text && (
              <p className="text-sm text-violet-800 whitespace-pre-wrap leading-relaxed">{text}<span className="inline-block w-1 h-4 bg-violet-500 animate-pulse ml-0.5 align-middle"></span></p>
            )}
          </div>
        )}

        {/* 분석 완료 */}
        {done && (
          <div className="bg-gradient-to-br from-violet-50 to-indigo-50 border border-violet-200 rounded-xl p-4 shadow-sm">
            <div className="flex items-center justify-between mb-2">
              <div className="flex items-center gap-1.5">
                <span className="text-base">✨</span>
                <p className="text-xs font-bold text-violet-700">AI 실시간 분석 결과</p>
              </div>
              <button
                onClick={() => setAiAnalysis(p => ({ ...p, [aiKey]: "" }))}
                className="text-xs text-violet-400 hover:text-violet-600"
              >다시 분석</button>
            </div>
            <p className="text-sm text-gray-700 whitespace-pre-wrap leading-relaxed">{text}</p>
          </div>
        )}

        {/* 일반 에러 */}
        {error && error !== "UPGRADE_REQUIRED" && (
          <div className="bg-red-50 border border-red-200 rounded-xl p-4">
            <p className="text-xs font-bold text-red-600 mb-1">⚠️ 오류</p>
            <p className="text-sm text-red-700">{error}</p>
            <button onClick={onRun} className="mt-2 text-xs text-red-600 underline hover:text-red-800">다시 시도</button>
          </div>
        )}
      </div>
    );
  }

  // ✅ SCT AI 권장사항 생성 (룰 기반 - 상담 유형별)
  function generateSctRecommendation(cat, nums) {
    
    // 응답 수집
    const responses = nums.map(n => ({
      question: sctQ[n],
      answer: sctResponses[n] || "(미응답)"
    }));
    
    // 키워드 분석
    const allText = responses.map(r => r.answer).join(" ").toLowerCase();
    
    // 상담 유형에 따라 분석 분기
    let analysis = "";
    let recommendations = [];
    
    if (counselingType === "biblical") {
      // 🕊️ 성경적 상담 분석
      analysis = generateBiblicalSctAnalysis(cat, allText);
      recommendations = generateBiblicalSctRecommendations(cat, allText);
    } else {
      // 🧠 심리상담 분석 (기존 로직)
      analysis = generatePsychologicalSctAnalysis(cat, allText);
      recommendations = generatePsychologicalSctRecommendations(allText);
    }
    
    const finalSummary = analysis + (recommendations.length > 0 ? "\n\n[권장사항]\n" + recommendations.join("\n") : "");
    
    setTimeout(() => {
      setSctSummaries(p => ({ ...p, [cat]: finalSummary }));
      setLoadingSummary(p => ({ ...p, [cat]: false }));
    }, 800);
  }

  // 🧠 심리상담 SCT 분석
  function generatePsychologicalSctAnalysis(cat, allText) {
    let analysis = "";
    
    if (cat.includes("어머니")) {
      if (allText.includes("좋") || allText.includes("사랑") || allText.includes("따뜻")) {
        analysis = "어머니와의 관계가 긍정적으로 형성되어 있습니다. 애착 관계가 안정적이며, 이는 대인관계 형성의 긍정적 기반이 됩니다.";
      } else if (allText.includes("힘들") || allText.includes("어렵") || allText.includes("갈등")) {
        analysis = "어머니와의 관계에서 일부 어려움이 관찰됩니다. 이는 정서적 지지 체계 강화가 필요함을 시사합니다. 상담을 통한 관계 개선이 도움이 될 수 있습니다.";
      } else {
        analysis = "어머니와의 관계에 대한 복합적인 감정이 나타납니다. 애착 패턴을 탐색하고 긍정적 측면을 강화하는 것이 도움이 될 수 있습니다.";
      }
    } else if (cat.includes("아버지")) {
      if (allText.includes("존경") || allText.includes("좋") || allText.includes("따뜻")) {
        analysis = "아버지와의 관계가 긍정적입니다. 권위 인물에 대한 건강한 태도가 형성되어 있으며, 이는 사회적응에 긍정적 영향을 줍니다.";
      } else if (allText.includes("무섭") || allText.includes("엄격") || allText.includes("거리")) {
        analysis = "아버지와의 관계에서 심리적 거리감이 느껴집니다. 권위에 대한 양가감정이 있을 수 있으며, 이는 상담을 통해 탐색할 필요가 있습니다.";
      } else {
        analysis = "아버지 상에 대한 다층적인 인식이 나타납니다. 권위 관계에 대한 이해를 심화하는 것이 성장에 도움이 될 수 있습니다.";
      }
    } else if (cat.includes("가족")) {
      if (allText.includes("화목") || allText.includes("행복") || allText.includes("사랑")) {
        analysis = "가족 관계가 전반적으로 긍정적입니다. 안정적인 가족 기반은 심리적 안녕감의 중요한 자원입니다.";
      } else if (allText.includes("갈등") || allText.includes("힘들") || allText.includes("불화")) {
        analysis = "가족 내 역동에 어려움이 있는 것으로 보입니다. 가족 상담이나 의사소통 개선이 도움이 될 수 있습니다.";
      } else {
        analysis = "가족 관계에 대한 복합적 인식이 나타납니다. 가족 내 자신의 역할과 위치를 재정립하는 것이 도움이 될 수 있습니다.";
      }
    } else if (cat.includes("두려움")) {
      if (allText.includes("없") || allText.includes("괜찮")) {
        analysis = "불안 수준이 낮고 심리적 안정감이 양호합니다. 현재의 대처 방식을 유지하는 것이 좋습니다.";
      } else if (allText.includes("실패") || allText.includes("거절") || allText.includes("혼자")) {
        analysis = "특정 영역에 대한 불안감이 관찰됩니다. 이는 자존감과 연결될 수 있으며, 인지행동치료적 접근이 도움이 될 수 있습니다.";
      } else {
        analysis = "다양한 두려움 요인이 나타납니다. 불안 관리 기법을 학습하고 대처 자원을 강화하는 것이 권장됩니다.";
      }
    } else if (cat.includes("죄책감")) {
      if (allText.includes("없") || allText.includes("후회")) {
        analysis = "죄책감이 적절한 수준으로 관리되고 있습니다. 자기 성찰 능력이 있으나 과도하지 않습니다.";
      } else if (allText.includes("많") || allText.includes("미안") || allText.includes("잘못")) {
        analysis = "죄책감 수준이 다소 높게 나타납니다. 자기 비난 패턴을 탐색하고 자기 용서를 연습하는 것이 도움이 될 수 있습니다.";
      } else {
        analysis = "죄책감에 대한 복합적 인식이 나타납니다. 과거 경험을 재해석하고 수용하는 과정이 필요할 수 있습니다.";
      }
    } else if (cat.includes("능력")) {
      if (allText.includes("잘") || allText.includes("자신") || allText.includes("능력")) {
        analysis = "자기 효능감이 양호합니다. 자신의 능력에 대한 긍정적 인식은 목표 달성의 중요한 자원입니다.";
      } else if (allText.includes("부족") || allText.includes("못") || allText.includes("없")) {
        analysis = "자기 효능감이 다소 낮게 나타납니다. 작은 성공 경험을 축적하고 강점을 재발견하는 것이 도움이 될 수 있습니다.";
      } else {
        analysis = "자기 능력에 대한 현실적 평가가 나타납니다. 강점을 더욱 발전시키고 약점을 보완하는 균형적 접근이 권장됩니다.";
      }
    } else if (cat.includes("미래")) {
      if (allText.includes("밝") || allText.includes("희망") || allText.includes("기대")) {
        analysis = "미래에 대한 낙관적 태도가 나타납니다. 긍정적 미래 전망은 현재의 동기와 에너지를 높입니다.";
      } else if (allText.includes("불안") || allText.includes("걱정") || allText.includes("어두")) {
        analysis = "미래에 대한 불안감이 관찰됩니다. 구체적 목표 설정과 단계적 계획이 불안을 감소시킬 수 있습니다.";
      } else {
        analysis = "미래에 대한 현실적 태도가 나타납니다. 희망과 준비를 균형있게 유지하는 것이 중요합니다.";
      }
    } else if (cat.includes("목표")) {
      if (allText.includes("명확") || allText.includes("계획") || allText.includes("꿈")) {
        analysis = "목표가 명확하고 동기 수준이 양호합니다. 구체적 실행 계획을 수립하면 목표 달성 가능성이 높습니다.";
      } else if (allText.includes("모르") || allText.includes("없") || allText.includes("막연")) {
        analysis = "목표가 불명확한 상태입니다. 자기 탐색을 통해 가치관과 방향성을 명료화하는 것이 필요합니다.";
      } else {
        analysis = "목표에 대한 탐색 과정에 있습니다. 다양한 가능성을 열어두고 점진적으로 방향을 설정하는 것이 도움이 됩니다.";
      }
    } else {
      analysis = "이 영역에 대한 응답을 종합적으로 분석한 결과, 개인의 고유한 경험과 인식이 반영되어 있습니다. 상담을 통해 더 깊이 탐색할 수 있습니다.";
    }
    
    return analysis;
  }
  
  // 🧠 심리상담 SCT 권장사항
  function generatePsychologicalSctRecommendations(allText) {
    const recommendations = [];
    if (allText.includes("힘들") || allText.includes("어렵") || allText.includes("갈등")) {
      recommendations.push("• 정기적인 심리 상담을 통한 감정 표현 및 해소");
      recommendations.push("• 인지행동치료(CBT) 기법을 통한 사고 패턴 개선");
    }
    if (allText.includes("불안") || allText.includes("걱정") || allText.includes("두렵")) {
      recommendations.push("• 이완 훈련 및 마음챙김 명상 실천");
      recommendations.push("• 불안 관리 기법 학습 (복식호흡, 점진적 근육 이완)");
    }
    if (allText.includes("없") || allText.includes("모르")) {
      recommendations.push("• 자기 탐색 활동 및 가치관 명료화 작업");
      recommendations.push("• 진로 상담 및 심리검사를 통한 자기 이해");
    }
    if (allText.includes("우울") || allText.includes("슬프") || allText.includes("의욕")) {
      recommendations.push("• 우울감 관리를 위한 행동 활성화 전략");
      recommendations.push("• 규칙적인 운동과 충분한 수면");
    }
    return recommendations;
  }
  
  // 🕊️ 성경적 상담 SCT 분석
  function generateBiblicalSctAnalysis(cat, allText) {
    let analysis = "";
    
    if (cat.includes("어머니")) {
      if (allText.includes("좋") || allText.includes("사랑") || allText.includes("따뜻")) {
        analysis = "어머니와의 관계에서 하나님의 사랑과 돌보심이 반영되어 있습니다. '어머니가 자식을 위로함같이 내가 너희를 위로하리니'(이사야 66:13)라는 말씀처럼, 건강한 어머니상은 하나님의 사랑을 경험하는 통로가 됩니다.";
      } else if (allText.includes("힘들") || allText.includes("어렵") || allText.includes("갈등")) {
        analysis = "어머니와의 관계에서 어려움이 있지만, 하나님께서는 '고아의 아버지'(시편 68:5)이시며 모든 관계의 상처를 치유하실 수 있습니다. 용서와 화해의 과정을 통해 하나님의 회복을 경험할 수 있습니다.";
      } else {
        analysis = "어머니와의 관계에 대한 복합적인 감정이 나타납니다. 이는 모든 인간 관계의 불완전함을 보여주며, 완전한 사랑은 오직 하나님 안에서만 발견됩니다(요한일서 4:19).";
      }
    } else if (cat.includes("아버지")) {
      if (allText.includes("존경") || allText.includes("좋") || allText.includes("따뜻")) {
        analysis = "아버지와의 긍정적 관계는 하늘 아버지를 이해하는 데 도움이 됩니다. '아버지께서 자식을 긍휼히 여기심같이 여호와께서는 자기를 경외하는 자를 긍휼히 여기시나니'(시편 103:13).";
      } else if (allText.includes("무섭") || allText.includes("엄격") || allText.includes("거리")) {
        analysis = "아버지와의 관계에서 두려움이나 거리감이 느껴지지만, 하나님 아버지는 '사랑의 아버지시오 모든 위로의 하나님이시며'(고린도후서 1:3) 우리를 완전히 받아주십니다. 땅의 아버지의 불완전함이 하늘 아버지의 완전한 사랑을 가리지 않도록 기도가 필요합니다.";
      } else {
        analysis = "아버지 상에 대한 다층적인 인식이 나타납니다. 하나님은 완전한 아버지이시며, 땅의 아버지와의 관계를 통해 하나님의 아버지 되심을 더 깊이 이해할 수 있습니다.";
      }
    } else if (cat.includes("가족")) {
      if (allText.includes("화목") || allText.includes("행복") || allText.includes("사랑")) {
        analysis = "가족 관계가 전반적으로 긍정적입니다. '보라 형제가 연합하여 동거함이 어찌 그리 선하고 아름다운고'(시편 133:1). 감사함으로 이 축복을 지키고 더욱 발전시켜 나가세요.";
      } else if (allText.includes("갈등") || allText.includes("힘들") || allText.includes("불화")) {
        analysis = "가족 내 어려움이 있지만, '그리스도의 평강이 너희 마음을 주장하게 하라'(골로새서 3:15). 용서와 화해는 성경적 가족 회복의 핵심입니다. 먼저 자신의 죄를 인정하고 용서를 구하는 것부터 시작하세요.";
      } else {
        analysis = "가족 관계에 대한 복합적 인식이 나타납니다. 가족은 하나님이 세우신 첫 번째 공동체이며, '서로 사랑하라'(요한복음 13:34)는 명령이 가장 먼저 실천되어야 할 곳입니다.";
      }
    } else if (cat.includes("두려움")) {
      if (allText.includes("없") || allText.includes("괜찮")) {
        analysis = "두려움이 적은 것은 하나님을 신뢰하는 믿음의 표현일 수 있습니다. '두려워하지 말라 내가 너와 함께함이라'(이사야 41:10)는 약속을 계속 붙들으세요.";
      } else if (allText.includes("실패") || allText.includes("거절") || allText.includes("혼자")) {
        analysis = "두려움이 관찰되지만, 성경은 '두려워 말라'를 365번 말씀합니다. 하나님은 '너를 버리지 아니하고 너를 떠나지 아니하시리라'(히브리서 13:5)고 약속하십니다. 두려움은 하나님께 맡기고 말씀 안에서 평안을 찾으세요.";
      } else {
        analysis = "다양한 두려움이 나타납니다. '완전한 사랑이 두려움을 내쫓나니'(요한일서 4:18). 하나님의 사랑을 더 깊이 경험할수록 두려움은 줄어듭니다.";
      }
    } else if (cat.includes("죄책감")) {
      if (allText.includes("없") || allText.includes("후회")) {
        analysis = "적절한 죄책감은 회개로 이끄는 건강한 양심의 표현입니다. '우리가 우리 죄를 자백하면 그는 미쁘시고 의로우사 우리 죄를 사하시며'(요한일서 1:9).";
      } else if (allText.includes("많") || allText.includes("미안") || allText.includes("잘못")) {
        analysis = "과도한 죄책감이 나타납니다. 그리스도 안에서 '정죄함이 없나니'(로마서 8:1). 이미 용서받았다면 계속 죄책감에 매여 있는 것은 사탄의 전략입니다. 하나님의 완전한 용서를 믿고 받아들이세요.";
      } else {
        analysis = "죄책감에 대한 복합적 인식이 나타납니다. 성경적으로 죄는 인정하되, 그리스도의 십자가를 통해 이미 용서받았음을 기억하세요(에베소서 1:7).";
      }
    } else if (cat.includes("능력")) {
      if (allText.includes("잘") || allText.includes("자신") || allText.includes("능력")) {
        analysis = "자신의 능력을 긍정적으로 인식하고 있습니다. 이는 하나님이 주신 은사를 잘 활용하는 것입니다. '내게 능력 주시는 자 안에서 내가 모든 것을 할 수 있느니라'(빌립보서 4:13).";
      } else if (allText.includes("부족") || allText.includes("못") || allText.includes("없")) {
        analysis = "자신의 부족함을 인식하는 것은 겸손의 시작입니다. '내 은혜가 네게 족하도다 이는 내 능력이 약한 데서 온전하여짐이라'(고린도후서 12:9). 하나님은 약한 자를 통해 일하십니다.";
      } else {
        analysis = "자기 능력에 대한 현실적 평가가 나타납니다. 성경은 '자기를 낮추는 자는 높아지고'(마태복음 23:12)라고 말씀합니다. 겸손과 자신감의 균형을 유지하세요.";
      }
    } else if (cat.includes("미래")) {
      if (allText.includes("밝") || allText.includes("희망") || allText.includes("기대")) {
        analysis = "미래에 대한 희망적 태도가 나타납니다. '너희를 향한 나의 생각을 아나니 평안이요 재앙이 아니니라 너희에게 미래와 희망을 주는 것이니라'(예레미야 29:11).";
      } else if (allText.includes("불안") || allText.includes("걱정") || allText.includes("어두")) {
        analysis = "미래에 대한 불안이 관찰됩니다. '내일 일을 위하여 염려하지 말라... 한 날의 괴로움은 그 날로 족하니라'(마태복음 6:34). 하나님이 인도하시는 미래를 신뢰하세요.";
      } else {
        analysis = "미래에 대한 현실적 태도가 나타납니다. '사람이 마음으로 자기의 길을 계획할지라도 그의 걸음을 인도하시는 이는 여호와시니라'(잠언 16:9).";
      }
    } else if (cat.includes("목표")) {
      if (allText.includes("명확") || allText.includes("계획") || allText.includes("꿈")) {
        analysis = "목표가 명확한 것은 좋은 청지기의 모습입니다. '네가 하는 일을 여호와께 맡기라 그리하면 네가 경영하는 것이 이루어지리라'(잠언 16:3). 하나님의 뜻 안에서 목표를 추구하세요.";
      } else if (allText.includes("모르") || allText.includes("없") || allText.includes("막연")) {
        analysis = "목표가 불명확한 상태입니다. '너희는 먼저 그의 나라와 그의 의를 구하라 그리하면 이 모든 것을 너희에게 더하시리라'(마태복음 6:33). 하나님의 뜻을 구하는 기도부터 시작하세요.";
      } else {
        analysis = "목표에 대한 탐색 과정에 있습니다. '너는 마음을 다하여 여호와를 신뢰하고 네 명철을 의지하지 말라 너는 범사에 그를 인정하라 그리하면 네 길을 지도하시리라'(잠언 3:5-6).";
      }
    } else {
      analysis = "이 영역에 대한 응답을 종합적으로 분석한 결과, 하나님의 형상으로 지음 받은 개인의 고유한 경험과 인식이 반영되어 있습니다. 성경적 상담을 통해 더 깊이 탐색하고 하나님의 뜻을 발견할 수 있습니다.";
    }
    
    return analysis;
  }
  
  // 🕊️ 성경적 상담 SCT 권장사항
  function generateBiblicalSctRecommendations(cat, allText) {
    const recommendations = [];
    
    if (allText.includes("힘들") || allText.includes("어렵") || allText.includes("갈등")) {
      recommendations.push("• 매일 성경 읽기와 기도로 하나님과의 관계 깊이하기");
      recommendations.push("• 성경적 상담을 통해 관계 회복과 용서의 과정 경험하기");
      recommendations.push("• 소그룹이나 셀 모임에서 영적 지지 받기");
    }
    
    if (allText.includes("불안") || allText.includes("걱정") || allText.includes("두렵")) {
      recommendations.push("• 시편 말씀 묵상과 암송 (시편 23, 27, 46편 등)");
      recommendations.push("• 염려를 기도로 전환하기 (빌립보서 4:6-7)");
      recommendations.push("• 찬양과 경배를 통한 영적 평안 경험");
    }
    
    if (allText.includes("없") || allText.includes("모르")) {
      recommendations.push("• 하나님의 뜻을 구하는 기도 생활 (야고보서 1:5)");
      recommendations.push("• 성경적 비전 발견을 위한 금식기도");
      recommendations.push("• 영적 멘토나 목회자와의 정기적 만남");
    }
    
    if (allText.includes("죄책") || allText.includes("잘못") || allText.includes("미안")) {
      recommendations.push("• 십자가 복음 묵상과 용서의 확신 갖기");
      recommendations.push("• 필요시 화해와 용서를 구하는 실천");
      recommendations.push("• '그리스도 안에서의 새로운 피조물' 정체성 확립 (고린도후서 5:17)");
    }
    
    if (allText.includes("우울") || allText.includes("슬프") || allText.includes("의욕")) {
      recommendations.push("• 시편 기도로 하나님께 감정 토로하기");
      recommendations.push("• 성도들과의 교제를 통한 영적 회복");
      recommendations.push("• 감사 일기 쓰기 (데살로니가전서 5:18)");
    }
    
    // 모든 경우에 공통 권장사항
    recommendations.push("• 정기적인 교회 출석과 말씀 사역 참여");
    recommendations.push("• 성경 통독 및 QT(Quiet Time) 습관화");
    
    return recommendations;
  }

  // ✅ DSI AI 권장사항 생성 (상담 유형별 분기)
  function generateDsiRecommendation() {
    setLoadingRec(true);
    setDsiRec("");
    
    // 상담 유형 확인 (기본값: 심리상담)
    const counselingType = activeLinkData?.counselingType || "psychological";
    
    const { total, areas } = calcDsi();
    
    let finalRec = "";
    if (counselingType === "biblical") {
      // 🕊️ 성경적 상담 분석
      finalRec = generateBiblicalDsiAnalysis(total, areas);
    } else {
      // 🧠 심리상담 분석
      finalRec = generatePsychologicalDsiAnalysis(total, areas);
    }
    
    setTimeout(() => {
      setDsiRec(finalRec);
      setLoadingRec(false);
    }, 1000);
  }
  
  // 🧠 심리상담 DSI 분석
  function generatePsychologicalDsiAnalysis(total, areas) {
    const level = total >= 120 ? "높음(양호)" : total >= 80 ? "중간(보통)" : "낮음(취약)";
    
    // 영역별 분석
    const areaAnalysis = [];
    const weakAreas = [];
    const strongAreas = [];
    
    Object.entries(areas).forEach(([area, score]) => {
      const maxScore = 36;
      const percentage = (score / maxScore) * 100;
      
      if (percentage >= 70) {
        strongAreas.push(area);
      } else if (percentage < 50) {
        weakAreas.push(area);
      }
      
      let areaComment = "";
      if (area === "인지적 기능") {
        if (percentage >= 70) {
          areaComment = "감정 조절과 의사결정 능력이 우수합니다. 충동성이 낮고 논리적 사고가 가능합니다.";
        } else if (percentage < 50) {
          areaComment = "충동성 조절에 어려움이 있을 수 있습니다. 감정과 사고를 분리하는 연습이 필요합니다.";
        } else {
          areaComment = "감정 조절 능력이 보통 수준입니다. 스트레스 관리 기법을 익히면 도움이 됩니다.";
        }
      } else if (area === "자아통합") {
        if (percentage >= 70) {
          areaComment = "자기 정체성이 명확하고 가치관이 일관됩니다. 자율성이 높습니다.";
        } else if (percentage < 50) {
          areaComment = "타인의 영향을 많이 받는 편입니다. 자기 가치관을 명료화하는 작업이 필요합니다.";
        } else {
          areaComment = "자아 정체성 형성 과정에 있습니다. 자기 탐색을 통해 더 강화할 수 있습니다.";
        }
      } else if (area === "가족투사") {
        if (percentage >= 70) {
          areaComment = "가족 문제로부터 건강하게 분리되어 있습니다. 객관적 시각을 유지합니다.";
        } else if (percentage < 50) {
          areaComment = "가족 문제가 현재 삶에 영향을 주고 있습니다. 가족 상담이 도움이 될 수 있습니다.";
        } else {
          areaComment = "가족 영향을 인식하고 있습니다. 건강한 경계 설정이 필요합니다.";
        }
      } else if (area === "정서적 단절") {
        if (percentage >= 70) {
          areaComment = "가족과 적절한 거리를 유지합니다. 독립성과 친밀감의 균형이 좋습니다.";
        } else if (percentage < 50) {
          areaComment = "가족으로부터 과도하게 단절되어 있을 수 있습니다. 연결감 회복이 필요합니다.";
        } else {
          areaComment = "가족과의 거리감이 적절합니다. 현재 수준을 유지하는 것이 좋습니다.";
        }
      } else if (area === "가족퇴행") {
        if (percentage >= 70) {
          areaComment = "가족 스트레스 상황에서도 성숙하게 대응합니다. 퇴행 경향이 낮습니다.";
        } else if (percentage < 50) {
          areaComment = "가족 상황에서 스트레스를 많이 받습니다. 감정 조절 기법이 필요합니다.";
        } else {
          areaComment = "가족 상황 대처가 보통입니다. 스트레스 관리를 강화하면 좋습니다.";
        }
      }
      
      areaAnalysis.push(`${area} (${score}/${maxScore}점, ${percentage.toFixed(0)}%):\n${areaComment}`);
    });
    
    // 종합 분석
    let overallAnalysis = `전반적인 자아분화 수준이 ${level}입니다. `;
    if (total >= 120) {
      overallAnalysis += "자기 자신에 대한 이해가 깊고, 타인과의 관계에서 건강한 경계를 유지할 수 있습니다. 정서적으로 안정적이며 독립적인 의사결정이 가능합니다.";
    } else if (total >= 80) {
      overallAnalysis += "기본적인 자아분화가 이루어져 있으나, 일부 영역에서 개선의 여지가 있습니다. 지속적인 자기 성찰과 성장이 도움이 됩니다.";
    } else {
      overallAnalysis += "자아분화 수준이 다소 낮은 편입니다. 가족이나 타인의 영향을 많이 받을 수 있으며, 전문적인 상담을 통한 지원이 권장됩니다.";
    }
    
    // 권장사항
    const recommendations = [];
    
    if (weakAreas.length > 0) {
      recommendations.push(`[취약 영역 개선]\n취약한 영역: ${weakAreas.join(", ")}\n• 해당 영역에 초점을 맞춘 상담 진행\n• 자기 인식 강화 활동 (일기 쓰기, 자기 성찰)\n• 가족과의 건강한 경계 설정 연습`);
    }
    
    if (total < 120) {
      recommendations.push("[상담 접근법]\n• Bowen 가족치료 기법 활용\n• 자아분화 향상 프로그램 참여\n• 정서 조절 기술 훈련\n• 가족 관계 재구조화 작업");
    }
    
    if (strongAreas.length > 0) {
      recommendations.push(`[강점 활용]\n강점 영역: ${strongAreas.join(", ")}\n• 강점을 활용한 대처 전략 강화\n• 긍정적 경험 확대 적용`);
    }
    
    recommendations.push("[단기 목표 (1-3개월)]\n• 주 1회 정기 상담 참여\n• 감정 일지 작성 (일일)\n• 이완 훈련 실천 (주 3회)");
    
    recommendations.push("[장기 목표 (6-12개월)]\n• 자아분화 수준 20% 향상\n• 가족과의 건강한 관계 재정립\n• 스트레스 상황에서의 대처 능력 강화");
    
    return `${overallAnalysis}\n\n[영역별 상세 분석]\n${areaAnalysis.join("\n\n")}\n\n${recommendations.join("\n\n")}\n\n[주의사항]\n본 권장사항은 자동 분석 결과이며, 전문 상담사의 해석과 병행되어야 합니다. 개인의 고유한 맥락을 고려한 맞춤형 상담이 중요합니다.`;
  }
  
  // 🕊️ 성경적 상담 DSI 분석
  function generateBiblicalDsiAnalysis(total, areas) {
    const level = total >= 120 ? "높음(양호)" : total >= 80 ? "중간(보통)" : "낮음(취약)";
    
    // 영역별 분석
    const areaAnalysis = [];
    const weakAreas = [];
    const strongAreas = [];
    
    Object.entries(areas).forEach(([area, score]) => {
      const maxScore = 36;
      const percentage = (score / maxScore) * 100;
      
      if (percentage >= 70) {
        strongAreas.push(area);
      } else if (percentage < 50) {
        weakAreas.push(area);
      }
      
      let areaComment = "";
      if (area === "인지적 기능") {
        if (percentage >= 70) {
          areaComment = "감정을 잘 조절하고 논리적으로 사고합니다. '너희는 이 세대를 본받지 말고 오직 마음을 새롭게 함으로 변화를 받아 하나님의 선하시고 기뻐하시고 온전하신 뜻이 무엇인지 분별하도록 하라'(로마서 12:2). 하나님이 주신 이성의 선물을 잘 사용하고 있습니다.";
        } else if (percentage < 50) {
          areaComment = "충동적인 반응이 나타날 수 있습니다. '사람의 성내는 것이 하나님의 의를 이루지 못함이라'(야고보서 1:20). 감정에 휘둘리기 전에 기도하며 하나님의 지혜를 구하세요.";
        } else {
          areaComment = "감정 조절 능력이 보통입니다. '너희 안에 이 마음을 품으라 곧 그리스도 예수의 마음이니'(빌립보서 2:5). 그리스도의 마음을 품고 성령의 열매를 구하세요.";
        }
      } else if (area === "자아통합") {
        if (percentage >= 70) {
          areaComment = "자기 정체성이 명확합니다. '그리스도 안에서 새로운 피조물'(고린도후서 5:17)로서의 정체성을 잘 확립하고 있습니다. 하나님의 자녀로서 확신 있게 살아가고 있습니다.";
        } else if (percentage < 50) {
          areaComment = "타인의 영향을 많이 받습니다. '사람을 기쁘게 하는 자가 되려 하였더라면 그리스도의 종이 아니니라'(갈라디아서 1:10). 하나님 안에서 자신의 정체성을 찾고, 하나님만을 기쁘시게 하는 삶을 추구하세요.";
        } else {
          areaComment = "자아 정체성 형성 중입니다. '너희 믿음을 시험하여 너희가 믿음 안에 있는가 너희 자신을 확증하라'(고린도후서 13:5). 그리스도 안에서 자신이 누구인지 확인하는 시간을 가지세요.";
        }
      } else if (area === "가족투사") {
        if (percentage >= 70) {
          areaComment = "가족 문제로부터 건강하게 분리되어 있습니다. '그러므로 사람이 부모를 떠나 그의 아내와 합하여 둘이 한 몸을 이룰지로다'(창세기 2:24). 성경적 독립과 분리를 이루었습니다.";
        } else if (percentage < 50) {
          areaComment = "가족 문제가 현재 삶에 영향을 줍니다. '또 다른 사람들도 건지고자 하여 두려움으로 붙들어 끌어내며'(유다서 1:23). 가족을 사랑하되, 가족의 문제가 당신의 정체성을 정의하지 않도록 기도하세요. 용서와 경계 설정이 필요합니다.";
        } else {
          areaComment = "가족 영향을 인식하고 있습니다. '내 멍에는 쉽고 내 짐은 가벼우니라'(마태복음 11:30). 가족의 짐을 주님께 맡기고 건강한 경계를 세우세요.";
        }
      } else if (area === "정서적 단절") {
        if (percentage >= 70) {
          areaComment = "가족과 적절한 거리를 유지합니다. '각 사람은 자기 자신의 행위를 살피라 그리하면 자랑할 것이 자기에게만 있고 남에게는 있지 아니하리니'(갈라디아서 6:4). 독립성과 친밀감의 균형이 좋습니다.";
        } else if (percentage < 50) {
          areaComment = "가족으로부터 과도하게 단절되어 있을 수 있습니다. '네 부모를 공경하라'(출애굽기 20:12)는 명령을 기억하세요. 상처가 있더라도 용서하고 화해를 추구하세요.";
        } else {
          areaComment = "가족과의 거리가 적절합니다. '모든 사람과 더불어 화평함과 거룩함을 따르라'(히브리서 12:14). 관계를 유지하며 성장하세요.";
        }
      } else if (area === "가족퇴행") {
        if (percentage >= 70) {
          areaComment = "가족 스트레스에도 성숙하게 대응합니다. '내가 어렸을 때에는 말하는 것이 어린 아이와 같고... 장성한 사람이 되어서는 어린 아이의 일을 버렸노라'(고린도전서 13:11). 영적 성숙함이 나타납니다.";
        } else if (percentage < 50) {
          areaComment = "가족 상황에서 스트레스를 많이 받습니다. '너희 염려를 다 주께 맡기라 이는 그가 너희를 돌보심이라'(베드로전서 5:7). 가족 문제를 하나님께 맡기고 평안을 찾으세요.";
        } else {
          areaComment = "가족 상황 대처가 보통입니다. '주 안에서 항상 기뻐하라'(빌립보서 4:4). 어려운 상황에서도 주님을 바라보세요.";
        }
      }
      
      areaAnalysis.push(`${area} (${score}/${maxScore}점, ${percentage.toFixed(0)}%):\n${areaComment}`);
    });
    
    // 종합 분석
    let overallAnalysis = `전반적인 자아분화 수준이 ${level}입니다. `;
    if (total >= 120) {
      overallAnalysis += "하나님께서 주신 건강한 자아가 잘 형성되어 있습니다. '그리스도 안에서 자유롭게 하는 것'(갈라디아서 5:1)을 경험하고 있으며, 타인과의 관계에서도 그리스도의 사랑으로 균형을 유지합니다. 이 은혜를 감사히 여기며 다른 이들을 세우는 데 사용하세요.";
    } else if (total >= 80) {
      overallAnalysis += "기본적인 자아분화가 이루어져 있습니다. '선을 행하되 낙심하지 말지니 포기하지 아니하면 때가 이르매 거두리라'(갈라디아서 6:9). 더 깊은 영적 성숙을 향해 나아가세요.";
    } else {
      overallAnalysis += "자아분화 수준이 낮은 편입니다. 그러나 하나님은 '연약한 자들을 강하게 하시는'(고린도후서 12:9) 분이십니다. 주님의 능력이 약한 데서 온전하여집니다. 겸손히 도움을 구하고 성경적 상담을 받으세요.";
    }
    
    // 성경적 권장사항
    const recommendations = [];
    
    if (weakAreas.length > 0) {
      recommendations.push(`[취약 영역의 영적 치유]\n취약한 영역: ${weakAreas.join(", ")}\n• 해당 영역에 대한 성경 말씀 묵상과 암송\n• 성경적 상담을 통한 하나님의 관점 회복\n• 기도와 금식으로 영적 돌파 경험\n• 소그룹에서 중보기도 받기`);
    }
    
    if (total < 120) {
      recommendations.push("[영적 성장 전략]\n• 매일 성경 읽기와 QT로 하나님과의 관계 깊이하기\n• 십자가 복음 묵상 - 정체성의 근원 확인\n• 용서와 화해의 실천 (가족 관계 회복)\n• 성령 충만과 성령의 열매 구하기");
    }
    
    if (strongAreas.length > 0) {
      recommendations.push(`[강점을 통한 섬김]\n강점 영역: ${strongAreas.join(", ")}\n• 이 은사를 교회와 이웃 섬김에 사용하기\n• 약한 자들을 돌보고 격려하기\n• 하나님께 감사와 찬양 드리기`);
    }
    
    recommendations.push("[단기 영적 목표 (1-3개월)]\n• 주 1회 성경적 상담 참여\n• 매일 성경 묵상과 기도 일기 작성\n• 주일 예배 및 소그룹 모임 참석\n• 가족을 위한 중보기도");
    
    recommendations.push("[장기 영적 목표 (6-12개월)]\n• 그리스도 안에서의 정체성 확립\n• 가족과의 성경적 관계 회복\n• 영적 성숙을 통한 자아분화 향상\n• 섬김과 사역을 통한 은사 개발");
    
    recommendations.push("[추천 성경 구절 묵상]\n• 정체성: 고린도후서 5:17, 갈라디아서 2:20\n• 가족 관계: 에베소서 6:1-4, 골로새서 3:18-21\n• 감정 조절: 잠언 16:32, 야고보서 1:19-20\n• 자유와 성숙: 갈라디아서 5:1, 고린도전서 13:11");
    
    return `${overallAnalysis}\n\n[영역별 상세 분석]\n${areaAnalysis.join("\n\n")}\n\n${recommendations.join("\n\n")}\n\n[성경적 상담의 원칙]\n본 권장사항은 성경 말씀에 기초한 분석이며, 숙련된 성경적 상담사와 함께 더 깊이 탐색하시기를 권장합니다. '모든 성경은 하나님의 감동으로 된 것으로 교훈과 책망과 바르게 함과 의로 교육하기에 유익하니'(디모데후서 3:16). 하나님의 말씀이 당신을 인도하고 치유하시기를 기도합니다.`;
  }

  function logout() {
    // ✅ 로그인 상태 제거
    clearLoginState();
    
    setIsAdmin(false);
    setIsMaster(false);
    setIsOrgAdmin(false);
    setMasterInfo(null);
    setIsCounselor(false);
    setIsOrgAdmin(false);
    setCounselorPhone("");
    setOrgAdminInfo(null);
    setOrgCounselors([]);
    setUserInfo({ phone: "", password: "" });
    setLoginMsg({ type: "", text: "" });
    setSctResponses({});
    setSctSummaries({});
    setDsiResponses({});
    setDsiRec("");
    setActiveLinkId(null);
    setActiveLinkData(null);
    setGeneratedLinks([]);
    setSubmitted([]);
    setLinkInput("");
    setPendingTests([]);
    setCurrentTestIndex(0);
    setMultiSessionIds([]);
    clearToken();
    setView("login");
  }

  const Msg = ({ msg }) => !msg.text ? null : (
    <div className={`mb-4 p-3 rounded-lg border-2 text-sm font-semibold ${msg.type === "success" ? "bg-green-50 border-green-400 text-green-800" : msg.type === "error" ? "bg-red-50 border-red-400 text-red-800" : "bg-blue-50 border-blue-400 text-blue-800"}`}>
      {msg.text}
    </div>
  );

  function getCounselorSessions() {
    return submitted.filter(s => {
      if (!s.linkId) return false;
      const linkData = loadLink(s.linkId);
      return linkData && linkData.counselorPhone === counselorPhone;
    });
  }

  // ========== VIEWS ==========

  if (view === "login") {
  }
  
  if (view === "login") return (
    <div className="min-h-screen bg-gradient-to-br from-slate-50 to-indigo-100 flex items-center justify-center p-4">
      <div className="bg-white rounded-2xl shadow-2xl p-8 w-full max-w-md">
        <div className="text-center mb-6">
          <div className="text-5xl mb-3">🧠</div>
          <h1 className="text-3xl font-bold text-gray-800">심리검사 시스템</h1>
          <p className="text-gray-400 text-sm mt-1">상담사에게 받은 링크 ID로 검사를 시작하세요</p>
        </div>
        <Msg msg={loginMsg} />
        <div className="bg-indigo-50 border-2 border-indigo-200 rounded-xl p-5 mb-5">
          <p className="text-sm font-bold text-indigo-700 mb-3">📋 검사 응시 (내담자)</p>
          <input
            className="w-full px-4 py-3 border-2 border-indigo-300 rounded-lg outline-none focus:border-indigo-500 text-sm mb-3 font-mono"
            placeholder="상담사에게 받은 링크 ID를 여기에 붙여넣으세요"
            value={linkInput}
            onChange={e => setLinkInput(e.target.value)}
            onKeyDown={e => e.key === "Enter" && enterByLinkId()}
          />
          <button onClick={enterByLinkId} className="w-full bg-indigo-600 text-white py-3 rounded-lg font-bold hover:bg-indigo-700 transition text-base">
            검사 시작하기 →
          </button>
        </div>
        <div className="relative mb-5">
          <div className="absolute inset-0 flex items-center"><div className="w-full border-t border-gray-200" /></div>
          <div className="relative flex justify-center"><span className="px-3 bg-white text-gray-400 text-xs">전문가 전용</span></div>
        </div>
        <div className="grid grid-cols-2 gap-2">
          <button onClick={() => { setLoginMsg({ type: "", text: "" }); setUserInfo({ phone: "", password: "" }); setView("orgAdminLogin"); }} className="bg-blue-600 text-white py-3 rounded-xl font-semibold hover:bg-blue-700 transition text-xs">
            🏢 단체관리자
          </button>
          <button onClick={() => { setLoginMsg({ type: "", text: "" }); setUserInfo({ phone: "", password: "" }); setView("counselorLogin"); }} className="bg-purple-600 text-white py-3 rounded-xl font-semibold hover:bg-purple-700 transition text-xs">
            👨‍⚕️ 상담사
          </button>
        </div>
        <div className="mt-3">
          <button onClick={() => { setLoginMsg({ type: "", text: "" }); setUserInfo({ phone: "", password: "" }); setView("masterLogin"); }} className="w-full bg-gray-900 text-yellow-400 py-2.5 rounded-xl font-semibold hover:bg-black transition text-xs flex items-center justify-center gap-1 border border-gray-700">
            👑 마스터 관리자
          </button>
        </div>
      </div>
    </div>
  );

  if (view === "clientLogin") return (
    <div className="min-h-screen bg-gradient-to-br from-teal-50 to-cyan-100 flex items-center justify-center p-4">
      <div className="bg-white rounded-2xl shadow-2xl p-8 w-full max-w-md">
        <button onClick={() => { setView("login"); setLoginMsg({ type: "", text: "" }); }} className="text-gray-400 hover:text-gray-600 text-sm mb-5 flex items-center gap-1">
          ← 뒤로
        </button>
        <div className="text-center mb-6">
          <div className="text-4xl mb-2">🧪</div>
          <h1 className="text-2xl font-bold text-gray-800">
            심리검사 시작
          </h1>
          <div className="mt-2 inline-block bg-teal-100 text-teal-800 px-3 py-1 rounded-full text-sm font-semibold">
            내담자: {activeLinkData?.clientName}
          </div>
          {activeLinkData && (activeLinkData.testTypes || [activeLinkData.testType]).length > 0 && (
            <div className="mt-3">
              <p className="text-xs text-gray-500 mb-1.5">진행할 검사 ({(activeLinkData.testTypes || [activeLinkData.testType]).length}개)</p>
              <div className="flex flex-wrap justify-center gap-1.5">
                {(activeLinkData.testTypes || [activeLinkData.testType]).map((t, i) => (
                  <span key={t} className="px-2.5 py-1 bg-purple-100 text-purple-800 rounded-full text-xs font-bold border border-purple-200">
                    {i+1}. {t}
                  </span>
                ))}
              </div>
            </div>
          )}
        </div>
        <div className="bg-teal-50 border border-teal-200 rounded-lg p-3 mb-4 text-sm text-teal-700">
          ✅ 링크 확인 완료. 전화번호와 비밀번호를 입력해 검사를 시작하세요.
        </div>
        <Msg msg={loginMsg} />
        <div className="space-y-4">
          <div>
            <label className="block text-sm font-semibold text-gray-700 mb-1">전화번호</label>
            <input type="tel" value={userInfo.phone} onChange={e => setUserInfo({ ...userInfo, phone: e.target.value })} placeholder="010-1234-5678" className="w-full px-4 py-3 border-2 border-gray-300 rounded-lg focus:border-teal-500 outline-none" />
          </div>
          <div>
            <label className="block text-sm font-semibold text-gray-700 mb-1">비밀번호</label>
            <input type="password" value={userInfo.password} onChange={e => setUserInfo({ ...userInfo, password: e.target.value })} placeholder="사용하실 비밀번호를 입력하세요" className="w-full px-4 py-3 border-2 border-gray-300 rounded-lg focus:border-teal-500 outline-none" onKeyDown={e => e.key === "Enter" && clientLogin()} />
            <p className="text-xs text-gray-400 mt-1">* 본인이 직접 설정하는 비밀번호입니다</p>
          </div>
          <button onClick={clientLogin} className="w-full bg-teal-600 text-white py-3 rounded-lg font-bold hover:bg-teal-700 transition text-lg">
            검사 시작 →
          </button>
        </div>
      </div>
    </div>
  );

  
if (view === "masterLogin") return (
    <div className="min-h-screen bg-gradient-to-br from-gray-800 to-slate-900 flex items-center justify-center p-4">
      <div className="bg-white rounded-2xl shadow-2xl p-8 w-full max-w-sm">
        <button onClick={() => { setView("login"); setLoginMsg({ type: "", text: "" }); }} className="text-gray-400 hover:text-gray-600 text-sm mb-5 flex items-center gap-1">← 뒤로</button>
        <div className="text-center mb-6">
          <div className="text-4xl mb-2">👑</div>
          <h1 className="text-2xl font-bold text-gray-800">마스터 로그인</h1>
          <p className="text-xs text-gray-400 mt-1">시스템 전체 관리자 전용</p>
        </div>
        <Msg msg={loginMsg} />
        <div className="space-y-4">
          <div>
            <label className="block text-sm font-semibold text-gray-700 mb-1">전화번호</label>
            <input type="tel" value={userInfo.phone} onChange={e => setUserInfo({ ...userInfo, phone: e.target.value })}
              placeholder="010-0000-0000" className="w-full px-4 py-3 border-2 border-gray-300 rounded-lg outline-none focus:border-gray-600" autoFocus />
          </div>
          <div>
            <label className="block text-sm font-semibold text-gray-700 mb-1">비밀번호</label>
            <input type="password" value={userInfo.password} onChange={e => setUserInfo({ ...userInfo, password: e.target.value })}
              placeholder="비밀번호 입력" className="w-full px-4 py-3 border-2 border-gray-300 rounded-lg outline-none focus:border-gray-600"
              onKeyDown={e => e.key === "Enter" && masterLogin()} />
          </div>
          <button onClick={masterLogin} disabled={loginLoading} className="w-full bg-gray-800 text-white py-3 rounded-lg font-bold hover:bg-gray-900 transition disabled:opacity-60 flex items-center justify-center gap-2">{loginLoading ? (<><svg className="w-4 h-4 animate-spin" fill="none" viewBox="0 0 24 24"><circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"/><path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"/></svg>로그인 중...</>) : '로그인'}</button>
        </div>
      </div>
    </div>
  );

  if (view === "adminLogin") return (
    <div className="min-h-screen bg-gradient-to-br from-gray-800 to-slate-900 flex items-center justify-center p-4">
      <div className="bg-white rounded-2xl shadow-2xl p-8 w-full max-w-sm">
        <button onClick={() => { setView("login"); setLoginMsg({ type: "", text: "" }); }} className="text-gray-400 hover:text-gray-600 text-sm mb-5 flex items-center gap-1">← 뒤로</button>
        <div className="text-center mb-6">
          <div className="text-4xl mb-2">👑</div>
          <h1 className="text-2xl font-bold text-gray-800">마스터 로그인</h1>
          <p className="text-xs text-gray-400 mt-1">시스템 전체 관리자 전용</p>
        </div>
        <Msg msg={loginMsg} />
        <div className="space-y-4">
          <div>
            <label className="block text-sm font-semibold text-gray-700 mb-1">전화번호</label>
            <input type="tel" value={userInfo.phone} onChange={e => setUserInfo({ ...userInfo, phone: e.target.value })}
              placeholder="01000000000" className="w-full px-4 py-3 border-2 border-gray-300 rounded-lg outline-none focus:border-gray-600" autoFocus />
          </div>
          <div>
            <label className="block text-sm font-semibold text-gray-700 mb-1">비밀번호</label>
            <input type="password" value={userInfo.password} onChange={e => setUserInfo({ ...userInfo, password: e.target.value })}
              placeholder="비밀번호 입력" className="w-full px-4 py-3 border-2 border-gray-300 rounded-lg outline-none focus:border-gray-600"
              onKeyDown={e => e.key === "Enter" && masterLogin()} />
          </div>
          <button onClick={masterLogin} disabled={loginLoading} className="w-full bg-gray-800 text-white py-3 rounded-lg font-bold hover:bg-gray-900 transition disabled:opacity-60">
            {loginLoading ? "로그인 중..." : "로그인"}
          </button>
        </div>
      </div>
    </div>
  );

  if (view === "orgAdminLogin") return (
    <div className="min-h-screen bg-gradient-to-br from-blue-100 to-indigo-200 flex items-center justify-center p-4">
      <div className="bg-white rounded-2xl shadow-2xl p-8 w-full max-w-sm">
        <button onClick={() => { setView("login"); setLoginMsg({ type: "", text: "" }); }} className="text-gray-400 hover:text-gray-600 text-sm mb-5 flex items-center gap-1">
          ← 뒤로
        </button>
        <h1 className="text-2xl font-bold text-gray-800 mb-6 text-center">🏢 단체 관리자 로그인</h1>
        <Msg msg={loginMsg} />
        <div className="space-y-4">
          <div>
            <label className="block text-sm font-semibold text-gray-700 mb-1">전화번호 (ID)</label>
            <input 
              type="tel" 
              value={userInfo.phone} 
              onChange={e => setUserInfo({ ...userInfo, phone: e.target.value })} 
              placeholder="org001" 
              className="w-full px-4 py-3 border-2 border-blue-300 rounded-lg outline-none focus:border-blue-500" 
              autoFocus
            />
          </div>
          <div>
            <label className="block text-sm font-semibold text-gray-700 mb-1">비밀번호</label>
            <input 
              type="password" 
              value={userInfo.password} 
              onChange={e => setUserInfo({ ...userInfo, password: e.target.value })} 
              placeholder="비밀번호 입력" 
              className="w-full px-4 py-3 border-2 border-blue-300 rounded-lg outline-none focus:border-blue-500" 
              onKeyDown={e => e.key === "Enter" && orgAdminLogin()} 
            />
          </div>
          <button 
            onClick={orgAdminLogin} 
            disabled={loginLoading}
            className="w-full bg-blue-600 text-white py-3 rounded-lg font-bold hover:bg-blue-700 transition disabled:opacity-50"
          >
            {loginLoading ? "로그인 중..." : "로그인"}
          </button>
        </div>
      </div>
    </div>
  );

  if (view === "counselorLogin") return (
    <div className="min-h-screen bg-gradient-to-br from-purple-50 to-pink-100 flex items-center justify-center p-4">
      <div className="bg-white rounded-2xl shadow-2xl p-8 w-full max-w-sm">
        <button onClick={() => { setView("login"); setLoginMsg({ type: "", text: "" }); }} className="text-gray-400 hover:text-gray-600 text-sm mb-5 flex items-center gap-1">
          ← 뒤로
        </button>
        <h1 className="text-2xl font-bold text-gray-800 mb-6 text-center">👨‍⚕️ 상담사 로그인</h1>
        <Msg msg={loginMsg} />
        <div className="space-y-4">
          <div>
            <label className="block text-sm font-semibold text-gray-700 mb-1">전화번호</label>
            <input type="tel" value={userInfo.phone} onChange={e => setUserInfo({ ...userInfo, phone: e.target.value })} placeholder="010-1234-5678" className="w-full px-4 py-3 border-2 border-gray-300 rounded-lg focus:border-purple-500 outline-none" />
          </div>
          <div>
            <label className="block text-sm font-semibold text-gray-700 mb-1">비밀번호</label>
            <input type="password" value={userInfo.password} onChange={e => setUserInfo({ ...userInfo, password: e.target.value })} placeholder="비밀번호" className="w-full px-4 py-3 border-2 border-gray-300 rounded-lg focus:border-purple-500 outline-none" onKeyDown={e => e.key === "Enter" && counselorLogin()} />
          </div>
          <button onClick={counselorLogin} className="w-full bg-purple-700 text-white py-3 rounded-lg font-bold hover:bg-purple-800">
            로그인
          </button>
          <div className="relative">
            <div className="absolute inset-0 flex items-center"><div className="w-full border-t border-gray-200" /></div>
            <div className="relative flex justify-center"><span className="px-3 bg-white text-gray-400 text-xs">또는</span></div>
          </div>
          <button onClick={() => { setFormMsg({ type: "", text: "" }); setView("counselorSignup"); }} className="w-full bg-purple-100 text-purple-800 py-3 rounded-lg font-semibold hover:bg-purple-200">
            상담사 가입 신청
          </button>
        </div>
      </div>
    </div>
  );

  if (view === "counselorSignup") {
    const { ok: eduOk, kws: eduKws } = checkEdu(counselorForm.education);
    return (
      <div className="min-h-screen bg-gradient-to-br from-purple-50 to-pink-100 flex items-center justify-center p-4">
        <div className="bg-white rounded-2xl shadow-2xl p-8 w-full max-w-lg">
          <button onClick={() => setView("counselorLogin")} className="text-gray-400 hover:text-gray-600 text-sm mb-5 flex items-center gap-1">
            ← 뒤로
          </button>
          <h1 className="text-2xl font-bold mb-1 text-center">상담사 가입 신청</h1>
          <p className="text-gray-400 text-sm text-center mb-5">관리자 승인 후 로그인 가능합니다</p>
          <Msg msg={formMsg} />
          <div className="space-y-4">
            {[["이름", "name", "text", "홍길동"], ["전화번호 *", "phone", "tel", "010-1234-5678"], ["비밀번호 *", "password", "password", "4자리 이상"], ["자격증", "certification", "text", "청소년상담사 2급 등"]].map(([l, k, t, p]) => (
              <div key={k}>
                <label className="block text-sm font-semibold text-gray-700 mb-1">{l}</label>
                <input type={t} value={counselorForm[k]} onChange={e => setCounselorForm({ ...counselorForm, [k]: e.target.value })} placeholder={p} className="w-full px-4 py-3 border-2 border-gray-300 rounded-lg focus:border-purple-500 outline-none" />
              </div>
            ))}
            <div>
              <label className="block text-sm font-semibold text-gray-700 mb-1">최종학력 *</label>
              <input type="text" value={counselorForm.education} onChange={e => setCounselorForm({ ...counselorForm, education: e.target.value })} placeholder="OO대학교 상담심리학과 졸업" className="w-full px-4 py-3 border-2 border-gray-300 rounded-lg focus:border-purple-500 outline-none" />
              {counselorForm.education && (
                <div className={`mt-1 text-xs px-3 py-2 rounded border ${eduOk ? "bg-green-50 border-green-300 text-green-800" : "bg-yellow-50 border-yellow-300 text-yellow-800"}`}>
                  {eduOk ? `✅ 관련 학과: ${eduKws.join(", ")}` : "⚠️ 상담 관련 학과 미확인"}
                </div>
              )}
            </div>
            <div>
              <label className="block text-sm font-semibold text-gray-700 mb-1">경력</label>
              <textarea value={counselorForm.experience} onChange={e => setCounselorForm({ ...counselorForm, experience: e.target.value })} placeholder="상담 경력, 근무 경험 등" rows={3} className="w-full px-4 py-3 border-2 border-gray-300 rounded-lg focus:border-purple-500 outline-none resize-none" />
            </div>
            <div className="flex gap-3 pt-2">
              <button onClick={counselorSignup} className="flex-1 bg-purple-700 text-white py-3 rounded-lg font-bold hover:bg-purple-800">
                가입 신청
              </button>
              <button onClick={() => setView("counselorLogin")} className="flex-1 bg-gray-200 text-gray-700 py-3 rounded-lg font-semibold hover:bg-gray-300">
                취소
              </button>
            </div>
          </div>
        </div>
      </div>
    );
  }

  if (view === "masterDashboard") {
    if (!masterInfo) {
      return (
        <div style={{display:'flex',alignItems:'center',justifyContent:'center',minHeight:'100vh',flexDirection:'column',gap:'12px'}}>
          <div style={{width:'36px',height:'36px',border:'3px solid #e2e8f0',borderTopColor:'#6366f1',borderRadius:'50%',animation:'spin .8s linear infinite'}}></div>
          <p style={{color:'#94a3b8',fontSize:'14px'}}>마스터 정보 로딩 중...</p>
        </div>
      );
    }
    const freelancePending = pendingCounselors.filter(c => !c.org_id);
    const orgPending = pendingCounselors.filter(c => c.org_id);
    const ORG_TYPES = { general: '일반', church: '교회', counseling_center: '상담센터', school: '학교', company: '기업' };
    const PLAN_LABELS = { org_small: 'Small(5명/100회)', org_medium: 'Medium(15명/300회)', org_large: 'Large(50명/1000회)', org_enterprise: 'Enterprise' };

    return (
      <div className="min-h-screen bg-gray-50 p-4">
        <div className="max-w-6xl mx-auto space-y-4">

          {/* 헤더 */}
          <div className="bg-white rounded-xl shadow p-4 flex justify-between items-center">
            <div>
              <h1 className="text-xl font-bold flex items-center gap-2">👑 마스터 대시보드</h1>
              <p className="text-xs text-gray-400 mt-1">{masterInfo?.name} · 전체 시스템 관리</p>
            </div>
            <div className="flex gap-2">
              <NotificationBell phone={masterInfo?.phone} />
              <button onClick={() => { setIsMaster(false); setIsAdmin(false); setMasterInfo(null); logout(); }}
                className="bg-gray-400 text-white px-4 py-2 rounded-lg text-sm hover:bg-gray-500">로그아웃</button>
            </div>
          </div>

          {/* 통계 요약 */}
          <div className="grid grid-cols-2 md:grid-cols-4 gap-3">
            {[
              { label: '등록 단체', value: organizations.length, icon: '🏢', color: 'bg-blue-50 border-blue-200' },
              { label: '전체 상담사', value: approvedCounselors.length, icon: '👨‍⚕️', color: 'bg-green-50 border-green-200' },
              { label: '승인 대기', value: pendingCounselors.length, icon: '⏳', color: pendingCounselors.length > 0 ? 'bg-red-50 border-red-300' : 'bg-gray-50 border-gray-200' },
              { label: '개인 상담사', value: approvedCounselors.filter(c => !c.org_id).length, icon: '🧑', color: 'bg-purple-50 border-purple-200' },
            ].map((s, i) => (
              <div key={i} className={`${s.color} border rounded-xl p-4 text-center`}>
                <div className="text-2xl mb-1">{s.icon}</div>
                <div className="text-2xl font-bold text-gray-800">{s.value}</div>
                <div className="text-xs text-gray-500">{s.label}</div>
              </div>
            ))}
          </div>

          {/* 탭 */}
          <div className="flex gap-2 flex-wrap">
            {[['orgs', '🏢 단체 관리'], ['counselors', '👨‍⚕️ 상담사 관리'], ['sessions', '📊 검사 현황'], ['notices', '📢 공지사항'], ['settings', '⚙️ 시스템 설정']].map(([k, l]) => (
              <button key={k} onClick={() => setMasterTab(k)}
                className={`px-4 py-2 rounded-lg text-sm font-bold transition ${masterTab === k ? 'bg-gray-800 text-white' : 'bg-white border border-gray-300 text-gray-600 hover:bg-gray-50'}`}>
                {l}{k === 'counselors' && pendingCounselors.length > 0 && <span className="ml-1 bg-red-500 text-white text-xs px-1.5 py-0.5 rounded-full">{pendingCounselors.length}</span>}
              </button>
            ))}
          </div>

          {/* ── 단체 관리 탭 ── */}
          {masterTab === 'orgs' && (
            <div className="bg-white rounded-xl shadow p-6">
              <div className="flex items-center justify-between mb-5">
                <h2 className="text-lg font-bold">🏢 단체 관리</h2>
                <button onClick={() => { setShowOrgForm(v => !v); setOrgMsg({ type: '', text: '' }); }}
                  className="bg-blue-600 text-white px-4 py-2 rounded-lg text-sm font-bold hover:bg-blue-700 transition">
                  {showOrgForm ? '✕ 닫기' : '+ 단체 등록'}
                </button>
              </div>
              {orgMsg.text && <div className={`mb-4 rounded-lg p-3 text-sm font-semibold ${orgMsg.type === 'success' ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'}`}>{orgMsg.text}</div>}
              {showOrgForm && (
                <div className="border-2 border-blue-200 rounded-xl p-5 bg-blue-50 mb-5">
                  <h3 className="font-bold text-blue-800 mb-4 text-sm">🏢 새 단체 등록</h3>
                  <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
                    <div>
                      <label className="block text-xs font-semibold text-gray-700 mb-1">단체명 *</label>
                      <input value={orgForm.name} onChange={e => setOrgForm(f => ({ ...f, name: e.target.value }))}
                        placeholder="OO교회 / OO상담센터" className="w-full px-3 py-2 border border-blue-200 rounded-lg text-sm outline-none focus:border-blue-400 bg-white" />
                    </div>
                    <div>
                      <label className="block text-xs font-semibold text-gray-700 mb-1">단체 유형</label>
                      <select value={orgForm.org_type} onChange={e => setOrgForm(f => ({ ...f, org_type: e.target.value }))}
                        className="w-full px-3 py-2 border border-blue-200 rounded-lg text-sm outline-none bg-white">
                        {Object.entries(ORG_TYPES).map(([v, l]) => <option key={v} value={v}>{l}</option>)}
                      </select>
                    </div>
                    <div>
                      <label className="block text-xs font-semibold text-gray-700 mb-1">관리자 전화번호 *</label>
                      <input value={orgForm.admin_phone} onChange={e => setOrgForm(f => ({ ...f, admin_phone: e.target.value }))}
                        placeholder="010-0000-0000" className="w-full px-3 py-2 border border-blue-200 rounded-lg text-sm outline-none focus:border-blue-400 bg-white" />
                      <p className="text-xs text-gray-400 mt-1">기존 상담사 계정이 있으면 자동으로 org_admin 역할 부여</p>
                    </div>
                    <div>
                      <label className="block text-xs font-semibold text-gray-700 mb-1">구독 플랜</label>
                      <select value={orgForm.subscription_type} onChange={e => setOrgForm(f => ({ ...f, subscription_type: e.target.value }))}
                        className="w-full px-3 py-2 border border-blue-200 rounded-lg text-sm outline-none bg-white">
                        {Object.entries(PLAN_LABELS).map(([v, l]) => <option key={v} value={v}>{l}</option>)}
                      </select>
                    </div>
                    <div className="md:col-span-2">
                      <label className="block text-xs font-semibold text-gray-700 mb-1">설명 (선택)</label>
                      <input value={orgForm.description} onChange={e => setOrgForm(f => ({ ...f, description: e.target.value }))}
                        placeholder="단체 소개" className="w-full px-3 py-2 border border-blue-200 rounded-lg text-sm outline-none focus:border-blue-400 bg-white" />
                    </div>
                  </div>
                  <div className="flex gap-2 mt-4">
                    <button onClick={saveOrganization} disabled={orgLoading}
                      className="bg-blue-600 text-white px-5 py-2 rounded-lg text-sm font-bold hover:bg-blue-700 disabled:opacity-50 transition">
                      {orgLoading ? '저장 중...' : '💾 등록'}
                    </button>
                    <button onClick={() => setShowOrgForm(false)} className="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg text-sm font-bold hover:bg-gray-400">취소</button>
                  </div>
                </div>
              )}
              {organizations.length === 0
                ? <div className="text-center py-10 text-gray-400"><p className="text-3xl mb-2">🏢</p><p>등록된 단체가 없습니다</p></div>
                : <div className="space-y-3">
                    {organizations.map(org => (
                      <div key={org.id} className={`border rounded-xl p-4 ${org.is_active === 0 ? 'border-gray-200 bg-gray-50 opacity-60' : 'border-gray-200'}`}>
                        <div className="flex items-start justify-between gap-3">
                          <div className="flex-1">
                            <div className="flex items-center gap-2 mb-1 flex-wrap">
                              {org.is_active === 0 && <span className="text-xs bg-gray-200 text-gray-600 px-2 py-0.5 rounded-full">비활성</span>}
                              <span className="font-bold text-gray-800">{org.name}</span>
                              <span className="text-xs bg-blue-100 text-blue-700 px-2 py-0.5 rounded-full">{ORG_TYPES[org.org_type] || org.org_type}</span>
                              <span className="text-xs bg-green-100 text-green-700 px-2 py-0.5 rounded-full">{PLAN_LABELS[org.subscription_type] || org.subscription_type}</span>
                            </div>
                            <p className="text-xs text-gray-500">관리자: {org.admin_phone} · 상담사: {org.counselor_count || 0}명 · 쿼터: {org.quota_used || 0}/{org.quota_total}회</p>
                            {org.description && <p className="text-xs text-gray-400 mt-1">{org.description}</p>}
                          </div>
                          <div className="flex gap-1.5 shrink-0">
                            <button
                              onClick={() => setOrgForm({
                                ...orgForm, _editId: org.id,
                                name: org.name, description: org.description || '',
                                org_type: org.org_type, admin_phone: org.admin_phone,
                                subscription_type: org.subscription_type, billing_cycle: org.billing_cycle || 'monthly'
                              }) || setShowOrgForm(true)}
                              className="text-xs bg-indigo-100 text-indigo-700 px-2.5 py-1.5 rounded-lg hover:bg-indigo-200 font-semibold">✏️ 수정</button>
                            <button
                              onClick={async () => {
                                const newAdmin = prompt(`"${org.name}" 단체의 새 관리자 전화번호를 입력하세요:\n현재: ${org.admin_phone}`);
                                if (!newAdmin || !newAdmin.trim()) return;
                                try {
                                  const res = await authFetch(`/api/organizations/${org.id}`, {
                                    method: 'PUT',
                                    body: JSON.stringify({ admin_phone: newAdmin.trim() })
                                  });
                                  const d = await res.json();
                                  if (d.success) { setOrgMsg({ type: 'success', text: '✅ 관리자가 변경되었습니다.' }); await loadOrganizations(); }
                                  else setOrgMsg({ type: 'error', text: '❌ ' + (d.error || '실패') });
                                } catch (e) { setOrgMsg({ type: 'error', text: '❌ 오류' }); }
                              }}
                              className="text-xs bg-blue-100 text-blue-700 px-2.5 py-1.5 rounded-lg hover:bg-blue-200 font-semibold">👤 관리자 변경</button>
                            <button
                              onClick={async () => {
                                if (!confirm(`"${org.name}" 단체를 ${org.is_active === 0 ? '활성화' : '비활성화'}하시겠습니까?`)) return;
                                try {
                                  const res = await authFetch(`/api/organizations/${org.id}`, {
                                    method: 'PUT',
                                    body: JSON.stringify({ is_active: org.is_active === 0 ? 1 : 0 })
                                  });
                                  const d = await res.json();
                                  if (d.success) { setOrgMsg({ type: 'success', text: '✅ 처리 완료' }); await loadOrganizations(); }
                                  else setOrgMsg({ type: 'error', text: '❌ ' + (d.error || '실패') });
                                } catch (e) { setOrgMsg({ type: 'error', text: '❌ 오류' }); }
                              }}
                              className={`text-xs px-2.5 py-1.5 rounded-lg font-semibold ${org.is_active === 0 ? 'bg-green-100 text-green-700 hover:bg-green-200' : 'bg-red-100 text-red-700 hover:bg-red-200'}`}>
                              {org.is_active === 0 ? '🔔 활성화' : '🔕 비활성화'}
                            </button>
                          </div>
                        </div>
                      </div>
                    ))}
                  </div>
              }
            </div>
          )}

          {/* ── 상담사 관리 탭 ── */}
          {masterTab === 'counselors' && (
            <div className="space-y-4">
              {/* 개인 프리랜서 승인 대기 */}
              <div className="bg-white rounded-xl shadow p-6">
                <h2 className="text-lg font-bold mb-4">⏳ 개인 상담사 승인 대기 ({freelancePending.length}건)</h2>
                {freelancePending.length === 0
                  ? <p className="text-gray-400 text-sm">대기 중인 개인 상담사가 없습니다</p>
                  : freelancePending.map(c => (
                    <div key={c.phone} className="border rounded-lg p-4 mb-3 flex items-center justify-between">
                      <div>
                        <p className="font-semibold">{c.name} <span className="text-sm text-gray-400">{c.phone}</span></p>
                        <p className="text-xs text-gray-500">{c.counselor_type === 'biblical' ? '🕊️ 성경적상담' : '🧠 심리상담'} · {c.education || '학력 미입력'}</p>
                      </div>
                      <div className="flex gap-2">
                        <button onClick={() => approveCounselor(c.phone)} className="bg-green-600 text-white px-3 py-1.5 rounded-lg text-xs font-bold hover:bg-green-700">✅ 승인</button>
                        <button onClick={() => rejectCounselor(c.phone)} className="bg-red-500 text-white px-3 py-1.5 rounded-lg text-xs font-bold hover:bg-red-600">❌ 거부</button>
                      </div>
                    </div>
                  ))
                }
              </div>
              {/* 승인된 상담사 목록 */}
              <div className="bg-white rounded-xl shadow p-6">
                <div className="flex flex-col md:flex-row md:items-center gap-3 mb-4">
                  <h2 className="text-lg font-bold shrink-0">✅ 전체 승인 상담사 ({approvedCounselors.length}명)</h2>
                  <div className="flex flex-wrap gap-2 flex-1">
                    <input
                      type="text" value={counselorSearch}
                      onChange={e => setCounselorSearch(e.target.value)}
                      placeholder="🔍 이름 또는 전화번호 검색"
                      className="flex-1 min-w-32 px-3 py-1.5 border border-gray-200 rounded-lg text-sm outline-none focus:border-indigo-400"
                    />
                    <select value={counselorFilterOrg} onChange={e => setCounselorFilterOrg(e.target.value)}
                      className="px-2 py-1.5 border border-gray-200 rounded-lg text-xs outline-none bg-white">
                      <option value="all">전체 소속</option>
                      <option value="individual">개인</option>
                      {organizations.map(o => <option key={o.id} value={String(o.id)}>{o.name}</option>)}
                    </select>
                    <select value={counselorFilterType} onChange={e => setCounselorFilterType(e.target.value)}
                      className="px-2 py-1.5 border border-gray-200 rounded-lg text-xs outline-none bg-white">
                      <option value="all">전체 유형</option>
                      <option value="psychological">🧠 심리</option>
                      <option value="biblical">🕊️ 성경적</option>
                    </select>
                    <select value={counselorFilterStatus} onChange={e => setCounselorFilterStatus(e.target.value)}
                      className="px-2 py-1.5 border border-gray-200 rounded-lg text-xs outline-none bg-white">
                      <option value="all">전체 상태</option>
                      <option value="active">활성</option>
                      <option value="inactive">비활성</option>
                    </select>
                    {/* CSV 다운로드 버튼 */}
                    <button
                      onClick={() => {
                        const filtered = approvedCounselors.filter(c => {
                          const q = counselorSearch.toLowerCase();
                          const matchQ = !q || c.name?.toLowerCase().includes(q) || c.phone?.includes(q);
                          const matchOrg = counselorFilterOrg === 'all' ? true : counselorFilterOrg === 'individual' ? !c.org_id : String(c.org_id) === counselorFilterOrg;
                          const matchType = counselorFilterType === 'all' || c.counselor_type === counselorFilterType;
                          const matchStatus = counselorFilterStatus === 'all' || (c.status || 'active') === counselorFilterStatus;
                          return matchQ && matchOrg && matchType && matchStatus;
                        });
                        const header = '이름,전화번호,상담유형,플랜,상태,소속,가입일';
                        const rows = filtered.map(c => [
                          c.name, c.phone,
                          c.counselor_type === 'biblical' ? '성경적상담' : '심리상담',
                          c.subscription_type || 'free',
                          c.status || 'active',
                          organizations.find(o => o.id === c.org_id)?.name || '개인',
                          c.created_at ? new Date(c.created_at).toLocaleDateString('ko-KR') : ''
                        ].join(','));
                        const csv = '\uFEFF' + [header, ...rows].join('\n');
                        const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
                        const url = URL.createObjectURL(blob);
                        const a = document.createElement('a'); a.href = url;
                        a.download = `counselors_${new Date().toISOString().slice(0,10)}.csv`; a.click();
                      }}
                      className="px-3 py-1.5 bg-green-600 text-white rounded-lg text-xs font-bold hover:bg-green-700 whitespace-nowrap">
                      📥 CSV
                    </button>
                  </div>
                </div>
                {(() => {
                  const filtered = approvedCounselors.filter(c => {
                    const q = counselorSearch.toLowerCase();
                    const matchQ = !q || c.name?.toLowerCase().includes(q) || c.phone?.includes(q);
                    const matchOrg = counselorFilterOrg === 'all' ? true : counselorFilterOrg === 'individual' ? !c.org_id : String(c.org_id) === counselorFilterOrg;
                    const matchType = counselorFilterType === 'all' || c.counselor_type === counselorFilterType;
                    const matchStatus = counselorFilterStatus === 'all' || (c.status || 'active') === counselorFilterStatus;
                    return matchQ && matchOrg && matchType && matchStatus;
                  });
                  if (filtered.length === 0) return <p className="text-gray-400 text-sm text-center py-4">검색 결과가 없습니다</p>;
                  return (
                    <div className="space-y-2">
                      <p className="text-xs text-gray-400">{filtered.length}명 표시 중 (전체 {approvedCounselors.length}명)</p>
                      {filtered.map(c => (
                        <div key={c.phone} className={`border rounded-lg p-3 flex items-center justify-between ${c.status === 'inactive' ? 'opacity-50 bg-gray-50' : ''}`}>
                          <div>
                            <span className="font-semibold text-sm">{c.name}</span>
                            <span className="text-xs text-gray-400 ml-2">{c.phone}</span>
                            {c.org_id
                              ? <span className="ml-2 text-xs bg-blue-100 text-blue-700 px-2 py-0.5 rounded-full">{organizations.find(o => o.id === c.org_id)?.name || '단체소속'}</span>
                              : <span className="ml-2 text-xs bg-gray-100 text-gray-600 px-2 py-0.5 rounded-full">개인</span>}
                            {c.status === 'inactive' && <span className="ml-2 text-xs bg-red-100 text-red-600 px-1.5 py-0.5 rounded-full">비활성</span>}
                          </div>
                          <div className="flex items-center gap-2">
                            <span className="text-xs text-gray-400">{c.subscription_type || 'free'}</span>
                            <button
                              onClick={async () => {
                                const ns = c.status === 'inactive' ? 'active' : 'inactive';
                                if (!confirm(`${c.name}을 ${ns === 'inactive' ? '비활성화' : '활성화'}하시겠습니까?`)) return;
                                const res = await authFetch('/api/counselor/status', {
                                  method: 'PATCH', body: JSON.stringify({ phone: c.phone, status: ns })
                                });
                                const d = await res.json();
                                if (d.success) setApprovedCounselors(prev => prev.map(x => x.phone === c.phone ? { ...x, status: ns } : x));
                                else alert('실패: ' + d.error);
                              }}
                              className={`text-xs px-2 py-1 rounded font-semibold ${c.status === 'inactive' ? 'bg-green-100 text-green-700 hover:bg-green-200' : 'bg-orange-100 text-orange-700 hover:bg-orange-200'}`}>
                              {c.status === 'inactive' ? '🔔' : '🔕'}
                            </button>
                            <button
                              onClick={async () => {
                                if (!confirm(`⚠️ ${c.name}(${c.phone}) 계정을 완전히 삭제하시겠습니까?\n이 작업은 되돌릴 수 없습니다.`)) return;
                                const res = await authFetch(`/api/counselor/${encodeURIComponent(c.phone)}`, { method: 'DELETE' });
                                const d = await res.json();
                                if (d.success) {
                                  setApprovedCounselors(prev => prev.filter(x => x.phone !== c.phone));
                                  alert('✅ 삭제 완료');
                                } else alert('삭제 실패: ' + d.error);
                              }}
                              className="text-xs bg-red-100 text-red-700 px-2 py-1 rounded hover:bg-red-200 font-semibold">🗑️</button>
                          </div>
                        </div>
                      ))}
                    </div>
                  );
                })()}
              </div>
            </div>
          )}

          {/* ── 검사 현황 탭 ── */}
          {masterTab === 'sessions' && (
            <div className="space-y-4">
              {/* 월별 추이 카드 */}
              <MonthlyStatsCard authFetch={authFetch} />

              {/* 기존 검사 결과 테이블 */}
              <div className="bg-white rounded-xl shadow p-6">
                <div className="flex items-center justify-between mb-5">
                  <div>
                    <h2 className="text-lg font-bold">📋 전체 검사 기록</h2>
                    <p className="text-xs text-gray-500 mt-1">최대 1,000건</p>
                  </div>
                  <div className="flex gap-2">
                    {masterSessions.length > 0 && (
                      <button
                        onClick={() => {
                          const header = '검사일,단체,상담사,내담자,전화번호,검사유형,상담유형,결과요약';
                          const rows = masterSessions.map(s => [
                            new Date(s.created_at).toLocaleDateString('ko-KR'),
                            organizations.find(o => o.id === s.org_id)?.name || (s.org_id ? '단체' : '개인'),
                            s.counselor_phone || '',
                            s.client_name || '',
                            s.client_phone || '',
                            s.test_type || '',
                            s.counseling_type === 'biblical' ? '성경적상담' : '심리상담',
                            (() => { try { const r = JSON.parse(s.result_summary || '{}'); return r.level || r.score || ''; } catch { return ''; } })()
                          ].join(','));
                          const csv = '\uFEFF' + [header, ...rows].join('\n');
                          const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
                          const a = document.createElement('a'); a.href = URL.createObjectURL(blob);
                          a.download = `all_sessions_${new Date().toISOString().slice(0,10)}.csv`; a.click();
                        }}
                        className="bg-green-600 text-white px-4 py-2 rounded-lg text-sm font-bold hover:bg-green-700 transition">
                        📥 CSV
                      </button>
                    )}
                    <button
                      onClick={loadMasterSessions}
                      disabled={masterSessionsLoading}
                      className="bg-gray-700 text-white px-4 py-2 rounded-lg text-sm font-bold hover:bg-gray-800 disabled:opacity-50 transition"
                    >
                      {masterSessionsLoading ? '로딩 중...' : '🔄 새로고침'}
                    </button>
                  </div>
                </div>

              {masterSessions.length === 0 ? (
                <div className="text-center py-12 text-gray-400">
                  <p className="text-4xl mb-3">📋</p>
                  <p className="font-semibold mb-1">검사 결과가 없습니다</p>
                  <p className="text-xs">새로고침 버튼을 눌러 불러오세요</p>
                </div>
              ) : (
                <div>
                  {/* 요약 통계 */}
                  <div className="grid grid-cols-2 md:grid-cols-5 gap-3 mb-5">
                    {[
                      { label: '전체', value: masterSessions.length, icon: '📋', color: 'bg-gray-50 border-gray-200' },
                      { label: '이번 달', value: masterSessions.filter(s => new Date(s.created_at) > new Date(Date.now() - 30*24*60*60*1000)).length, icon: '📅', color: 'bg-blue-50 border-blue-200' },
                      { label: 'SCT', value: masterSessions.filter(s => s.test_type === 'SCT').length, icon: '📝', color: 'bg-purple-50 border-purple-200' },
                      { label: '심리상담', value: masterSessions.filter(s => s.counseling_type !== 'biblical').length, icon: '🧠', color: 'bg-green-50 border-green-200' },
                      { label: '성경적 상담', value: masterSessions.filter(s => s.counseling_type === 'biblical').length, icon: '🕊️', color: 'bg-amber-50 border-amber-200' },
                    ].map((stat, i) => (
                      <div key={i} className={`${stat.color} border rounded-xl p-3 text-center`}>
                        <div className="text-xl mb-1">{stat.icon}</div>
                        <div className="text-xl font-bold text-gray-800">{stat.value}</div>
                        <div className="text-xs text-gray-500">{stat.label}</div>
                      </div>
                    ))}
                  </div>

                  {/* 검사 유형별 분포 */}
                  <div className="mb-5 bg-gray-50 rounded-xl p-4">
                    <p className="text-xs font-semibold text-gray-600 mb-3">검사 유형별 분포</p>
                    <div className="flex flex-wrap gap-2">
                      {['SCT','DSI','PHQ9','GAD7','DASS21','BIG5','BURNOUT'].map(type => {
                        const count = masterSessions.filter(s => s.test_type === type).length;
                        const pct = masterSessions.length > 0 ? Math.round(count / masterSessions.length * 100) : 0;
                        return count > 0 ? (
                          <div key={type} className="bg-white border border-gray-200 rounded-lg px-3 py-2 text-center min-w-16">
                            <div className="text-xs font-bold text-gray-700">{type}</div>
                            <div className="text-lg font-bold text-blue-600">{count}</div>
                            <div className="text-xs text-gray-400">{pct}%</div>
                          </div>
                        ) : null;
                      })}
                    </div>
                  </div>

                  {/* 결과 테이블 */}
                  <div className="overflow-x-auto">
                    <table className="w-full text-xs">
                      <thead>
                        <tr className="bg-gray-50 border-b">
                          {['검사일', '단체', '상담사', '내담자', '검사', '상담 유형', '결과', ''].map(h => (
                            <th key={h} className="px-3 py-2.5 text-left text-gray-600 font-semibold whitespace-nowrap">{h}</th>
                          ))}
                        </tr>
                      </thead>
                      <tbody>
                        {masterSessions.slice(0, 200).map(s => {
                          let summary = '';
                          try {
                            const r = typeof s.result_summary === 'string' ? JSON.parse(s.result_summary) : s.result_summary;
                            if (r) summary = r.level || (r.score !== undefined ? r.score + '점' : '');
                          } catch {}
                          const orgName = organizations.find(o => o.id === s.org_id)?.name || (s.org_id ? '단체' : '개인');
                          return (
                            <tr key={s.session_id} className="border-b hover:bg-gray-50 transition">
                              <td className="px-3 py-2 text-gray-500 whitespace-nowrap">
                                {new Date(s.created_at).toLocaleDateString('ko-KR', { month: '2-digit', day: '2-digit' })}
                              </td>
                              <td className="px-3 py-2 text-gray-600 text-xs">
                                <span className={`px-1.5 py-0.5 rounded-full ${s.org_id ? 'bg-blue-100 text-blue-700' : 'bg-gray-100 text-gray-600'}`}>{orgName}</span>
                              </td>
                              <td className="px-3 py-2 font-mono text-gray-600">{s.counselor_phone ? '****' + s.counselor_phone.slice(-4) : '-'}</td>
                              <td className="px-3 py-2">{s.client_name || s.client_phone || '-'}</td>
                              <td className="px-3 py-2">
                                <span className="bg-blue-100 text-blue-700 px-2 py-0.5 rounded-full font-semibold">{s.test_type}</span>
                              </td>
                              <td className="px-3 py-2">
                                <span className={`px-1.5 py-0.5 rounded-full font-semibold ${s.counseling_type === 'biblical' ? 'bg-purple-100 text-purple-700' : 'bg-green-100 text-green-700'}`}>
                                  {s.counseling_type === 'biblical' ? '🕊️' : '🧠'}
                                </span>
                              </td>
                              <td className="px-3 py-2 text-gray-600">{summary || '-'}</td>
                              <td className="px-3 py-2">
                                <button onClick={() => deleteSession(s.session_id)}
                                  className="text-red-400 hover:text-red-600 transition">🗑️</button>
                              </td>
                            </tr>
                          );
                        })}
                      </tbody>
                    </table>
                    {masterSessions.length > 200 && (
                      <p className="text-xs text-gray-400 text-center mt-3">최신 200건 표시 중 (전체 {masterSessions.length}건)</p>
                    )}
                  </div>
                </div>
              )}
              </div>
            </div>
          )}

          {/* ── 공지사항 탭 ── */}
          {masterTab === 'notices' && (
            <div className="bg-white rounded-xl shadow p-6">
              <div className="flex items-center justify-between mb-5">
                <h2 className="text-lg font-bold">📢 공지사항 관리</h2>
                <button onClick={() => { setShowNoticeForm(v => !v); setNoticeMsg({ type: '', text: '' }); }}
                  className="bg-indigo-600 text-white px-4 py-2 rounded-lg text-sm font-bold hover:bg-indigo-700 transition">
                  {showNoticeForm ? '✕ 닫기' : '+ 공지 등록'}
                </button>
              </div>

              {noticeMsg.text && (
                <div className={`mb-4 p-3 rounded-lg text-sm font-semibold ${noticeMsg.type === 'success' ? 'bg-green-100 text-green-800' : noticeMsg.type === 'info' ? 'bg-blue-100 text-blue-800' : 'bg-red-100 text-red-800'}`}>
                  {noticeMsg.text}
                </div>
              )}

              {showNoticeForm && (
                <div className="border-2 border-indigo-100 rounded-xl p-5 bg-indigo-50 mb-5 space-y-3">
                  <div>
                    <label className="block text-xs font-semibold text-gray-600 mb-1">제목 *</label>
                    <input value={noticeForm.title} onChange={e => setNoticeForm(f => ({ ...f, title: e.target.value }))}
                      placeholder="공지사항 제목" className="w-full px-3 py-2 border border-indigo-200 rounded-lg text-sm outline-none bg-white focus:border-indigo-400" />
                  </div>
                  <div>
                    <label className="block text-xs font-semibold text-gray-600 mb-1">내용 *</label>
                    <textarea value={noticeForm.content} onChange={e => setNoticeForm(f => ({ ...f, content: e.target.value }))}
                      placeholder="공지 내용을 입력하세요" rows={5}
                      className="w-full px-3 py-2 border border-indigo-200 rounded-lg text-sm outline-none bg-white focus:border-indigo-400 resize-y" />
                  </div>
                  <div className="grid grid-cols-2 gap-3">
                    <div>
                      <label className="block text-xs font-semibold text-gray-600 mb-1">대상</label>
                      <select value={noticeForm.target} onChange={e => setNoticeForm(f => ({ ...f, target: e.target.value }))}
                        className="w-full px-3 py-2 border border-indigo-200 rounded-lg text-sm outline-none bg-white">
                        <option value="all">전체 상담사</option>
                        <option value="counselor">일반 상담사</option>
                        <option value="org_admin">단체 관리자</option>
                      </select>
                    </div>
                    <div className="flex flex-col gap-2 justify-end">
                      <label className="flex items-center gap-2 text-xs text-gray-600 cursor-pointer">
                        <input type="checkbox" checked={noticeForm.pinned}
                          onChange={e => setNoticeForm(f => ({ ...f, pinned: e.target.checked }))} />
                        📌 상단 고정
                      </label>
                      <label className="flex items-center gap-2 text-xs text-gray-600 cursor-pointer">
                        <input type="checkbox" checked={noticeForm.send_notification}
                          onChange={e => setNoticeForm(f => ({ ...f, send_notification: e.target.checked }))} />
                        🔔 인앱 알림 발송
                      </label>
                    </div>
                  </div>
                  <div className="flex gap-2">
                    <button onClick={saveNotice}
                      className="bg-indigo-600 text-white px-4 py-2 rounded-lg text-sm font-bold hover:bg-indigo-700">💾 등록</button>
                    <button onClick={() => setShowNoticeForm(false)}
                      className="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg text-sm font-bold hover:bg-gray-400">취소</button>
                  </div>
                </div>
              )}

              {notices.length === 0 ? (
                <div className="text-center py-10 text-gray-400">
                  <p className="text-3xl mb-2">📢</p>
                  <p>등록된 공지사항이 없습니다</p>
                </div>
              ) : (
                <div className="space-y-3">
                  {notices.map(n => (
                    <div key={n.id} className={`border rounded-xl p-4 ${n.pinned ? 'border-indigo-300 bg-indigo-50' : 'border-gray-200'}`}>
                      <div className="flex items-start justify-between gap-3">
                        <div className="flex-1">
                          <div className="flex items-center gap-2 mb-1">
                            {n.pinned ? <span className="text-xs bg-indigo-600 text-white px-2 py-0.5 rounded-full font-semibold">📌 고정</span> : null}
                            <span className={`text-xs px-2 py-0.5 rounded-full font-semibold ${n.target === 'all' ? 'bg-gray-100 text-gray-600' : n.target === 'org_admin' ? 'bg-blue-100 text-blue-700' : 'bg-purple-100 text-purple-700'}`}>
                              {n.target === 'all' ? '전체' : n.target === 'org_admin' ? '단체관리자' : '상담사'}
                            </span>
                            <span className="font-bold text-gray-800 text-sm">{n.title}</span>
                          </div>
                          <p className="text-xs text-gray-500 line-clamp-2">{n.content}</p>
                          <p className="text-xs text-gray-400 mt-1">{new Date(n.created_at).toLocaleDateString('ko-KR')}</p>
                        </div>
                        <div className="flex gap-1 shrink-0">
                          <button onClick={() => toggleNoticePin(n.id, n.pinned)}
                            className={`text-xs px-2 py-1 rounded font-semibold ${n.pinned ? 'bg-gray-100 text-gray-600 hover:bg-gray-200' : 'bg-indigo-100 text-indigo-700 hover:bg-indigo-200'}`}>
                            {n.pinned ? '📌 해제' : '📌 고정'}
                          </button>
                          <button onClick={() => deleteNotice(n.id)}
                            className="text-xs bg-red-100 text-red-600 px-2 py-1 rounded hover:bg-red-200">🗑️</button>
                        </div>
                      </div>
                    </div>
                  ))}
                </div>
              )}
            </div>
          )}

          {/* ── 시스템 설정 탭 ── */}
          {masterTab === 'settings' && (
            <div className="space-y-4">
              {/* 마스터 비밀번호 변경 */}
              <div className="bg-white rounded-xl shadow p-6">
                <h2 className="text-lg font-bold mb-4">🔐 마스터 비밀번호 변경</h2>
                <PasswordChangeForm masterInfo={masterInfo} authFetch={authFetch} />
                
              </div>

              {/* API 키 + 참고자료 */}
              <div className="bg-amber-50 border border-amber-200 rounded-xl p-4 text-sm text-amber-800">
                💡 API 키 관리, 성경적 상담 참고자료 관리는 아래에서 확인하세요.
              </div>
              <div className="bg-white rounded-xl shadow p-6">
                <h2 className="text-lg font-bold mb-2">⚙️ 상세 시스템 설정</h2>
                <button onClick={() => setView('admin')} className="bg-gray-700 text-white px-4 py-2 rounded-lg text-sm font-bold hover:bg-gray-800">
                  🔧 API 키 · 참고자료 · 검사 현황 설정 열기
                </button>
              </div>
            </div>
          )}
        </div>
      </div>
    );
  }

  if (view === "orgAdminDashboard") {
    if (!orgAdminInfo) return <div style={{display:'flex',alignItems:'center',justifyContent:'center',minHeight:'100vh'}}><p style={{color:'#94a3b8'}}>로딩 중...</p></div>;
    return (
      <div className="min-h-screen bg-gray-50 p-4">
        <div className="max-w-6xl mx-auto">
          {/* 헤더 */}
          <div className="bg-white rounded-xl shadow p-6 mb-4">
            <div className="flex justify-between items-center">
              <div>
                <h1 className="text-2xl font-bold text-blue-800">🏢 단체 관리자 대시보드</h1>
                <p className="text-gray-500 text-sm mt-1">
                  {orgAdminInfo?.org_name} | {orgAdminInfo?.name}
                </p>
              </div>
              <button onClick={logout} className="bg-gray-400 text-white px-4 py-2 rounded-lg hover:bg-gray-500 text-sm">
                로그아웃
              </button>
            </div>
          </div>

          {/* 탭 */}
          <div className="bg-white rounded-xl shadow mb-4">
            <div className="flex border-b">
              <button
                onClick={() => setOrgAdminTab('counselors')}
                className={`flex-1 py-3 px-4 font-semibold ${orgAdminTab === 'counselors' ? 'border-b-2 border-blue-600 text-blue-600' : 'text-gray-500'}`}
              >
                👨‍⚕️ 소속 상담사
              </button>
              <button
                onClick={() => setOrgAdminTab('sessions')}
                className={`flex-1 py-3 px-4 font-semibold ${orgAdminTab === 'sessions' ? 'border-b-2 border-blue-600 text-blue-600' : 'text-gray-500'}`}
              >
                📊 검사 결과
              </button>
            </div>
          </div>

          {/* 소속 상담사 탭 */}
          {orgAdminTab === 'counselors' && (
            <div className="bg-white rounded-xl shadow p-6">
              <h2 className="text-lg font-bold text-gray-800 mb-4">소속 상담사 목록</h2>
              {orgCounselors.length === 0 ? (
                <div className="text-center py-12 text-gray-400">
                  <div className="text-4xl mb-2">👥</div>
                  <p>소속 상담사가 없습니다</p>
                  <p className="text-xs mt-1">관리자에게 상담사 배정을 요청하세요</p>
                </div>
              ) : (
                <div className="overflow-x-auto">
                  <table className="w-full">
                    <thead className="bg-gray-50">
                      <tr>
                        <th className="px-4 py-2 text-left text-xs font-semibold text-gray-600">이름</th>
                        <th className="px-4 py-2 text-left text-xs font-semibold text-gray-600">전화번호</th>
                        <th className="px-4 py-2 text-left text-xs font-semibold text-gray-600">쿼터</th>
                        <th className="px-4 py-2 text-left text-xs font-semibold text-gray-600">상태</th>
                      </tr>
                    </thead>
                    <tbody>
                      {orgCounselors.map((c, i) => (
                        <tr key={i} className="border-t hover:bg-gray-50">
                          <td className="px-4 py-3 text-sm">{c.name}</td>
                          <td className="px-4 py-3 text-sm font-mono">{c.phone}</td>
                          <td className="px-4 py-3 text-sm">
                            {c.quota_used || 0} / {c.quota_total || 0}
                          </td>
                          <td className="px-4 py-3">
                            <span className={`px-2 py-1 rounded-full text-xs font-semibold ${c.is_approved ? 'bg-green-100 text-green-700' : 'bg-yellow-100 text-yellow-700'}`}>
                              {c.is_approved ? '활성' : '대기'}
                            </span>
                          </td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                </div>
              )}
            </div>
          )}

          {/* 검사 결과 탭 */}
          {orgAdminTab === 'sessions' && (
            <div className="bg-white rounded-xl shadow p-6">
              <h2 className="text-lg font-bold text-gray-800 mb-4">조직 검사 결과</h2>
              <div className="text-center py-12 text-gray-400">
                <div className="text-4xl mb-2">📊</div>
                <p>검사 결과가 없습니다</p>
                <p className="text-xs mt-1">상담사가 검사를 진행하면 여기에 표시됩니다</p>
              </div>
            </div>
          )}
        </div>
      </div>
    );
  }

  if (view === "counselorDashboard") {
    const counselorSessions = getCounselorSessions();
    // subscription 기본값 보장
    const sub = subscription || { quota_total: 0, quota_used: 0, subscription_type: 'free' };
    const remaining = sub.quota_total - sub.quota_used;
    const usagePercent = sub.quota_total > 0 ? (sub.quota_used / sub.quota_total * 100) : 0;
    
    return (
      <div className="min-h-screen bg-gray-50 p-4">
        <div className="max-w-5xl mx-auto space-y-4">
          <div className="bg-white rounded-xl shadow p-4 flex justify-between items-center">
            <div>
              <h1 className="text-xl font-bold">👨‍⚕️ 상담사 대시보드</h1>
              <p className="text-sm text-gray-400">{counselorPhone}</p>
            </div>
            <div className="flex gap-2">
              <label className="bg-green-600 text-white px-4 py-2 rounded-lg text-sm font-semibold hover:bg-green-700 cursor-pointer flex items-center gap-2">
                📂 불러오기
                <input 
                  type="file" 
                  accept=".json" 
                  onChange={handleFileUpload} 
                  className="hidden"
                />
              </label>
              <button onClick={() => { loadAllSubmitted(); setView("counselorResults"); }} className="bg-purple-600 text-white px-4 py-2 rounded-lg text-sm font-semibold hover:bg-purple-700 relative">
                📊 제출된 검사
                {counselorSessions.length > 0 && (
                  <span className="absolute -top-1 -right-1 bg-red-500 text-white text-xs w-5 h-5 rounded-full flex items-center justify-center">
                    {counselorSessions.length}
                  </span>
                )}
              </button>
              <button onClick={logout} className="bg-gray-400 text-white px-4 py-2 rounded-lg text-sm hover:bg-gray-500">
                로그아웃
              </button>
            </div>
          </div>

          {/* 구독 정보 카드 */}
          {subscription && (
            <div className="bg-gradient-to-r from-purple-500 to-pink-500 rounded-xl shadow-lg p-6 text-white">
              <div className="flex justify-between items-start mb-4">
                <div>
                  <h3 className="text-2xl font-bold mb-1">💳 구독 정보</h3>
                  <p className="text-purple-100 text-sm">
                    {subscription.subscription_type === 'free' && '무료 체험'}
                    {subscription.subscription_type === 'basic' && 'Basic 월간 플랜'}
                    {subscription.subscription_type === 'professional' && 'Professional 월간 플랜'}
                    {subscription.subscription_type === 'basic_annual' && 'Basic 연간 플랜'}
                    {subscription.subscription_type === 'professional_annual' && 'Professional 연간 플랜'}
                  </p>
                </div>
                {subscription.subscription_type === 'free' && (
                  <button 
                    onClick={() => setView("pricingPlans")}
                    className="bg-white text-purple-600 px-4 py-2 rounded-lg font-semibold text-sm hover:bg-purple-50 transition"
                  >
                    업그레이드 ⚡
                  </button>
                )}
              </div>
              
              <div className="grid grid-cols-3 gap-4 mb-3">
                <div className="bg-white/20 rounded-lg p-3">
                  <p className="text-purple-100 text-xs mb-1">총 쿼터</p>
                  <p className="text-2xl font-bold">{subscription?.quota_total ?? 0}</p>
                </div>
                <div className="bg-white/20 rounded-lg p-3">
                  <p className="text-purple-100 text-xs mb-1">사용함</p>
                  <p className="text-2xl font-bold">{subscription?.quota_used ?? 0}</p>
                </div>
                <div className="bg-white/20 rounded-lg p-3">
                  <p className="text-purple-100 text-xs mb-1">남은 쿼터</p>
                  <p className="text-2xl font-bold text-yellow-300">{remaining}</p>
                </div>
              </div>
              
              <div className="bg-white/20 rounded-full h-3 overflow-hidden mb-2">
                <div 
                  className="bg-yellow-300 h-full transition-all duration-500"
                  style={{ width: `${usagePercent}%` }}
                />
              </div>
              <p className="text-purple-100 text-xs text-center">
                {remaining > 0 ? `${remaining}회 남음 (${usagePercent.toFixed(0)}% 사용)` : '⚠️ 쿼터가 모두 소진되었습니다. 플랜을 업그레이드하세요.'}
              </p>

              {/* AI 분석 사용 현황 (무료 플랜만 표시) */}
              {subscription.subscription_type === 'free' && (
                <div className="mt-4 pt-4 border-t border-white/30">
                  <div className="flex items-center justify-between mb-2">
                    <p className="text-sm font-semibold text-white flex items-center gap-1.5">
                      ✨ AI 실시간 분석
                    </p>
                    <span className={`text-xs px-2 py-0.5 rounded-full font-bold ${
                      aiUsageCount >= FREE_AI_LIMIT
                        ? "bg-red-400 text-white"
                        : aiUsageCount >= FREE_AI_LIMIT - 2
                        ? "bg-amber-300 text-amber-900"
                        : "bg-white/30 text-white"
                    }`}>
                      {aiUsageCount >= FREE_AI_LIMIT
                        ? "사용 완료"
                        : `${aiUsageCount} / ${FREE_AI_LIMIT}회 사용`}
                    </span>
                  </div>
                  <div className="bg-white/20 rounded-full h-2 overflow-hidden mb-2">
                    <div
                      className={`h-full rounded-full transition-all duration-500 ${
                        aiUsageCount >= FREE_AI_LIMIT ? "bg-red-400" : "bg-white"
                      }`}
                      style={{ width: `${Math.min(100, (aiUsageCount / FREE_AI_LIMIT) * 100)}%` }}
                    />
                  </div>
                  {aiUsageCount >= FREE_AI_LIMIT ? (
                    <div className="flex items-center justify-between">
                      <p className="text-xs text-red-200">무료 AI 분석 횟수를 모두 사용했습니다.</p>
                      <button
                        onClick={() => setView("pricingPlans")}
                        className="text-xs bg-white text-purple-600 px-3 py-1 rounded-lg font-bold hover:bg-purple-50 transition"
                      >
                        업그레이드
                      </button>
                    </div>
                  ) : (
                    <p className="text-xs text-purple-200">
                      {FREE_AI_LIMIT - aiUsageCount}회 남음 · 유료 플랜은 무제한 제공
                    </p>
                  )}
                </div>
              )}
              {subscription.subscription_type !== 'free' && (
                <div className="mt-4 pt-4 border-t border-white/30 flex items-center gap-2">
                  <span className="text-white text-sm">✨ AI 실시간 분석</span>
                  <span className="bg-white/30 text-white text-xs px-2 py-0.5 rounded-full font-semibold">무제한</span>
                </div>
              )}
            </div>
          )}

          <div className="bg-white rounded-xl shadow p-6">
            <h2 className="text-lg font-bold text-gray-800 mb-4">🔗 검사 링크 생성</h2>
            <Msg msg={formMsg} />
            <div className="grid grid-cols-2 gap-4 mb-4">
              <div>
                <label className="block text-sm font-semibold text-gray-600 mb-1">내담자 이름</label>
                <input value={linkForm.clientName} onChange={e => setLinkForm({ ...linkForm, clientName: e.target.value })} placeholder="홍길동" className="w-full px-4 py-3 border-2 border-gray-200 rounded-lg focus:border-purple-400 outline-none" />
              </div>
              <div>
                <label className="block text-sm font-semibold text-gray-600 mb-1">내담자 전화번호</label>
                <input type="tel" value={linkForm.clientPhone} onChange={e => setLinkForm({ ...linkForm, clientPhone: e.target.value })} placeholder="010-1234-5678" className="w-full px-4 py-3 border-2 border-gray-200 rounded-lg focus:border-purple-400 outline-none" />
              </div>
            </div>
            <div className="mb-4">
              <label className="block text-sm font-semibold text-gray-600 mb-1">
                검사 유형 선택 <span className="text-purple-600 font-bold">(복수 선택 가능)</span>
                {linkForm.testTypes.length > 0 && (
                  <span className="ml-2 px-2 py-0.5 bg-purple-100 text-purple-700 rounded-full text-xs font-bold">
                    {linkForm.testTypes.length}개 선택됨
                  </span>
                )}
              </label>
              <div className="grid grid-cols-2 gap-2 mb-2">
                {[
                  ["SCT", "📝 문장완성검사"],
                  ["DSI", "🔍 자아분화검사"],
                  ["PHQ9", "😔 우울증 선별(PHQ-9)"],
                  ["GAD7", "😰 불안장애 선별(GAD-7)"],
                  ["DASS21", "📊 우울/불안/스트레스(DASS-21)"],
                  ["BIG5", "🌟 Big5 성격검사"],
                  ["BURNOUT", "🔥 번아웃 진단(K-MBI+)"],
                  ["LOST", "🧭 행동 운영체계(LOST)"]
                ].map(([v, l]) => {
                  const isSelected = linkForm.testTypes.includes(v);
                  const idx = linkForm.testTypes.indexOf(v);
                  return (
                    <button
                      key={v}
                      onClick={() => {
                        const cur = linkForm.testTypes;
                        setLinkForm({
                          ...linkForm,
                          testTypes: isSelected
                            ? cur.filter(t => t !== v)
                            : [...cur, v]
                        });
                      }}
                      className={`py-3 px-2 rounded-xl font-semibold border-2 transition text-sm relative ${
                        isSelected
                          ? "border-purple-500 bg-purple-50 text-purple-800"
                          : "border-gray-200 text-gray-600 hover:border-purple-300"
                      }`}
                    >
                      {isSelected && (
                        <span className="absolute top-1.5 right-1.5 w-5 h-5 bg-purple-600 text-white rounded-full text-xs flex items-center justify-center font-bold">
                          {idx + 1}
                        </span>
                      )}
                      {l}
                    </button>
                  );
                })}
              </div>
              {linkForm.testTypes.length > 0 ? (
                <div className="bg-purple-50 border border-purple-200 rounded-lg p-3">
                  <p className="text-xs font-bold text-purple-700 mb-1">📋 선택된 검사 순서 (내담자가 이 순서로 진행)</p>
                  <div className="flex flex-wrap gap-1.5">
                    {linkForm.testTypes.map((t, i) => (
                      <span key={t} className="px-2 py-1 bg-purple-600 text-white rounded-full text-xs font-bold">
                        {i+1}. {t}
                      </span>
                    ))}
                  </div>
                  <p className="text-xs text-purple-500 mt-1.5">※ 검사 1개 묶음 = 쿼터 1회 차감</p>
                </div>
              ) : (
                <p className="text-xs text-red-500 font-semibold">⚠️ 검사를 1개 이상 선택하세요</p>
              )}
            </div>
            <div className="mb-4">
              <label className="block text-sm font-semibold text-gray-600 mb-2">상담 유형</label>
              <div className="flex gap-3">
                {[["psychological", "🧠 심리상담"], ["biblical", "🕊️ 성경적 상담"]].map(([v, l]) => (
                  <button key={v} onClick={() => setLinkForm({ ...linkForm, counselingType: v })} className={`flex-1 py-3 rounded-xl font-semibold border-2 transition ${linkForm.counselingType === v ? "border-blue-500 bg-blue-50 text-blue-800" : "border-gray-200 text-gray-500 hover:border-blue-300"}`}>
                    {l}
                  </button>
                ))}
              </div>
              <p className="text-xs text-gray-500 mt-2">
                {linkForm.counselingType === "biblical"
                  ? "성경적 상담: 성경 말씀과 기독교 신앙을 기반으로 한 해석과 권장사항을 제공합니다."
                  : "심리상담: 심리학 이론과 과학적 접근을 기반으로 한 해석과 권장사항을 제공합니다."}
              </p>
            </div>
            <button onClick={generateLink} disabled={linkForm.testTypes.length === 0} className={`w-full py-4 rounded-xl font-bold text-lg transition ${linkForm.testTypes.length === 0 ? "bg-gray-300 text-gray-500 cursor-not-allowed" : "bg-purple-600 text-white hover:bg-purple-700"}`}>
              ✨ 검사 링크 생성 {linkForm.testTypes.length > 0 ? `(${linkForm.testTypes.length}개 검사)` : ""}
            </button>
          </div>

          <div className="bg-white rounded-xl shadow p-6">
            <h2 className="text-lg font-bold text-gray-800 mb-4">생성된 링크 ({generatedLinks.length}건)</h2>
            {generatedLinks.length === 0 ? (
              <div className="text-center py-10 text-gray-400">
                <div className="text-4xl mb-2">🔗</div>
                <p>생성된 링크가 없습니다</p>
              </div>
            ) : (
              <div className="space-y-3">
                {generatedLinks.map((link, i) => (
                  <div key={i} className={`border-2 rounded-xl p-4 transition ${link.status === "completed" ? "border-green-200 bg-green-50" : "border-gray-100 hover:border-purple-200"}`}>
                    <div className="flex items-start justify-between gap-3 flex-wrap">
                      <div className="flex-1 min-w-0">
                        <div className="flex items-center gap-2 mb-1 flex-wrap">
                          <span className="font-bold text-gray-800 text-base">{link.clientName}</span>
                          <span className="text-gray-500 text-sm">{link.clientPhone}</span>
                          {(link.testTypes || [link.testType]).map(t => (
                            <span key={t} className={`px-2 py-0.5 rounded text-xs font-bold ${t === "SCT" ? "bg-blue-100 text-blue-800" : t === "DSI" ? "bg-green-100 text-green-800" : t === "PHQ9" ? "bg-yellow-100 text-yellow-800" : t === "GAD7" ? "bg-orange-100 text-orange-800" : t === "DASS21" ? "bg-pink-100 text-pink-800" : t === "BIG5" ? "bg-purple-100 text-purple-800" : t === "BURNOUT" ? "bg-red-100 text-red-800" : t === "LOST" ? "bg-teal-100 text-teal-800" : "bg-gray-100 text-gray-800"}`}>
                              {t}
                            </span>
                          ))}
                          <span className={`px-2 py-0.5 rounded text-xs font-bold ${link.status === "completed" ? "bg-green-200 text-green-800" : "bg-yellow-100 text-yellow-700"}`}>
                            {link.status === "completed" ? "✅ 완료" : "⏳ 대기중"}
                          </span>
                        </div>
                        <p className="text-xs text-gray-400">생성: {new Date(link.createdAt).toLocaleString("ko-KR")}</p>
                        {showLinkId === link.linkId && (
                          <div className="mt-3 bg-indigo-50 border border-indigo-200 rounded-lg p-3">
                            <p className="text-xs text-indigo-600 font-bold mb-2">📋 내담자에게 아래 ID를 전달하세요:</p>
                            <div className="flex items-center gap-2">
                              <code className="flex-1 text-xs bg-white border border-indigo-300 rounded px-3 py-2 text-indigo-800 font-mono break-all select-all cursor-text">
                                {link.linkId}
                              </code>
                            </div>
                            <p className="text-xs text-indigo-400 mt-2">내담자는 메인 화면에서 이 ID를 입력 → 전화번호 확인 → 검사 시작</p>
                          </div>
                        )}
                      </div>
                      <div className="flex flex-col gap-2 shrink-0">
                        <button onClick={() => copyLink(link.linkId)} className={`px-4 py-2 rounded-lg text-sm font-bold transition whitespace-nowrap ${copiedId === link.linkId ? "bg-green-500 text-white" : "bg-indigo-600 text-white hover:bg-indigo-700"}`}>
                          {copiedId === link.linkId ? "✅ 복사됨!" : "📋 링크 ID 복사"}
                        </button>
                        <button onClick={() => setShowLinkId(showLinkId === link.linkId ? null : link.linkId)} className="px-4 py-2 rounded-lg text-sm font-semibold bg-gray-100 text-gray-600 hover:bg-gray-200 transition">
                          {showLinkId === link.linkId ? "🔼 닫기" : "🔍 ID 보기"}
                        </button>
                      </div>
                    </div>
                  </div>
                ))}
              </div>
            )}
          </div>

          {counselorSessions.length > 0 && (
            <div className="bg-white rounded-xl shadow p-6">
              <div className="flex justify-between items-center mb-4">
                <h2 className="text-lg font-bold text-gray-800">📊 최근 제출된 검사 ({counselorSessions.length}건)</h2>
                <button onClick={() => setView("counselorResults")} className="text-sm text-purple-600 font-semibold hover:text-purple-800">
                  전체 보기 →
                </button>
              </div>
              <div className="space-y-2">
                {counselorSessions.slice(0, 3).map((s, idx) => (
                  <div key={s.sessionId} className="flex items-center justify-between p-3 border border-gray-200 rounded-lg hover:bg-gray-50 transition">
                    <div className="flex items-center gap-3">
                      <span className="text-gray-400 text-sm font-semibold">{idx + 1}</span>
                      <span className={`px-2 py-0.5 rounded text-xs font-bold ${s.testType === "SCT" ? "bg-blue-100 text-blue-800" : "bg-green-100 text-green-800"}`}>
                        {s.testType}
                      </span>
                      <div>
                        <p className="text-sm font-semibold text-gray-700">{s.userPhone}</p>
                        <p className="text-xs text-gray-400">{new Date(s.createdAt).toLocaleString("ko-KR")}</p>
                      </div>
                    </div>
                    <button onClick={() => viewSession(s.sessionId)} className="bg-blue-600 text-white px-3 py-1.5 rounded-lg text-xs font-bold hover:bg-blue-700">
                      결과 보기
                    </button>
                  </div>
                ))}
              </div>
            </div>
          )}

          <div className="bg-indigo-50 border border-indigo-200 rounded-xl p-4 text-sm text-indigo-800">
            <p className="font-bold mb-2">📌 내담자 검사 진행 방법</p>
            <ol className="space-y-1 list-decimal list-inside text-indigo-700 text-sm">
              <li>링크 생성 후 <strong>📋 링크 ID 복사</strong> 클릭</li>
              <li>복사된 ID를 문자/카카오톡으로 내담자에게 전달</li>
              <li>내담자가 메인 화면에서 ID 입력 → 전화번호 + 비밀번호 입력 → 검사 시작</li>
              <li>검사 완료 후 상태가 <strong>✅ 완료</strong>로 변경되며, 위에 제출된 검사로 표시됨</li>
            </ol>
          </div>
        </div>
      </div>
    );
  }

  if (view === "counselorResults") {
    const counselorSessions = getCounselorSessions();
    
    return (
      <div className="min-h-screen bg-gray-50 p-4">
        <div className="max-w-5xl mx-auto bg-white rounded-xl shadow p-6">
          <div className="flex justify-between items-center mb-6">
            <h1 className="text-xl font-bold">📊 제출된 검사 목록 ({counselorSessions.length}건)</h1>
            <div className="flex gap-2">
              <button onClick={() => loadAllSubmitted()} className="bg-blue-500 text-white px-4 py-2 rounded-lg text-sm font-semibold hover:bg-blue-600">
                🔄 새로고침
              </button>
              <button onClick={() => setView("counselorDashboard")} className="bg-purple-100 text-purple-800 px-4 py-2 rounded-lg text-sm font-semibold">
                ← 대시보드
              </button>
              <button onClick={logout} className="bg-gray-400 text-white px-4 py-2 rounded-lg text-sm">
                로그아웃
              </button>
            </div>
          </div>
          <SessionList sessions={counselorSessions} onView={viewSession} />
        </div>
      </div>
    );
  }

  if (view === "sctTest") return (
    <div className="min-h-screen bg-gray-50 p-4">
      <div className="max-w-3xl mx-auto bg-white rounded-xl shadow p-6">
        {pendingTests.length > 1 && (
          <div className="mb-4 bg-purple-50 border border-purple-200 rounded-xl p-3">
            <p className="text-xs font-bold text-purple-700 mb-2">📋 검사 진행 현황 ({currentTestIndex + 1}/{pendingTests.length})</p>
            <div className="flex gap-2 flex-wrap">
              {pendingTests.map((t, i) => (
                <span key={t} className={`px-3 py-1 rounded-full text-xs font-bold border ${i < currentTestIndex ? "bg-green-100 border-green-300 text-green-700" : i === currentTestIndex ? "bg-purple-600 text-white border-purple-600" : "bg-gray-100 border-gray-300 text-gray-400"}`}>
                  {i < currentTestIndex ? "✅ " : i === currentTestIndex ? "▶ " : ""}{t}
                </span>
              ))}
            </div>
            <div className="mt-2 bg-gray-200 rounded-full h-1.5">
              <div className="bg-purple-500 h-1.5 rounded-full transition-all" style={{width: `${((currentTestIndex) / pendingTests.length) * 100}%`}}></div>
            </div>
          </div>
        )}
        <h1 className="text-2xl font-bold text-center text-blue-800 mb-1">📝 문장완성검사 (SCT)</h1>
        <p className="text-center text-gray-400 text-sm mb-2">아래 문장을 자유롭게 완성해 주세요 (50문항)</p>
        <div className="bg-blue-50 border border-blue-200 rounded-lg p-2 text-xs text-blue-700 mb-6 text-center">
          진행: <strong>{Object.values(sctResponses).filter(v => v?.trim()).length}</strong> / 50 문항
        </div>
        {saveStatus && <div className="mb-4 p-3 bg-yellow-50 border border-yellow-300 rounded text-sm text-yellow-800 text-center">{saveStatus}</div>}
        <div className="space-y-4">
          {Object.keys(sctQ).map(n => (
            <div key={n} className="border-b border-gray-100 pb-4">
              <label className="block mb-1.5 font-semibold text-gray-700 text-sm">{n}. {sctQ[n]}</label>
              <input type="text" value={sctResponses[n] || ""} onChange={e => setSctResponses(p => ({ ...p, [n]: e.target.value }))} placeholder="답변을 입력하세요..." className={`w-full px-4 py-2.5 border-2 rounded-lg outline-none text-sm transition ${sctResponses[n]?.trim() ? "border-green-300 bg-green-50 focus:border-green-500" : "border-gray-200 focus:border-blue-400"}`} />
            </div>
          ))}
        </div>
        <div className="mt-8 text-center">
          <button onClick={submitSct} className="bg-blue-600 text-white px-10 py-3 rounded-xl font-bold text-lg hover:bg-blue-700 transition">
            {pendingTests.length > 1 && currentTestIndex < pendingTests.length - 1 ? `다음 검사로 → (${currentTestIndex + 1}/${pendingTests.length})` : "검사 제출"} ({Object.values(sctResponses).filter(v => v?.trim()).length}/50)
          </button>
        </div>
      </div>
    </div>
  );

  if (view === "dsiTest") return (
    <div className="min-h-screen bg-gray-50 p-4">
      <div className="max-w-3xl mx-auto bg-white rounded-xl shadow p-6">
        {pendingTests.length > 1 && (
          <div className="mb-4 bg-purple-50 border border-purple-200 rounded-xl p-3">
            <p className="text-xs font-bold text-purple-700 mb-2">📋 검사 진행 현황 ({currentTestIndex + 1}/{pendingTests.length})</p>
            <div className="flex gap-2 flex-wrap">
              {pendingTests.map((t, i) => (
                <span key={t} className={`px-3 py-1 rounded-full text-xs font-bold border ${i < currentTestIndex ? "bg-green-100 border-green-300 text-green-700" : i === currentTestIndex ? "bg-purple-600 text-white border-purple-600" : "bg-gray-100 border-gray-300 text-gray-400"}`}>
                  {i < currentTestIndex ? "✅ " : i === currentTestIndex ? "▶ " : ""}{t}
                </span>
              ))}
            </div>
            <div className="mt-2 bg-gray-200 rounded-full h-1.5">
              <div className="bg-purple-500 h-1.5 rounded-full transition-all" style={{width: `${((currentTestIndex) / pendingTests.length) * 100}%`}}></div>
            </div>
          </div>
        )}
        {pendingTests.length > 1 && (
          <div className="mb-4 bg-purple-50 border border-purple-200 rounded-xl p-3">
            <p className="text-xs font-bold text-purple-700 mb-2">📋 검사 진행 현황 ({currentTestIndex + 1}/{pendingTests.length})</p>
            <div className="flex gap-2 flex-wrap">
              {pendingTests.map((t, i) => (
                <span key={t} className={`px-3 py-1 rounded-full text-xs font-bold border ${i < currentTestIndex ? "bg-green-100 border-green-300 text-green-700" : i === currentTestIndex ? "bg-purple-600 text-white border-purple-600" : "bg-gray-100 border-gray-300 text-gray-400"}`}>
                  {i < currentTestIndex ? "✅ " : i === currentTestIndex ? "▶ " : ""}{t}
                </span>
              ))}
            </div>
            <div className="mt-2 bg-gray-200 rounded-full h-1.5">
              <div className="bg-purple-500 h-1.5 rounded-full transition-all" style={{width: `${((currentTestIndex) / pendingTests.length) * 100}%`}}></div>
            </div>
          </div>
        )}
        <h1 className="text-2xl font-bold text-center text-green-800 mb-1">🔍 자아분화검사 (DSI)</h1>
        <p className="text-center text-gray-400 text-sm mb-2">각 문항에 해당하는 번호를 선택하세요 (36문항)</p>
        <div className="bg-green-50 border border-green-200 rounded-lg p-3 mb-4 text-xs text-green-800">
          <div className="flex flex-wrap gap-3">
            {["1: 전혀 아니다", "2: 거의 아니다", "3: 어쩌다 그렇다", "4: 자주 그렇다", "5: 항상 그렇다"].map(t => <span key={t} className="font-semibold">{t}</span>)}
          </div>
        </div>
        {saveStatus && <div className="mb-4 p-3 bg-yellow-50 border border-yellow-300 rounded text-sm text-yellow-800 text-center">{saveStatus}</div>}
        <div className="space-y-3">
          {dsiQ.map(q => (
            <div key={q.num} className={`border-2 rounded-xl p-4 transition ${dsiResponses[q.num] ? "border-green-300 bg-green-50" : "border-gray-100"}`}>
              <div className="flex items-start gap-2 mb-3">
                <span className="text-xs bg-purple-100 text-purple-700 px-2 py-0.5 rounded shrink-0 mt-0.5">{q.area}</span>
                <p className="text-sm font-semibold text-gray-700">{q.num}. {q.content}</p>
              </div>
              <div className="flex gap-2">
                {[1, 2, 3, 4, 5].map(s => (
                  <button key={s} onClick={() => setDsiResponses(p => ({ ...p, [q.num]: s }))} className={`flex-1 py-2 rounded-lg font-bold text-sm border-2 transition ${dsiResponses[q.num] === s ? "bg-green-600 text-white border-green-600" : "bg-white border-gray-300 text-gray-500 hover:border-green-400"}`}>
                    {s}
                  </button>
                ))}
              </div>
            </div>
          ))}
        </div>
        <div className="mt-8 text-center">
          <button onClick={submitDsi} disabled={Object.keys(dsiResponses).length < 36} className="bg-green-600 text-white px-10 py-3 rounded-xl font-bold text-lg hover:bg-green-700 disabled:bg-gray-300 disabled:cursor-not-allowed transition">
            검사 제출 ({Object.keys(dsiResponses).length}/36)
          </button>
        </div>
      </div>
    </div>
  );

  // PHQ-9 검사 화면
  if (view === "phq9Test") return (
    <div className="min-h-screen bg-gray-50 p-4">
      <div className="max-w-3xl mx-auto bg-white rounded-xl shadow p-6">
        {pendingTests.length > 1 && (
          <div className="mb-4 bg-purple-50 border border-purple-200 rounded-xl p-3">
            <p className="text-xs font-bold text-purple-700 mb-2">📋 검사 진행 현황 ({currentTestIndex + 1}/{pendingTests.length})</p>
            <div className="flex gap-2 flex-wrap">
              {pendingTests.map((t, i) => (
                <span key={t} className={`px-3 py-1 rounded-full text-xs font-bold border ${i < currentTestIndex ? "bg-green-100 border-green-300 text-green-700" : i === currentTestIndex ? "bg-purple-600 text-white border-purple-600" : "bg-gray-100 border-gray-300 text-gray-400"}`}>
                  {i < currentTestIndex ? "✅ " : i === currentTestIndex ? "▶ " : ""}{t}
                </span>
              ))}
            </div>
            <div className="mt-2 bg-gray-200 rounded-full h-1.5">
              <div className="bg-purple-500 h-1.5 rounded-full transition-all" style={{width: `${((currentTestIndex) / pendingTests.length) * 100}%`}}></div>
            </div>
          </div>
        )}
        <h1 className="text-2xl font-bold text-center text-indigo-800 mb-1">😔 우울증 선별검사 (PHQ-9)</h1>
        <p className="text-center text-gray-400 text-sm mb-2">지난 2주간 얼마나 자주 다음의 문제들로 어려움을 겪었는지 표시해 주세요 (9문항)</p>
        <div className="bg-indigo-50 border border-indigo-200 rounded-lg p-3 mb-4 text-xs text-indigo-800">
          <div className="flex flex-wrap gap-3">
            {["0: 전혀 없음", "1: 여러 날 동안", "2: 7일 이상", "3: 거의 매일"].map(t => <span key={t} className="font-semibold">{t}</span>)}
          </div>
        </div>
        <div className="bg-indigo-50 border border-indigo-200 rounded-lg p-2 text-xs text-indigo-700 mb-6 text-center">
          진행: <strong>{Object.keys(phq9Responses).length}</strong> / 9 문항
        </div>
        {saveStatus && <div className="mb-4 p-3 bg-yellow-50 border border-yellow-300 rounded text-sm text-yellow-800 text-center">{saveStatus}</div>}
        <div className="space-y-3">
          {phq9Q.map(q => (
            <div key={q.num} className="border-b border-gray-100 pb-3">
              <label className="block mb-2 font-semibold text-gray-700 text-sm">{q.num}. {q.content}</label>
              <div className="flex gap-2">
                {[0, 1, 2, 3].map(v => (
                  <button key={v} onClick={() => setPhq9Responses(p => ({ ...p, [q.num]: v }))} className={`flex-1 py-2 rounded-lg text-sm font-semibold transition ${phq9Responses[q.num] === v ? "bg-indigo-600 text-white" : "bg-gray-100 text-gray-600 hover:bg-indigo-100"}`}>
                    {v}
                  </button>
                ))}
              </div>
            </div>
          ))}
        </div>
        <div className="mt-8 text-center">
          <button onClick={submitPhq9} className="bg-indigo-600 text-white px-10 py-3 rounded-xl font-bold text-lg hover:bg-indigo-700 transition">
            검사 제출 ({Object.keys(phq9Responses).length}/9)
          </button>
        </div>
      </div>
    </div>
  );

  // GAD-7 검사 화면
  if (view === "gad7Test") return (
    <div className="min-h-screen bg-gray-50 p-4">
      <div className="max-w-3xl mx-auto bg-white rounded-xl shadow p-6">
        {pendingTests.length > 1 && (
          <div className="mb-4 bg-purple-50 border border-purple-200 rounded-xl p-3">
            <p className="text-xs font-bold text-purple-700 mb-2">📋 검사 진행 현황 ({currentTestIndex + 1}/{pendingTests.length})</p>
            <div className="flex gap-2 flex-wrap">
              {pendingTests.map((t, i) => (
                <span key={t} className={`px-3 py-1 rounded-full text-xs font-bold border ${i < currentTestIndex ? "bg-green-100 border-green-300 text-green-700" : i === currentTestIndex ? "bg-purple-600 text-white border-purple-600" : "bg-gray-100 border-gray-300 text-gray-400"}`}>
                  {i < currentTestIndex ? "✅ " : i === currentTestIndex ? "▶ " : ""}{t}
                </span>
              ))}
            </div>
            <div className="mt-2 bg-gray-200 rounded-full h-1.5">
              <div className="bg-purple-500 h-1.5 rounded-full transition-all" style={{width: `${((currentTestIndex) / pendingTests.length) * 100}%`}}></div>
            </div>
          </div>
        )}
        <h1 className="text-2xl font-bold text-center text-orange-800 mb-1">😰 범불안장애 선별검사 (GAD-7)</h1>
        <p className="text-center text-gray-400 text-sm mb-2">지난 2주간 다음의 문제들로 얼마나 자주 시달렸는지 표시해 주세요 (7문항)</p>
        <div className="bg-orange-50 border border-orange-200 rounded-lg p-3 mb-4 text-xs text-orange-800">
          <div className="flex flex-wrap gap-3">
            {["0: 전혀 없음", "1: 여러 날 동안", "2: 7일 이상", "3: 거의 매일"].map(t => <span key={t} className="font-semibold">{t}</span>)}
          </div>
        </div>
        <div className="bg-orange-50 border border-orange-200 rounded-lg p-2 text-xs text-orange-700 mb-6 text-center">
          진행: <strong>{Object.keys(gad7Responses).length}</strong> / 7 문항
        </div>
        {saveStatus && <div className="mb-4 p-3 bg-yellow-50 border border-yellow-300 rounded text-sm text-yellow-800 text-center">{saveStatus}</div>}
        <div className="space-y-3">
          {gad7Q.map(q => (
            <div key={q.num} className="border-b border-gray-100 pb-3">
              <label className="block mb-2 font-semibold text-gray-700 text-sm">{q.num}. {q.content}</label>
              <div className="flex gap-2">
                {[0, 1, 2, 3].map(v => (
                  <button key={v} onClick={() => setGad7Responses(p => ({ ...p, [q.num]: v }))} className={`flex-1 py-2 rounded-lg text-sm font-semibold transition ${gad7Responses[q.num] === v ? "bg-orange-600 text-white" : "bg-gray-100 text-gray-600 hover:bg-orange-100"}`}>
                    {v}
                  </button>
                ))}
              </div>
            </div>
          ))}
        </div>
        <div className="mt-8 text-center">
          <button onClick={submitGad7} className="bg-orange-600 text-white px-10 py-3 rounded-xl font-bold text-lg hover:bg-orange-700 transition">
            검사 제출 ({Object.keys(gad7Responses).length}/7)
          </button>
        </div>
      </div>
    </div>
  );

  // DASS-21 검사 화면
  if (view === "dass21Test") return (
    <div className="min-h-screen bg-gray-50 p-4">
      <div className="max-w-3xl mx-auto bg-white rounded-xl shadow p-6">
        {pendingTests.length > 1 && (
          <div className="mb-4 bg-purple-50 border border-purple-200 rounded-xl p-3">
            <p className="text-xs font-bold text-purple-700 mb-2">📋 검사 진행 현황 ({currentTestIndex + 1}/{pendingTests.length})</p>
            <div className="flex gap-2 flex-wrap">
              {pendingTests.map((t, i) => (
                <span key={t} className={`px-3 py-1 rounded-full text-xs font-bold border ${i < currentTestIndex ? "bg-green-100 border-green-300 text-green-700" : i === currentTestIndex ? "bg-purple-600 text-white border-purple-600" : "bg-gray-100 border-gray-300 text-gray-400"}`}>
                  {i < currentTestIndex ? "✅ " : i === currentTestIndex ? "▶ " : ""}{t}
                </span>
              ))}
            </div>
            <div className="mt-2 bg-gray-200 rounded-full h-1.5">
              <div className="bg-purple-500 h-1.5 rounded-full transition-all" style={{width: `${((currentTestIndex) / pendingTests.length) * 100}%`}}></div>
            </div>
          </div>
        )}
        <h1 className="text-2xl font-bold text-center text-teal-800 mb-1">📊 우울/불안/스트레스 척도 (DASS-21)</h1>
        <p className="text-center text-gray-400 text-sm mb-2">지난 일주일 동안 자신에게 해당되는 정도를 표시해 주세요 (21문항)</p>
        <div className="bg-teal-50 border border-teal-200 rounded-lg p-3 mb-4 text-xs text-teal-800">
          <div className="flex flex-wrap gap-2">
            {["1: 전혀 아님", "2: 가끔", "3: 자주", "4: 대부분"].map(t => <span key={t} className="font-semibold">{t}</span>)}
          </div>
        </div>
        <div className="bg-teal-50 border border-teal-200 rounded-lg p-2 text-xs text-teal-700 mb-6 text-center">
          진행: <strong>{Object.keys(dass21Responses).length}</strong> / 21 문항
        </div>
        {saveStatus && <div className="mb-4 p-3 bg-yellow-50 border border-yellow-300 rounded text-sm text-yellow-800 text-center">{saveStatus}</div>}
        <div className="space-y-3">
          {dass21Q.map(q => (
            <div key={q.num} className="border-b border-gray-100 pb-3">
              <label className="block mb-2 font-semibold text-gray-700 text-sm">{q.num}. {q.content}</label>
              <div className="flex gap-2">
                {[1, 2, 3, 4].map(v => (
                  <button key={v} onClick={() => setDass21Responses(p => ({ ...p, [q.num]: v }))} className={`flex-1 py-2 rounded-lg text-sm font-semibold transition ${dass21Responses[q.num] === v ? "bg-teal-600 text-white" : "bg-gray-100 text-gray-600 hover:bg-teal-100"}`}>
                    {v}
                  </button>
                ))}
              </div>
            </div>
          ))}
        </div>
        <div className="mt-8 text-center">
          <button onClick={submitDass21} className="bg-teal-600 text-white px-10 py-3 rounded-xl font-bold text-lg hover:bg-teal-700 transition">
            검사 제출 ({Object.keys(dass21Responses).length}/21)
          </button>
        </div>
      </div>
    </div>
  );

  // Big5 검사 화면
  // 번아웃 검사 화면
  if (view === "burnoutTest") return (
    <div className="min-h-screen bg-gray-50 p-4">
      <div className="max-w-4xl mx-auto bg-white rounded-xl shadow-lg p-6">
        {pendingTests.length > 1 && (
          <div className="mb-4 bg-purple-50 border border-purple-200 rounded-xl p-3">
            <p className="text-xs font-bold text-purple-700 mb-2">📋 검사 진행 현황 ({currentTestIndex + 1}/{pendingTests.length})</p>
            <div className="flex gap-2 flex-wrap">
              {pendingTests.map((t, i) => (
                <span key={t} className={`px-3 py-1 rounded-full text-xs font-bold border ${i < currentTestIndex ? "bg-green-100 border-green-300 text-green-700" : i === currentTestIndex ? "bg-purple-600 text-white border-purple-600" : "bg-gray-100 border-gray-300 text-gray-400"}`}>
                  {i < currentTestIndex ? "✅ " : i === currentTestIndex ? "▶ " : ""}{t}
                </span>
              ))}
            </div>
            <div className="mt-2 bg-gray-200 rounded-full h-1.5">
              <div className="bg-purple-500 h-1.5 rounded-full transition-all" style={{width: `${((currentTestIndex) / pendingTests.length) * 100}%`}}></div>
            </div>
          </div>
        )}
        <h1 className="text-3xl font-bold text-center text-red-600 mb-2">🔥 번아웃 증후군 검사 (K-MBI+)</h1>
        <p className="text-center text-gray-500 text-sm mb-4">
          최근 한 달간 경험한 빈도를 선택해 주세요 (50문항)
        </p>
        
        {/* 응답 옵션 안내 */}
        <div className="bg-red-50 border border-red-200 rounded-lg p-3 mb-4">
          <div className="grid grid-cols-7 gap-1 text-xs text-center font-semibold text-red-800">
            <div>0: 전혀없음</div>
            <div>1: 1년에 몇번</div>
            <div>2: 한달에 한번</div>
            <div>3: 한달에 몇번</div>
            <div>4: 일주일에 한번</div>
            <div>5: 일주일에 몇번</div>
            <div>6: 매일</div>
          </div>
        </div>
        
        {/* 진행 상태 */}
        <div className="bg-red-50 border border-red-200 rounded-lg p-3 mb-6 text-center">
          <div className="text-sm text-red-700 mb-2">
            진행: <strong className="text-xl">{Object.keys(burnoutResponses).length}</strong> / 50 문항
          </div>
          <div className="w-full bg-gray-200 rounded-full h-3">
            <div 
              className="bg-red-600 h-3 rounded-full transition-all duration-300"
              style={{ width: `${(Object.keys(burnoutResponses).length / 50) * 100}%` }}
            ></div>
          </div>
        </div>
        
        {/* 문항 섹션별 렌더링 */}
        <div className="space-y-6">
          {getBurnoutDomains().map((domain, dIdx) => (
            <div key={dIdx} className="border-2 border-gray-200 rounded-lg p-4 bg-gray-50">
              <h2 className="text-lg font-bold text-gray-800 mb-3 flex items-center gap-2">
                <span className="text-red-600">{domain.icon}</span>
                {domain.name} ({domain.questions.length}문항)
              </h2>
              <div className="space-y-3">
                {domain.questions.map((q, qIdx) => (
                  <div key={q.num} className="bg-white border border-gray-200 rounded-lg p-3">
                    <label className="block mb-2 font-semibold text-gray-700 text-sm">
                      {q.num}. {q.content}
                    </label>
                    <div className="grid grid-cols-7 gap-1">
                      {[0, 1, 2, 3, 4, 5, 6].map(v => (
                        <button
                          key={v}
                          onClick={() => setBurnoutResponses(p => ({ ...p, [q.num]: v }))}
                          className={`py-2 px-1 rounded-lg text-xs font-bold transition ${
                            burnoutResponses[q.num] === v 
                              ? "bg-red-600 text-white shadow-lg scale-105" 
                              : "bg-gray-100 text-gray-600 hover:bg-red-100"
                          }`}
                        >
                          {v}
                        </button>
                      ))}
                    </div>
                  </div>
                ))}
              </div>
            </div>
          ))}
        </div>
        
        {/* 제출 버튼 */}
        <div className="mt-8 text-center">
          <button 
            onClick={submitBurnout} 
            className="bg-red-600 text-white px-12 py-4 rounded-xl font-bold text-lg hover:bg-red-700 transition shadow-lg transform hover:scale-105"
          >
            🔥 검사 제출 ({Object.keys(burnoutResponses).length}/50)
          </button>
        </div>
      </div>
    </div>
  );

  if (view === "big5Test") return (
    <div className="min-h-screen bg-gray-50 p-4">
      <div className="max-w-3xl mx-auto bg-white rounded-xl shadow p-6">
        {pendingTests.length > 1 && (
          <div className="mb-4 bg-purple-50 border border-purple-200 rounded-xl p-3">
            <p className="text-xs font-bold text-purple-700 mb-2">📋 검사 진행 현황 ({currentTestIndex + 1}/{pendingTests.length})</p>
            <div className="flex gap-2 flex-wrap">
              {pendingTests.map((t, i) => (
                <span key={t} className={`px-3 py-1 rounded-full text-xs font-bold border ${i < currentTestIndex ? "bg-green-100 border-green-300 text-green-700" : i === currentTestIndex ? "bg-purple-600 text-white border-purple-600" : "bg-gray-100 border-gray-300 text-gray-400"}`}>
                  {i < currentTestIndex ? "✅ " : i === currentTestIndex ? "▶ " : ""}{t}
                </span>
              ))}
            </div>
            <div className="mt-2 bg-gray-200 rounded-full h-1.5">
              <div className="bg-purple-500 h-1.5 rounded-full transition-all" style={{width: `${((currentTestIndex) / pendingTests.length) * 100}%`}}></div>
            </div>
          </div>
        )}
        {pendingTests.length > 1 && (
          <div className="mb-4 bg-purple-50 border border-purple-200 rounded-xl p-3">
            <p className="text-xs font-bold text-purple-700 mb-2">📋 검사 진행 현황 ({currentTestIndex + 1}/{pendingTests.length})</p>
            <div className="flex gap-2 flex-wrap">
              {pendingTests.map((t, i) => (
                <span key={t} className={`px-3 py-1 rounded-full text-xs font-bold border ${i < currentTestIndex ? "bg-green-100 border-green-300 text-green-700" : i === currentTestIndex ? "bg-purple-600 text-white border-purple-600" : "bg-gray-100 border-gray-300 text-gray-400"}`}>
                  {i < currentTestIndex ? "✅ " : i === currentTestIndex ? "▶ " : ""}{t}
                </span>
              ))}
            </div>
            <div className="mt-2 bg-gray-200 rounded-full h-1.5">
              <div className="bg-purple-500 h-1.5 rounded-full transition-all" style={{width: `${((currentTestIndex) / pendingTests.length) * 100}%`}}></div>
            </div>
          </div>
        )}
        <h1 className="text-2xl font-bold text-center text-purple-800 mb-1">🌟 Big5 성격검사</h1>
        <p className="text-center text-gray-400 text-sm mb-2">각 문장이 자신을 얼마나 잘 설명하는지 표시해 주세요 (50문항)</p>
        <div className="bg-purple-50 border border-purple-200 rounded-lg p-3 mb-4 text-xs text-purple-800">
          <div className="flex flex-wrap gap-2">
            {["1: 전혀 아님", "2: 아님", "3: 보통", "4: 그러함", "5: 매우 그러함"].map(t => <span key={t} className="font-semibold">{t}</span>)}
          </div>
        </div>
        <div className="bg-purple-50 border border-purple-200 rounded-lg p-2 text-xs text-purple-700 mb-6 text-center">
          진행: <strong>{Object.keys(big5Responses).length}</strong> / 50 문항
        </div>
        {saveStatus && <div className="mb-4 p-3 bg-yellow-50 border border-yellow-300 rounded text-sm text-yellow-800 text-center">{saveStatus}</div>}
        <div className="space-y-3">
          {big5Q.map(q => (
            <div key={q.num} className="border-b border-gray-100 pb-3">
              <label className="block mb-2 font-semibold text-gray-700 text-sm">{q.num}. {q.content}</label>
              <div className="flex gap-2">
                {[1, 2, 3, 4, 5].map(v => (
                  <button key={v} onClick={() => setBig5Responses(p => ({ ...p, [q.num]: v }))} className={`flex-1 py-2 rounded-lg text-sm font-semibold transition ${big5Responses[q.num] === v ? "bg-purple-600 text-white" : "bg-gray-100 text-gray-600 hover:bg-purple-100"}`}>
                    {v}
                  </button>
                ))}
              </div>
            </div>
          ))}
        </div>
        <div className="mt-8 text-center">
          <button onClick={submitBig5} className="bg-purple-600 text-white px-10 py-3 rounded-xl font-bold text-lg hover:bg-purple-700 transition">
            검사 제출 ({Object.keys(big5Responses).length}/50)
          </button>
        </div>
      </div>
    </div>
  );

  if (view === "lostTest") {
    const AXIS_INFO = [
      { axis:"E", label:"에너지 방향",   range:[1,10],  color:"teal",   desc:"외향(E) vs 내향(I)" },
      { axis:"D", label:"의사결정 방식", range:[11,20], color:"blue",   desc:"논리(T) vs 감정(F)" },
      { axis:"S", label:"행동 속도",     range:[21,30], color:"orange", desc:"빠름(P) vs 신중(J)" },
      { axis:"N", label:"안정성",        range:[31,40], color:"green",  desc:"변화(C) vs 안정(N)" },
      { axis:"R", label:"관계 민감도",   range:[41,50], color:"purple", desc:"관계중심(R) vs 독립(I)" },
      { axis:"T", label:"스트레스 반응", range:[51,60], color:"red",    desc:"직면(A) vs 회피(V)" },
    ];
    const btnActiveMap = {
      teal:"bg-teal-600 text-white", blue:"bg-blue-600 text-white",
      orange:"bg-orange-500 text-white", green:"bg-green-600 text-white",
      purple:"bg-purple-600 text-white", red:"bg-red-500 text-white",
    };
    const headerMap = {
      teal:"bg-teal-50 border-teal-200 text-teal-800",
      blue:"bg-blue-50 border-blue-200 text-blue-800",
      orange:"bg-orange-50 border-orange-200 text-orange-800",
      green:"bg-green-50 border-green-200 text-green-800",
      purple:"bg-purple-50 border-purple-200 text-purple-800",
      red:"bg-red-50 border-red-200 text-red-800",
    };
    const answered = Object.keys(lostResponses).length;
    return (
      <div className="min-h-screen bg-gray-50 p-4">
        <div className="max-w-3xl mx-auto bg-white rounded-xl shadow p-6">
          {pendingTests.length > 1 && (
            <div className="mb-4 bg-teal-50 border border-teal-200 rounded-xl p-3">
              <p className="text-xs font-bold text-teal-700 mb-2">📋 검사 진행 현황 ({currentTestIndex + 1}/{pendingTests.length})</p>
              <div className="flex gap-2 flex-wrap">
                {pendingTests.map((t, i) => (
                  <span key={t} className={`px-3 py-1 rounded-full text-xs font-bold border ${i < currentTestIndex ? "bg-green-100 border-green-300 text-green-700" : i === currentTestIndex ? "bg-teal-600 text-white border-teal-600" : "bg-gray-100 border-gray-300 text-gray-400"}`}>
                    {i < currentTestIndex ? "✅ " : i === currentTestIndex ? "▶ " : ""}{t}
                  </span>
                ))}
              </div>
              <div className="mt-2 bg-gray-200 rounded-full h-1.5">
                <div className="bg-teal-500 h-1.5 rounded-full transition-all" style={{width:`${(currentTestIndex/pendingTests.length)*100}%`}}></div>
              </div>
            </div>
          )}
          <h1 className="text-2xl font-bold text-center text-teal-800 mb-1">🧭 행동 운영체계 검사 (LOST)</h1>
          <p className="text-center text-gray-500 text-sm mb-1">나는 어떻게 행동하고 결정하는가 — 6개 축, 60문항</p>
          <p className="text-center text-gray-400 text-xs mb-4">Big Five · HEXACO · TCI 이론 기반 | 한국 문화 요소 반영</p>
          <div className="bg-teal-50 border border-teal-200 rounded-lg p-3 mb-3 text-xs text-teal-800 flex flex-wrap gap-3">
            {["1: 전혀 아님","2: 아님","3: 보통","4: 그러함","5: 매우 그러함"].map(t => <span key={t} className="font-semibold">{t}</span>)}
          </div>
          <div className="mb-5">
            <div className="flex justify-between text-xs text-gray-500 mb-1">
              <span>전체 진행률</span>
              <span className="font-bold text-teal-700">{answered} / 60 문항</span>
            </div>
            <div className="w-full bg-gray-200 rounded-full h-2">
              <div className="bg-teal-500 h-2 rounded-full transition-all" style={{width:`${(answered/60)*100}%`}}></div>
            </div>
          </div>
          {saveStatus && <div className="mb-4 p-3 bg-yellow-50 border border-yellow-300 rounded text-sm text-yellow-800 text-center">{saveStatus}</div>}
          <div className="space-y-6">
            {AXIS_INFO.map(({ axis, label, range, color, desc }) => {
              const axisQs = lostQ.filter(q => q.num >= range[0] && q.num <= range[1]);
              const axisAnswered = axisQs.filter(q => lostResponses[q.num] !== undefined).length;
              return (
                <div key={axis} className={`border-2 rounded-xl overflow-hidden ${axisAnswered === 10 ? "border-teal-300" : "border-gray-200"}`}>
                  <div className={`px-4 py-2 border-b flex justify-between items-center ${headerMap[color]}`}>
                    <div>
                      <span className="font-bold text-sm">{label}</span>
                      <span className="ml-2 text-xs opacity-75">({desc})</span>
                    </div>
                    <span className={`text-xs font-bold px-2 py-0.5 rounded-full ${axisAnswered === 10 ? "bg-teal-600 text-white" : "bg-white/60 text-gray-600"}`}>
                      {axisAnswered}/10
                    </span>
                  </div>
                  <div className="p-3 space-y-3">
                    {axisQs.map(q => (
                      <div key={q.num} className="border-b border-gray-100 pb-3 last:border-0 last:pb-0">
                        <label className="block mb-2 font-medium text-gray-700 text-sm">
                          <span className="text-gray-400 mr-1">{q.num}.</span>{q.content}
                        </label>
                        <div className="flex gap-1.5">
                          {[1,2,3,4,5].map(v => (
                            <button key={v}
                              onClick={() => setLostResponses(p => ({...p, [q.num]: v}))}
                              className={`flex-1 py-2 rounded-lg text-sm font-semibold transition ${lostResponses[q.num] === v ? btnActiveMap[color] : "bg-gray-100 text-gray-600 hover:bg-gray-200"}`}
                            >{v}</button>
                          ))}
                        </div>
                      </div>
                    ))}
                  </div>
                </div>
              );
            })}
          </div>
          <div className="mt-8 text-center">
            <button onClick={submitLost} className="bg-teal-600 text-white px-10 py-3 rounded-xl font-bold text-lg hover:bg-teal-700 transition">
              검사 제출 ({answered}/60)
            </button>
          </div>
        </div>
      </div>
    );
  }

  if (view === "complete") return (
      <div className="bg-white rounded-2xl shadow-2xl p-8 w-full max-w-md text-center">
        <div className="w-20 h-20 bg-green-500 rounded-full flex items-center justify-center mx-auto mb-4">
          <svg className="w-12 h-12 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
          </svg>
        </div>
        <h1 className="text-3xl font-bold text-gray-800 mb-2">모든 검사 완료!</h1>
        {multiSessionIds.length > 1 ? (
          <div className="mb-5">
            <p className="text-gray-500 mb-3">총 <strong className="text-green-700">{multiSessionIds.length}개</strong>의 검사가 성공적으로 제출되었습니다.</p>
            <div className="flex flex-wrap justify-center gap-2 mb-3">
              {pendingTests.map((t, i) => (
                <span key={t} className="px-3 py-1 bg-green-100 text-green-800 rounded-full text-sm font-bold border border-green-300">
                  ✅ {t}
                </span>
              ))}
            </div>
            <p className="text-gray-400 text-sm">상담사가 결과를 확인할 예정입니다.</p>
          </div>
        ) : (
          <p className="text-gray-500 mb-6">
            검사가 성공적으로 제출되었습니다.
            <br />
            상담사가 결과를 확인할 예정입니다.
          </p>
        )}
        <button onClick={logout} className="w-full bg-green-600 text-white py-3 rounded-xl font-bold hover:bg-green-700 transition">
          처음으로 돌아가기
        </button>
      </div>
  );

  if (view === "sctResult") {
    const counselingType = activeLinkData?.counselingType || "psychological";
    const counselingTypeLabel = counselingType === "biblical" ? "🕊️ 성경적 상담" : "🧠 심리상담";
    const counselingTypeColor = counselingType === "biblical" ? "bg-purple-50 border-purple-200 text-purple-700" : "bg-blue-50 border-blue-200 text-blue-700";
    
    return (
    <div className="min-h-screen bg-gray-50 p-4">
      <div className="max-w-4xl mx-auto bg-white rounded-xl shadow p-6">
        <div className="flex justify-between items-center mb-6">
          <h1 className="text-2xl font-bold text-blue-800">📝 SCT 검사 결과</h1>
          <div className="flex gap-2">
            <button onClick={() => { setView(isCounselor ? "counselorResults" : isAdmin ? "admin" : "login"); }} className="bg-gray-400 text-white px-4 py-2 rounded-lg text-sm hover:bg-gray-500">
              ← 목록
            </button>
          </div>
        </div>
        <div className={`border rounded-lg p-4 mb-6 ${counselingTypeColor}`}>
          <p className="text-sm"><strong>상담 유형:</strong> {counselingTypeLabel}</p>
          <p className="text-sm"><strong>세션 ID:</strong> {sessionId}</p>
          <p className="text-sm"><strong>전화번호:</strong> {userInfo.phone || "N/A"}</p>
        </div>
        <div className="space-y-6">
          {Object.entries(sctCategories).map(([cat, nums]) => (
            <div key={cat} className="border border-gray-200 rounded-xl p-5">
              <div className="flex justify-between items-center mb-3">
                <h3 className="font-bold text-lg text-gray-800">{cat}</h3>
                {!sctSummaries[cat] && !loadingSummary[cat] && (
                  <button 
                    onClick={() => generateSctRecommendation(cat, nums)}
                    className="bg-indigo-600 text-white px-3 py-1.5 rounded-lg text-xs font-bold hover:bg-indigo-700 transition"
                  >
                    🤖 AI 분석 생성
                  </button>
                )}
              </div>
              <div className="space-y-2 mb-4">
                {nums.map(n => (
                  <div key={n} className="bg-gray-50 rounded p-3">
                    <p className="text-xs text-gray-500 mb-1">{n}. {sctQ[n]}</p>
                    <p className="text-sm font-semibold text-gray-800">{sctResponses[n] || "(미응답)"}</p>
                  </div>
                ))}
              </div>
              {loadingSummary[cat] && (
                <div className="bg-indigo-50 border border-indigo-200 rounded p-3 text-center">
                  <p className="text-sm text-indigo-600">🔄 AI 분석 중...</p>
                </div>
              )}
              {sctSummaries[cat] && (
                <div className="bg-indigo-50 border border-indigo-200 rounded p-3">
                  <p className="text-xs text-indigo-600 font-bold mb-1">💡 룰 기반 AI 분석</p>
                  <p className="text-sm text-indigo-800 whitespace-pre-wrap">{sctSummaries[cat]}</p>
                </div>
              )}
              <AiAnalysisBox
                aiKey={`SCT_${cat}`}
                onRun={() => runAiAnalysis(
                  `SCT_${cat}`,
                  "SCT",
                  { items: nums.map(n => ({ question: sctQ[n], answer: sctResponses[n] || "(미응답)" })) },
                  cat
                )}
              />
            </div>
          ))}
        </div>
        <div className="mt-6 bg-green-50 border border-green-200 rounded-lg p-4 text-center">
          <p className="text-sm text-green-700 font-semibold">✅ 룰 기반 분석 + AI 실시간 분석 모두 사용 가능합니다!</p>
          <p className="text-xs text-green-600 mt-1">각 카테고리에서 기존 룰 기반 분석 또는 ✨ AI 실시간 분석 버튼을 클릭하세요.</p>
        </div>
        <ChatBox testType="SCT" initialPrompts={[
          "이 SCT 결과에서 가장 주의해야 할 점은 무엇인가요?",
          "첫 상담 세션에서 어떤 주제부터 다루면 좋을까요?",
          "어머니 관계 패턴이 현재 대인관계에 미치는 영향은?",
          "이 내담자에게 적합한 상담 기법을 추천해주세요",
        ]} />
      </div>
    </div>
    );
  }

  if (view === "dsiResult") {
    const { total, areas } = calcDsi();
    const level = total >= 120 ? "높음(양호)" : total >= 80 ? "중간(보통)" : "낮음(취약)";
    
    const counselingType = activeLinkData?.counselingType || "psychological";
    const counselingTypeLabel = counselingType === "biblical" ? "🕊️ 성경적 상담" : "🧠 심리상담";
    const counselingTypeColor = counselingType === "biblical" ? "bg-purple-50 border-purple-200 text-purple-700" : "bg-green-50 border-green-200 text-green-700";
    
    return (
      <div className="min-h-screen bg-gray-50 p-4">
        <div className="max-w-4xl mx-auto bg-white rounded-xl shadow p-6">
          <div className="flex justify-between items-center mb-6">
            <h1 className="text-2xl font-bold text-green-800">🔍 DSI 검사 결과</h1>
            <div className="flex gap-2">
              <button onClick={() => { setView(isCounselor ? "counselorResults" : isAdmin ? "admin" : "login"); }} className="bg-gray-400 text-white px-4 py-2 rounded-lg text-sm hover:bg-gray-500">
                ← 목록
              </button>
            </div>
          </div>
          <div className={`border rounded-lg p-4 mb-6 ${counselingTypeColor}`}>
            <p className="text-sm"><strong>상담 유형:</strong> {counselingTypeLabel}</p>
            <p className="text-sm"><strong>세션 ID:</strong> {sessionId}</p>
            <p className="text-sm"><strong>전화번호:</strong> {userInfo.phone || "N/A"}</p>
            <p className="text-lg font-bold mt-2">총점: {total}/180 ({level})</p>
          </div>
          <div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
            {Object.entries(areas).map(([area, score]) => (
              <div key={area} className="bg-gray-50 rounded-lg p-4 border border-gray-200">
                <h3 className="font-bold text-gray-800 mb-2">{area}</h3>
                <div className="flex items-center gap-3">
                  <div className="flex-1 bg-gray-200 rounded-full h-3">
                    <div className="bg-green-600 h-3 rounded-full" style={{ width: `${(score / 36) * 100}%` }} />
                  </div>
                  <span className="text-sm font-bold text-gray-700">{score}/36</span>
                </div>
              </div>
            ))}
          </div>
          
          {/* ✅ 룰 기반 AI 권장사항 생성 버튼 */}
          {!dsiRec && !loadingRec && (
            <div className="mb-4 text-center">
              <button 
                onClick={generateDsiRecommendation}
                className="bg-indigo-600 text-white px-6 py-3 rounded-xl font-bold text-base hover:bg-indigo-700 transition shadow-lg"
              >
                🤖 룰 기반 AI 분석 생성
              </button>
              <p className="text-xs text-gray-500 mt-2">심리학 이론 기반 규칙으로 즉시 분석합니다</p>
            </div>
          )}
          
          {loadingRec && (
            <div className="mb-6 bg-indigo-50 border border-indigo-200 rounded-lg p-6 text-center">
              <div className="inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-indigo-600 mb-2"></div>
              <p className="text-sm text-indigo-600 font-semibold">🔄 AI가 검사 결과를 분석 중입니다...</p>
              <p className="text-xs text-indigo-500 mt-1">잠시만 기다려주세요</p>
            </div>
          )}
          
          {dsiRec && (
            <div className="mb-4 bg-indigo-50 border-2 border-indigo-300 rounded-xl p-5 shadow-md">
              <div className="flex items-center gap-2 mb-3">
                <span className="text-2xl">💡</span>
                <p className="font-bold text-indigo-900 text-lg">룰 기반 AI 분석 결과</p>
              </div>
              <div className="bg-white rounded-lg p-4 border border-indigo-200">
                <p className="text-sm text-gray-700 whitespace-pre-wrap leading-relaxed">{dsiRec}</p>
              </div>
            </div>
          )}

          {/* ✨ AI 실시간 분석 */}
          <div className="mb-6">
            <AiAnalysisBox
              aiKey="DSI"
              onRun={() => {
                const { total, areas } = calcDsi();
                runAiAnalysis("DSI", "DSI", { total, areas });
              }}
            />
          </div>
          
          <div className="space-y-3">
            {dsiQ.map(q => (
              <div key={q.num} className="bg-gray-50 rounded-lg p-3 border border-gray-200">
                <div className="flex items-start justify-between gap-2">
                  <p className="text-sm text-gray-700 flex-1">{q.num}. {q.content}</p>
                  <span className={`px-3 py-1 rounded font-bold text-sm ${dsiResponses[q.num] ? "bg-green-600 text-white" : "bg-gray-300 text-gray-600"}`}>
                    {dsiResponses[q.num] || "-"}
                  </span>
                </div>
              </div>
            ))}
          </div>
          
          <div className="mt-6 bg-green-50 border border-green-200 rounded-lg p-4 text-center">
            <p className="text-sm text-green-700 font-semibold">✅ 룰 기반 분석 + AI 실시간 분석 모두 사용 가능합니다!</p>
            <p className="text-xs text-green-600 mt-1">두 가지 분석을 비교하여 더욱 깊이 있는 상담을 진행하세요.</p>
          </div>

          {/* 💬 AI 상담 채팅 */}
          <ChatBox testType="DSI" initialPrompts={[
            "자아분화 수준이 낮은 내담자를 어떻게 상담해야 하나요?",
            "Bowen의 가족치료 이론을 실제 상담에 어떻게 적용하나요?",
            "취약한 영역에 집중하는 방법을 알려주세요",
            "가족관계 개선을 위한 구체적인 과제를 제시해주세요"
          ]} />
        </div>
      </div>
    );
  }

  if (view === "admin") return (
    <div className="min-h-screen bg-gray-50 p-4">
      <div className="max-w-6xl mx-auto space-y-4">
        <div className="bg-white rounded-xl shadow p-4 flex justify-between items-center">
          <div>
            <h1 className="text-xl font-bold">🔐 관리자 대시보드</h1>
            <p className="text-xs text-gray-400 mt-1">LocalStorage 영구 저장 활성화</p>
          </div>
          <div className="flex gap-2">
            <label className="bg-green-600 text-white px-4 py-2 rounded-lg text-sm hover:bg-green-700 cursor-pointer flex items-center gap-2">
              📂 불러오기
              <input 
                type="file" 
                accept=".json" 
                onChange={handleFileUpload} 
                className="hidden"
              />
            </label>
            <button 
              onClick={() => {
                alert(`✅ 데이터 확인\n\n승인된 상담사: ${approvedCounselors.length}명\n대기 중인 상담사: ${pendingCounselors.length}명\n제출된 검사: ${submitted.length}건\n\n콘솔(F12)에서 상세 정보 확인 가능`);
              }}
              className="bg-blue-500 text-white px-4 py-2 rounded-lg text-sm hover:bg-blue-600"
            >
              🔍 데이터 확인
            </button>
            <button onClick={logout} className="bg-gray-400 text-white px-4 py-2 rounded-lg text-sm hover:bg-gray-500">
              로그아웃
            </button>
          </div>
        </div>

        <div className="bg-white rounded-xl shadow p-6">
          <h2 className="text-lg font-bold text-gray-800 mb-4">👨‍⚕️ 상담사 승인 대기 ({pendingCounselors.length}건)</h2>
          {pendingCounselors.length === 0 ? (
            <div className="text-center py-10 text-gray-400">
              <p>대기 중인 신청이 없습니다</p>
            </div>
          ) : (
            <div className="space-y-3">
              {pendingCounselors.map((c, i) => (
                <div key={i} className="border border-gray-200 rounded-lg p-4">
                  <div className="flex justify-between items-start">
                    <div className="flex-1">
                      <p className="font-bold text-gray-800">{c.name || "이름 미입력"} ({c.phone})</p>
                      <p className="text-sm text-gray-600">자격증: {c.certification || "없음"}</p>
                      <p className="text-sm text-gray-600">학력: {c.education}</p>
                      <p className="text-sm text-gray-600">경력: {c.experience || "없음"}</p>
                      <div className={`mt-2 inline-block px-2 py-1 rounded text-xs font-bold ${c.eduOk ? "bg-green-100 text-green-800" : "bg-yellow-100 text-yellow-800"}`}>
                        {c.eduOk ? `✅ 관련 학과: ${c.eduKws.join(", ")}` : "⚠️ 상담 관련 학과 미확인"}
                      </div>
                      <p className="text-xs text-gray-400 mt-1">신청일: {new Date(c.requestDate).toLocaleString("ko-KR")}</p>
                    </div>
                    <div className="flex gap-2 ml-4">
                      <button onClick={() => approveCounselor(c.phone)} className="bg-green-600 text-white px-4 py-2 rounded-lg text-sm font-bold hover:bg-green-700">
                        ✓ 승인
                      </button>
                      <button onClick={() => rejectCounselor(c.phone)} className="bg-red-500 text-white px-4 py-2 rounded-lg text-sm font-bold hover:bg-red-600">
                        ✗ 거부
                      </button>
                    </div>
                  </div>
                </div>
              ))}
            </div>
          )}
        </div>

        <div className="bg-white rounded-xl shadow p-6">
          <h2 className="text-lg font-bold text-gray-800 mb-4">✅ 승인된 상담사 ({approvedCounselors.length}명)</h2>
          {approvedCounselors.length === 0 ? (
            <div className="text-center py-10 text-gray-400">
              <p>승인된 상담사가 없습니다</p>
            </div>
          ) : (
            <div className="space-y-2">
              {approvedCounselors.map((c, i) => (
                <div key={i} className="border border-gray-200 rounded-lg p-4">
                  <div className="flex justify-between items-start mb-2">
                    <div className="flex-1">
                      <p className="font-bold text-gray-800">{c.name || "이름 미입력"} ({c.phone})</p>
                      <p className="text-xs text-gray-500 mt-1">
                        상담 유형: {c.counselor_type === 'biblical' ? '🕊️ 성경적' : '🧠 심리'} | 
                        구독: {c.subscription_type === 'free' ? '무료' : c.subscription_type === 'professional' ? '프로페셔널' : c.subscription_type}
                      </p>
                    </div>
                    <span className="bg-green-100 text-green-800 px-3 py-1 rounded-full text-xs font-bold whitespace-nowrap">활성</span>
                  </div>
                  
                  {/* 쿼터 정보 및 수정 */}
                  <div className="flex items-center gap-3 mt-3 pt-3 border-t border-gray-100">
                    <div className="flex items-center gap-2">
                      <span className="text-sm text-gray-600">쿼터:</span>
                      {quotaEditingPhone === c.phone ? (
                        // 편집 모드
                        <div className="flex items-center gap-2">
                          <input
                            type="number"
                            min="0"
                            value={quotaEditingValue}
                            onChange={(e) => setQuotaEditingValue(e.target.value)}
                            className="w-20 px-2 py-1 border border-indigo-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500"
                            autoFocus
                          />
                          <span className="text-sm text-gray-500">/ {c.quota_total}</span>
                          <button
                            onClick={() => saveQuotaEdit(c.phone, c.name)}
                            className="bg-indigo-600 text-white px-3 py-1 rounded text-xs hover:bg-indigo-700 transition-colors"
                          >
                            저장
                          </button>
                          <button
                            onClick={cancelEditQuota}
                            className="bg-gray-400 text-white px-3 py-1 rounded text-xs hover:bg-gray-500 transition-colors"
                          >
                            취소
                          </button>
                        </div>
                      ) : (
                        // 보기 모드
                        <div className="flex items-center gap-2">
                          <span className="text-sm font-bold text-indigo-600">{c.quota_used || 0}</span>
                          <span className="text-sm text-gray-400">/</span>
                          <span className="text-sm font-bold text-gray-800">{c.quota_total || 0}</span>
                          <span className="text-xs text-gray-500">회 사용</span>
                          <button
                            onClick={() => startEditQuota(c.phone, c.quota_total)}
                            className="ml-2 bg-gray-100 text-gray-700 px-2 py-1 rounded text-xs hover:bg-gray-200 transition-colors"
                            title="쿼터 조정"
                          >
                            🔢 수정
                          </button>
                        </div>
                      )}
                    </div>
                    
                    {/* 남은 쿼터 표시 */}
                    {quotaEditingPhone !== c.phone && (
                      <div className="ml-auto">
                        <span className={`text-xs px-2 py-1 rounded ${
                          (c.quota_total - c.quota_used) > 10 
                            ? 'bg-green-100 text-green-700' 
                            : (c.quota_total - c.quota_used) > 3 
                            ? 'bg-yellow-100 text-yellow-700' 
                            : 'bg-red-100 text-red-700'
                        }`}>
                          남은 쿼터: {(c.quota_total || 0) - (c.quota_used || 0)}회
                        </span>
                      </div>
                    )}
                  </div>
                  
                  <p className="text-xs text-gray-400 mt-2">승인일: {new Date(c.created_at).toLocaleString("ko-KR")}</p>
                </div>
              ))}
            </div>
          )}
        </div>

        <div className="bg-white rounded-xl shadow p-6">
          <h2 className="text-lg font-bold text-gray-800 mb-4">📊 전체 제출된 검사 ({submitted.length}건)</h2>
          <SessionList sessions={submitted} onView={viewSession} />
        </div>

        {/* ── AI API 키 관리 섹션 ────────────────────────── */}
        <div className="bg-white rounded-xl shadow p-6">
          <div className="flex items-center justify-between mb-5">
            <div>
              <h2 className="text-lg font-bold text-gray-800 flex items-center gap-2">
                🔑 AI API 키 관리
              </h2>
              <p className="text-xs text-gray-500 mt-1">Claude AI 심리분석에 사용되는 API 키를 관리합니다</p>
            </div>
            <button
              onClick={() => { setShowApiKeyInput(v => !v); setApiSettingMsg({ type: '', text: '' }); setApiTestResult({ type: '', text: '' }); }}
              className="bg-indigo-600 text-white px-4 py-2 rounded-lg text-sm font-bold hover:bg-indigo-700 transition"
            >
              {showApiKeyInput ? '✕ 닫기' : '+ 키 등록/변경'}
            </button>
          </div>

          {/* 등록된 API 키 목록 */}
          <div className="mb-5">
            {apiSettings.length === 0 ? (
              <div className="border-2 border-dashed border-red-200 rounded-xl p-6 text-center bg-red-50">
                <p className="text-3xl mb-2">⚠️</p>
                <p className="font-bold text-red-700 mb-1">등록된 API 키가 없습니다</p>
                <p className="text-xs text-red-600">AI 실시간 분석 기능을 사용하려면 Anthropic API 키를 등록해주세요.</p>
              </div>
            ) : (
              <div className="space-y-3">
                {apiSettings.map(setting => (
                  <div key={setting.id} className={`border rounded-xl p-4 ${setting.is_active ? 'border-green-200 bg-green-50' : 'border-gray-200 bg-gray-50 opacity-60'}`}>
                    <div className="flex items-start justify-between gap-3">
                      <div className="flex-1">
                        <div className="flex items-center gap-2 mb-1">
                          <span className={`text-xs px-2 py-0.5 rounded-full font-bold ${setting.is_active ? 'bg-green-200 text-green-800' : 'bg-gray-200 text-gray-600'}`}>
                            {setting.is_active ? '● 활성' : '○ 비활성'}
                          </span>
                          <span className="font-bold text-gray-800 text-sm">{setting.key_name}</span>
                        </div>
                        <p className="text-xs text-gray-500 font-mono bg-white border border-gray-200 rounded px-2 py-1 inline-block">
                          {setting.masked_value}
                        </p>
                        {setting.description && (
                          <p className="text-xs text-gray-500 mt-1">{setting.description}</p>
                        )}
                        <p className="text-xs text-gray-400 mt-1">
                          등록일: {new Date(setting.created_at).toLocaleString('ko-KR')}
                          {setting.updated_at !== setting.created_at && ` · 수정: ${new Date(setting.updated_at).toLocaleString('ko-KR')}`}
                        </p>
                      </div>
                      <div className="flex gap-2 shrink-0">
                        <button
                          onClick={() => { setApiSettingForm(f => ({ ...f, key_name: setting.key_name, key_value: '', description: setting.description || '' })); setShowApiKeyInput(true); setApiTestResult({ type: '', text: '' }); }}
                          className="text-xs bg-indigo-100 text-indigo-700 px-3 py-1.5 rounded-lg hover:bg-indigo-200 font-semibold"
                        >✏️ 수정</button>
                        {setting.is_active && (
                          <button
                            onClick={() => deactivateApiKey(setting.key_name)}
                            className="text-xs bg-red-100 text-red-700 px-3 py-1.5 rounded-lg hover:bg-red-200 font-semibold"
                          >🔒 비활성화</button>
                        )}
                      </div>
                    </div>
                  </div>
                ))}
              </div>
            )}
          </div>

          {/* API 키 등록/수정 폼 */}
          {showApiKeyInput && (
            <div className="border-2 border-indigo-200 rounded-xl p-5 bg-indigo-50">
              <h3 className="font-bold text-indigo-800 mb-4 flex items-center gap-2">
                🔐 API 키 등록 / 변경
              </h3>
              <div className="space-y-3">
                {/* 키 이름 선택 */}
                <div>
                  <label className="block text-sm font-semibold text-gray-700 mb-1">API 키 종류</label>
                  <select
                    value={apiSettingForm.key_name}
                    onChange={e => setApiSettingForm(f => ({ ...f, key_name: e.target.value }))}
                    className="w-full px-3 py-2 border-2 border-indigo-200 rounded-lg text-sm focus:border-indigo-400 outline-none bg-white"
                  >
                    <option value="ANTHROPIC_API_KEY">ANTHROPIC_API_KEY (Claude AI 분석)</option>
                  </select>
                </div>

                {/* API 키 입력 */}
                <div>
                  <label className="block text-sm font-semibold text-gray-700 mb-1">
                    API 키 값 <span className="text-red-500">*</span>
                  </label>
                  <input
                    type="password"
                    value={apiSettingForm.key_value}
                    onChange={e => setApiSettingForm(f => ({ ...f, key_value: e.target.value }))}
                    placeholder="sk-ant-api03-..."
                    className="w-full px-3 py-2 border-2 border-indigo-200 rounded-lg text-sm focus:border-indigo-400 outline-none font-mono bg-white"
                  />
                  <p className="text-xs text-gray-500 mt-1">Anthropic API 키는 <span className="font-mono font-bold">sk-ant-</span> 로 시작합니다</p>
                </div>

                {/* 설명 */}
                <div>
                  <label className="block text-sm font-semibold text-gray-700 mb-1">메모 (선택)</label>
                  <input
                    type="text"
                    value={apiSettingForm.description}
                    onChange={e => setApiSettingForm(f => ({ ...f, description: e.target.value }))}
                    placeholder="예: 2026년 3월 발급"
                    className="w-full px-3 py-2 border-2 border-indigo-200 rounded-lg text-sm focus:border-indigo-400 outline-none bg-white"
                  />
                </div>

                {/* 연결 테스트 결과 */}
                {apiTestResult.text && (
                  <div className={`rounded-lg p-3 text-sm font-semibold ${apiTestResult.type === 'success' ? 'bg-green-100 text-green-800 border border-green-300' : 'bg-red-100 text-red-800 border border-red-300'}`}>
                    {apiTestResult.text}
                  </div>
                )}

                {/* 저장 메시지 */}
                {apiSettingMsg.text && (
                  <div className={`rounded-lg p-3 text-sm font-semibold ${apiSettingMsg.type === 'success' ? 'bg-green-100 text-green-800 border border-green-300' : 'bg-red-100 text-red-800 border border-red-300'}`}>
                    {apiSettingMsg.text}
                  </div>
                )}

                {/* 버튼 영역 */}
                <div className="flex gap-2 pt-1">
                  <button
                    onClick={testApiConnection}
                    disabled={apiTestLoading || !apiSettingForm.key_value}
                    className="flex items-center gap-1.5 bg-blue-600 text-white px-4 py-2 rounded-lg text-sm font-bold hover:bg-blue-700 transition disabled:opacity-50 disabled:cursor-not-allowed"
                  >
                    {apiTestLoading ? (
                      <><span className="inline-block w-3 h-3 border-2 border-white border-t-transparent rounded-full animate-spin"></span> 테스트 중...</>
                    ) : '🔌 연결 테스트'}
                  </button>
                  <button
                    onClick={saveApiSetting}
                    disabled={apiSettingLoading || !apiSettingForm.key_value}
                    className="flex items-center gap-1.5 bg-green-600 text-white px-4 py-2 rounded-lg text-sm font-bold hover:bg-green-700 transition disabled:opacity-50 disabled:cursor-not-allowed"
                  >
                    {apiSettingLoading ? (
                      <><span className="inline-block w-3 h-3 border-2 border-white border-t-transparent rounded-full animate-spin"></span> 저장 중...</>
                    ) : '💾 저장'}
                  </button>
                  <button
                    onClick={() => { setShowApiKeyInput(false); setApiSettingMsg({ type: '', text: '' }); setApiTestResult({ type: '', text: '' }); }}
                    className="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg text-sm font-bold hover:bg-gray-400 transition"
                  >취소</button>
                </div>
              </div>
            </div>
          )}

          {/* 안내 박스 */}
          <div className="mt-5 bg-amber-50 border border-amber-200 rounded-xl p-4">
            <p className="text-xs font-bold text-amber-800 mb-2">📌 API 키 관리 안내</p>
            <ul className="text-xs text-amber-700 space-y-1">
              <li>• API 키는 DB에 암호화되어 저장됩니다</li>
              <li>• 키 변경 즉시 모든 AI 분석에 반영됩니다 (재배포 불필요)</li>
              <li>• Anthropic API 키 발급: <span className="font-mono font-bold">console.anthropic.com</span></li>
              <li>• 저장 전 반드시 <strong>연결 테스트</strong>로 유효성을 확인하세요</li>
            </ul>
          </div>
        </div>
        {/* ── API 키 관리 섹션 끝 ──────────────────────────── */}

        {/* ── 성경적 상담 참고자료 관리 섹션 ────────────────── */}
        <div className="bg-white rounded-xl shadow p-6">
          <div className="flex items-center justify-between mb-5">
            <div>
              <h2 className="text-lg font-bold text-gray-800">📖 성경적 상담 참고자료 관리</h2>
              <p className="text-xs text-gray-500 mt-1">
                등록된 자료는 🕊️ 성경적 상담 선택 시 AI 분석에 <strong>우선 반영</strong>됩니다
              </p>
            </div>
            <button
              onClick={() => {
                setBiblicalForm({ id: null, title: '', category: 'general', content: '', sort_order: 0 });
                setShowBiblicalForm(v => !v);
                setBiblicalMsg({ type: '', text: '' });
              }}
              className="bg-purple-600 text-white px-4 py-2 rounded-lg text-sm font-bold hover:bg-purple-700 transition"
            >
              {showBiblicalForm ? '✕ 닫기' : '+ 자료 등록'}
            </button>
          </div>

          {/* 메시지 */}
          {biblicalMsg.text && (
            <div className={`mb-4 rounded-lg p-3 text-sm font-semibold ${biblicalMsg.type === 'success' ? 'bg-green-100 text-green-800 border border-green-300' : 'bg-red-100 text-red-800 border border-red-300'}`}>
              {biblicalMsg.text}
            </div>
          )}

          {/* 등록/수정 폼 */}
          {showBiblicalForm && (
            <div className="border-2 border-purple-200 rounded-xl p-5 bg-purple-50 mb-5">
              <h3 className="font-bold text-purple-800 mb-4 text-sm">
                {biblicalForm.id ? '✏️ 참고자료 수정' : '📝 새 참고자료 등록'}
              </h3>
              <div className="space-y-3">
                <div>
                  <label className="block text-sm font-semibold text-gray-700 mb-1">
                    자료 제목 <span className="text-red-500">*</span>
                  </label>
                  <input
                    type="text"
                    value={biblicalForm.title}
                    onChange={e => setBiblicalForm(f => ({ ...f, title: e.target.value }))}
                    placeholder="예: 어머니 관계 치유를 위한 성경구절"
                    className="w-full px-3 py-2 border-2 border-purple-200 rounded-lg text-sm focus:border-purple-400 outline-none bg-white"
                  />
                </div>

                <div>
                  <label className="block text-sm font-semibold text-gray-700 mb-1">
                    적용 카테고리 <span className="text-red-500">*</span>
                  </label>
                  <select
                    value={biblicalForm.category}
                    onChange={e => setBiblicalForm(f => ({ ...f, category: e.target.value }))}
                    className="w-full px-3 py-2 border-2 border-purple-200 rounded-lg text-sm focus:border-purple-400 outline-none bg-white"
                  >
                    {BIBLICAL_CATEGORIES.map(cat => (
                      <option key={cat.value} value={cat.value}>{cat.label}</option>
                    ))}
                  </select>
                </div>

                <div>
                  <label className="block text-sm font-semibold text-gray-700 mb-1">
                    참고자료 내용 <span className="text-red-500">*</span>
                  </label>
                  <textarea
                    value={biblicalForm.content}
                    onChange={e => setBiblicalForm(f => ({ ...f, content: e.target.value }))}
                    placeholder="성경구절, 해석, 상담원칙 등을 입력하세요"
                    rows="8"
                    className="w-full px-3 py-2 border-2 border-purple-200 rounded-lg text-sm focus:border-purple-400 outline-none bg-white resize-y"
                  />
                  <p className="text-xs text-gray-500 mt-1">
                    {biblicalForm.content.length} / 50,000자
                  </p>
                </div>

                <div>
                  <label className="block text-sm font-semibold text-gray-700 mb-1">
                    파일 업로드 (.txt, .md)
                  </label>
                  <input
                    type="file"
                    accept=".txt,.md"
                    onChange={handleBiblicalFileUpload}
                    className="w-full text-sm"
                  />
                  <p className="text-xs text-gray-500 mt-1">
                    최대 500KB, 파일 내용이 자동으로 본문에 입력됩니다
                  </p>
                </div>

                <div>
                  <label className="block text-sm font-semibold text-gray-700 mb-1">
                    정렬 순서
                  </label>
                  <input
                    type="number"
                    value={biblicalForm.sort_order}
                    onChange={e => setBiblicalForm(f => ({ ...f, sort_order: parseInt(e.target.value) || 0 }))}
                    className="w-full px-3 py-2 border-2 border-purple-200 rounded-lg text-sm focus:border-purple-400 outline-none bg-white"
                  />
                  <p className="text-xs text-gray-500 mt-1">
                    숫자가 작을수록 먼저 적용됩니다
                  </p>
                </div>

                <div className="flex gap-2 pt-2">
                  <button
                    onClick={saveBiblicalRef}
                    disabled={biblicalLoading}
                    className="flex-1 bg-purple-600 text-white px-4 py-2.5 rounded-lg text-sm font-bold hover:bg-purple-700 transition disabled:opacity-50"
                  >
                    {biblicalLoading ? '저장 중...' : '💾 저장'}
                  </button>
                  <button
                    onClick={() => { setShowBiblicalForm(false); setBiblicalMsg({ type: '', text: '' }); }}
                    className="bg-gray-300 text-gray-700 px-4 py-2 rounded-lg text-sm font-bold hover:bg-gray-400 transition"
                  >취소</button>
                </div>
              </div>
            </div>
          )}

          {/* 필터 탭 */}
          <div className="flex gap-2 mb-4 flex-wrap">
            {[
              { key: 'all',      label: `전체 (${biblicalRefs.length})`,                              active: 'bg-purple-600 text-white border-purple-600' },
              { key: 'active',   label: `활성 (${biblicalRefs.filter(r => r.is_active).length})`,     active: 'bg-green-600 text-white border-green-600' },
              { key: 'inactive', label: `비활성 (${biblicalRefs.filter(r => !r.is_active).length})`,  active: 'bg-gray-500 text-white border-gray-500' },
            ].map(tab => (
              <button
                key={tab.key}
                onClick={() => setBiblicalFilter(tab.key)}
                className={`text-xs px-3 py-1.5 rounded-full border transition ${biblicalFilter === tab.key ? tab.active : 'bg-white text-gray-600 border-gray-300 hover:border-purple-400'}`}
              >{tab.label}</button>
            ))}
          </div>

          {/* 목록 */}
          {biblicalRefs.length === 0 ? (
            <div className="border-2 border-dashed border-purple-200 rounded-xl p-8 text-center bg-purple-50">
              <p className="text-3xl mb-2">📖</p>
              <p className="font-bold text-purple-700 mb-1">등록된 참고자료가 없습니다</p>
              <p className="text-xs text-purple-600">+ 자료 등록 버튼을 눌러 성경구절·상담 원칙 등을 등록하세요</p>
            </div>
          ) : (
            <div className="space-y-3">
              {biblicalRefs
                .filter(r => biblicalFilter === 'all' || (biblicalFilter === 'active' ? r.is_active : !r.is_active))
                .map(ref => {
                  const catLabel = BIBLICAL_CATEGORIES.find(c => c.value === ref.category)?.label || ref.category;
                  return (
                    <div key={ref.id} className={`border rounded-xl p-4 ${ref.is_active ? 'border-purple-200 bg-purple-50' : 'border-gray-200 bg-gray-50 opacity-60'}`}>
                      <div className="flex items-start justify-between gap-3">
                        <div className="flex-1 min-w-0">
                          <div className="flex items-center gap-2 mb-1 flex-wrap">
                            <span className={`text-xs px-2 py-0.5 rounded-full font-bold shrink-0 ${ref.is_active ? 'bg-purple-200 text-purple-800' : 'bg-gray-200 text-gray-600'}`}>
                              {ref.is_active ? '● 활성' : '○ 비활성'}
                            </span>
                            <span className="font-bold text-gray-800 text-sm truncate">{ref.title}</span>
                          </div>
                          <span className="text-xs bg-white border border-purple-200 text-purple-700 px-2 py-0.5 rounded-full">{catLabel}</span>
                          <p className="text-xs text-gray-500 mt-2 font-mono bg-white border border-gray-100 rounded p-2 line-clamp-2">
                            {ref.content.slice(0, 120)}{ref.content.length > 120 ? '…' : ''}
                          </p>
                        </div>
                        <div className="flex flex-col gap-1 shrink-0">
                          <button
                            onClick={() => toggleBiblicalRef(ref.id)}
                            className={`text-xs px-2 py-1 rounded font-bold ${ref.is_active ? 'bg-gray-200 text-gray-700 hover:bg-gray-300' : 'bg-green-200 text-green-700 hover:bg-green-300'}`}
                          >
                            {ref.is_active ? '비활성' : '활성화'}
                          </button>
                          <button
                            onClick={() => editBiblicalRef(ref)}
                            className="bg-blue-500 text-white text-xs px-2 py-1 rounded font-bold hover:bg-blue-600"
                          >✏️ 수정</button>
                          <button
                            onClick={() => deleteBiblicalRef(ref.id, ref.title)}
                            className="bg-red-500 text-white text-xs px-2 py-1 rounded font-bold hover:bg-red-600"
                          >🗑️ 삭제</button>
                        </div>
                      </div>
                    </div>
                  );
                })}
            </div>
          )}

          {/* 안내 */}
          <div className="mt-5 bg-purple-50 border border-purple-200 rounded-xl p-4">
            <p className="text-xs font-bold text-purple-800 mb-2">📌 참고자료 활용 안내</p>
            <ul className="text-xs text-purple-700 space-y-1">
              <li>• 🕊️ 성경적 상담 선택 시 AI 분석에 <strong>우선 적용</strong>됩니다</li>
              <li>• '전체 공통'은 모든 검사에 항상 포함되며, 카테고리별 자료와 함께 제공됩니다</li>
              <li>• 활성 자료만 분석에 반영됩니다. 비활성화하면 분석에서 제외됩니다</li>
              <li>• 정렬순서 낮은 숫자가 먼저 적용됩니다</li>
            </ul>
          </div>
        </div>
        {/* ── 성경적 상담 참고자료 섹션 끝 ────────────────────── */}

      </div>
    </div>
  );

  // PHQ-9 결과 화면
  if (view === "phq9Result") {
    const result = calcPhq9();
    return (
      <div className="min-h-screen bg-gray-50 p-4">
        <div className="max-w-4xl mx-auto bg-white rounded-xl shadow p-6">
          <div className="flex justify-between items-center mb-6">
            <h1 className="text-2xl font-bold text-indigo-800">😔 PHQ-9 우울증 선별 결과</h1>
            <button onClick={() => setView(isCounselor ? "counselorResults" : "login")} className="bg-gray-400 text-white px-4 py-2 rounded-lg text-sm hover:bg-gray-500">
              ← 목록
            </button>
          </div>
          <div className="border rounded-lg p-4 mb-6 bg-gray-50">
            <p className="text-sm"><strong>세션 ID:</strong> {sessionId}</p>
            <p className="text-sm"><strong>전화번호:</strong> {userInfo.phone || "N/A"}</p>
            <p className="text-lg font-bold mt-2">총점: {result.total}/27 ({result.level})</p>
          </div>
          <div className={`p-4 rounded-lg mb-6 ${result.color === 'green' ? 'bg-green-50 border border-green-200' : result.color === 'yellow' ? 'bg-yellow-50 border border-yellow-200' : result.color === 'orange' ? 'bg-orange-50 border border-orange-200' : 'bg-red-50 border border-red-200'}`}>
            <h3 className="font-bold mb-2">해석</h3>
            <p className="text-sm">
              {result.total < 5 && "우울증 증상이 거의 없습니다."}
              {result.total >= 5 && result.total < 10 && "가벼운 우울 증상이 있습니다. 필요시 전문가 상담을 고려하세요."}
              {result.total >= 10 && result.total < 15 && "중간 정도의 우울 증상이 있습니다. 전문가 상담을 권장합니다."}
              {result.total >= 15 && result.total < 20 && "중간-심도의 우울 증상이 있습니다. 전문가의 평가와 치료가 필요합니다."}
              {result.total >= 20 && "심한 우울 증상이 있습니다. 즉시 전문가의 도움을 받으시기 바랍니다."}
            </p>
          </div>
          <div className="space-y-2">
            <h3 className="font-bold mb-2">응답 내역</h3>
            {phq9Q.map(q => (
              <div key={q.num} className="border-b pb-2">
                <p className="text-sm text-gray-600">{q.num}. {q.content}</p>
                <p className="text-sm font-semibold">응답: {phq9Responses[q.num]}점</p>
              </div>
            ))}
          </div>
          <AiAnalysisBox
            aiKey="PHQ9"
            onRun={() => {
              const r = calcPhq9();
              runAiAnalysis("PHQ9", "PHQ9", {
                total: r.total, level: r.level,
                items: phq9Q.map(q => ({ question: q.content, score: phq9Responses[q.num] || 0 }))
              });
            }}
          />

          {/* 💬 AI 상담 채팅 */}
          <ChatBox testType="PHQ9" initialPrompts={[
            "우울증 정도가 높은 내담자에게 어떤 접근이 필요한가요?",
            "PHQ-9 결과를 바탕으로 첫 상담을 어떻게 시작하면 좋을까요?",
            "우울 증상이 일상생활에 미치는 영향을 어떻게 평가하나요?",
            "우울증 개선을 위한 구체적인 개입 방법을 제안해주세요"
          ]} />
        </div>
      </div>
    );
  }
  if (view === "gad7Result") {
    const result = calcGad7();
    return (
      <div className="min-h-screen bg-gray-50 p-4">
        <div className="max-w-4xl mx-auto bg-white rounded-xl shadow p-6">
          <div className="flex justify-between items-center mb-6">
            <h1 className="text-2xl font-bold text-orange-800">😰 GAD-7 범불안장애 선별 결과</h1>
            <button onClick={() => setView(isCounselor ? "counselorResults" : "login")} className="bg-gray-400 text-white px-4 py-2 rounded-lg text-sm hover:bg-gray-500">
              ← 목록
            </button>
          </div>
          <div className="border rounded-lg p-4 mb-6 bg-gray-50">
            <p className="text-sm"><strong>세션 ID:</strong> {sessionId}</p>
            <p className="text-sm"><strong>전화번호:</strong> {userInfo.phone || "N/A"}</p>
            <p className="text-lg font-bold mt-2">총점: {result.total}/21 ({result.level})</p>
          </div>
          <div className={`p-4 rounded-lg mb-6 ${result.color === 'green' ? 'bg-green-50 border border-green-200' : result.color === 'yellow' ? 'bg-yellow-50 border border-yellow-200' : result.color === 'orange' ? 'bg-orange-50 border border-orange-200' : 'bg-red-50 border border-red-200'}`}>
            <h3 className="font-bold mb-2">해석</h3>
            <p className="text-sm">
              {result.total < 5 && "불안 증상이 거의 없습니다."}
              {result.total >= 5 && result.total < 10 && "가벼운 불안 증상이 있습니다. 필요시 전문가 상담을 고려하세요."}
              {result.total >= 10 && result.total < 15 && "중간 정도의 불안 증상이 있습니다. 전문가 상담을 권장합니다."}
              {result.total >= 15 && "심한 불안 증상이 있습니다. 전문가의 평가와 치료가 필요합니다."}
            </p>
          </div>
          <div className="space-y-2">
            <h3 className="font-bold mb-2">응답 내역</h3>
            {gad7Q.map(q => (
              <div key={q.num} className="border-b pb-2">
                <p className="text-sm text-gray-600">{q.num}. {q.content}</p>
                <p className="text-sm font-semibold">응답: {gad7Responses[q.num]}점</p>
              </div>
            ))}
          </div>
          <AiAnalysisBox
            aiKey="GAD7"
            onRun={() => {
              const r = calcGad7();
              runAiAnalysis("GAD7", "GAD7", {
                total: r.total, level: r.level,
                items: gad7Q.map(q => ({ question: q.content, score: gad7Responses[q.num] || 0 }))
              });
            }}
          />

          {/* 💬 AI 상담 채팅 */}
          <ChatBox testType="GAD7" initialPrompts={[
            "불안 증상이 심한 경우 초기 상담 전략은 무엇인가요?",
            "GAD-7 결과에서 특히 주목해야 할 문항이 있나요?",
            "불안장애와 일상 기능 저하의 관계를 어떻게 평가하나요?",
            "불안 완화를 위한 즉각적인 개입 방법을 알려주세요"
          ]} />
        </div>
      </div>
    );
  }

  // DASS-21 결과 화면
  if (view === "dass21Result") {
    const result = calcDass21();
    return (
      <div className="min-h-screen bg-gray-50 p-4">
        <div className="max-w-4xl mx-auto bg-white rounded-xl shadow p-6">
          <div className="flex justify-between items-center mb-6">
            <h1 className="text-2xl font-bold text-teal-800">📊 DASS-21 결과</h1>
            <button onClick={() => setView(isCounselor ? "counselorResults" : "login")} className="bg-gray-400 text-white px-4 py-2 rounded-lg text-sm hover:bg-gray-500">
              ← 목록
            </button>
          </div>
          <div className="border rounded-lg p-4 mb-6 bg-gray-50">
            <p className="text-sm"><strong>세션 ID:</strong> {sessionId}</p>
            <p className="text-sm"><strong>전화번호:</strong> {userInfo.phone || "N/A"}</p>
          </div>
          <div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
            <div className={`p-4 rounded-lg border-2 ${result.depression.color === 'green' ? 'border-green-300 bg-green-50' : result.depression.color === 'blue' ? 'border-blue-300 bg-blue-50' : result.depression.color === 'yellow' ? 'border-yellow-300 bg-yellow-50' : result.depression.color === 'orange' ? 'border-orange-300 bg-orange-50' : 'border-red-300 bg-red-50'}`}>
              <h3 className="font-bold text-lg mb-2">😔 우울</h3>
              <p className="text-2xl font-bold">{result.depression.score}</p>
              <p className="text-sm mt-1">{result.depression.level}</p>
            </div>
            <div className={`p-4 rounded-lg border-2 ${result.anxiety.color === 'green' ? 'border-green-300 bg-green-50' : result.anxiety.color === 'blue' ? 'border-blue-300 bg-blue-50' : result.anxiety.color === 'yellow' ? 'border-yellow-300 bg-yellow-50' : result.anxiety.color === 'orange' ? 'border-orange-300 bg-orange-50' : 'border-red-300 bg-red-50'}`}>
              <h3 className="font-bold text-lg mb-2">😰 불안</h3>
              <p className="text-2xl font-bold">{result.anxiety.score}</p>
              <p className="text-sm mt-1">{result.anxiety.level}</p>
            </div>
            <div className={`p-4 rounded-lg border-2 ${result.stress.color === 'green' ? 'border-green-300 bg-green-50' : result.stress.color === 'blue' ? 'border-blue-300 bg-blue-50' : result.stress.color === 'yellow' ? 'border-yellow-300 bg-yellow-50' : result.stress.color === 'orange' ? 'border-orange-300 bg-orange-50' : 'border-red-300 bg-red-50'}`}>
              <h3 className="font-bold text-lg mb-2">😓 스트레스</h3>
              <p className="text-2xl font-bold">{result.stress.score}</p>
              <p className="text-sm mt-1">{result.stress.level}</p>
            </div>
          </div>
          <div className="space-y-2">
            <h3 className="font-bold mb-2">응답 내역</h3>
            {dass21Q.map(q => (
              <div key={q.num} className="border-b pb-2">
                <p className="text-sm text-gray-600">{q.num}. {q.content} <span className="text-xs text-gray-400">({q.scale})</span></p>
                <p className="text-sm font-semibold">응답: {dass21Responses[q.num]}점</p>
              </div>
            ))}
          </div>
          <AiAnalysisBox
            aiKey="DASS21"
            onRun={() => {
              const r = calcDass21();
              runAiAnalysis("DASS21", "DASS21", {
                depression: { score: r.depression.score, level: r.depression.level },
                anxiety: { score: r.anxiety.score, level: r.anxiety.level },
                stress: { score: r.stress.score, level: r.stress.level }
              });
            }}
          />

          {/* 💬 AI 상담 채팅 */}
          <ChatBox testType="DASS21" initialPrompts={[
            "우울/불안/스트레스가 모두 높을 때 우선순위는 무엇인가요?",
            "DASS-21 결과에서 가장 시급한 개입 영역은 어디인가요?",
            "세 가지 영역 간의 상호작용을 어떻게 이해해야 하나요?",
            "각 영역별 맞춤 상담 전략을 제안해주세요"
          ]} />
        </div>
      </div>
    );
  }

  // Big5 결과 화면
  if (view === "pricingPlans") {
    const plans = [
      {
        name: "무료 체험",
        type: "free",
        price: "0원",
        period: "평생",
        quota: "5회",
        features: ["모든 검사 이용 가능", "✨ AI 실시간 분석 5회", "데이터 90일 보관", "커뮤니티 지원"],
        color: "gray",
        current: subscription?.subscription_type === 'free'
      },
      {
        name: "Basic 월간",
        type: "basic",
        price: "29,900원",
        period: "월",
        quota: "30회/월",
        features: ["모든 검사 이용 가능", "✨ AI 실시간 분석 무제한", "데이터 90일 보관", "대시보드 무제한", "이메일 지원"],
        color: "blue",
        recommended: true,
        current: subscription?.subscription_type === 'basic'
      },
      {
        name: "Professional 월간",
        type: "professional",
        price: "49,900원",
        period: "월",
        quota: "100회/월",
        features: ["모든 검사 이용 가능", "✨ AI 실시간 분석 무제한", "데이터 1년 보관", "고급 대시보드", "우선 지원", "맞춤 리포트"],
        color: "purple",
        current: subscription?.subscription_type === 'professional'
      },
      {
        name: "Basic 연간",
        type: "basic_annual",
        price: "287,040원",
        period: "년",
        quota: "360회/년",
        features: ["Basic 월간 모든 기능", "✨ AI 실시간 분석 무제한", "20% 할인 (71,760원 절약)", "데이터 1년 보관"],
        color: "green",
        badge: "20% 할인",
        current: subscription?.subscription_type === 'basic_annual'
      },
      {
        name: "Professional 연간",
        type: "professional_annual",
        price: "479,040원",
        period: "년",
        quota: "1,200회/년",
        features: ["Professional 월간 모든 기능", "✨ AI 실시간 분석 무제한", "20% 할인 (119,760원 절약)", "데이터 무제한 보관", "전담 매니저"],
        color: "pink",
        badge: "20% 할인",
        current: subscription?.subscription_type === 'professional_annual'
      }
    ];

    return (
      <div className="min-h-screen bg-gradient-to-br from-purple-50 to-pink-50 p-4">
        <div className="max-w-7xl mx-auto">
          <div className="text-center mb-8">
            <button 
              onClick={() => setView(isCounselor ? "counselorDashboard" : "login")} 
              className="mb-4 text-gray-600 hover:text-gray-800 flex items-center gap-2 mx-auto"
            >
              ← 돌아가기
            </button>
            <h1 className="text-4xl font-bold text-gray-800 mb-2">💎 구독 플랜 선택</h1>
            <p className="text-gray-600">필요에 맞는 플랜을 선택하고 무제한으로 검사를 생성하세요</p>
          </div>

          {subscription && (
            <div className="bg-blue-50 border-2 border-blue-200 rounded-xl p-4 mb-6 max-w-2xl mx-auto">
              <div className="flex items-center gap-3">
                <span className="text-3xl">ℹ️</span>
                <div>
                  <p className="font-bold text-blue-900">
                    현재 플랜: {plans.find(p => p.current)?.name}
                  </p>
                  <p className="text-sm text-blue-700">
                    남은 쿼터: {(subscription?.quota_total ?? 0) - (subscription?.quota_used ?? 0)}/{subscription?.quota_total ?? 0}
                  </p>
                </div>
              </div>
            </div>
          )}

          <div className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-5 gap-4">
            {plans.map(plan => (
              <div 
                key={plan.type}
                className={`relative bg-white rounded-2xl shadow-lg overflow-hidden transition-transform hover:scale-105 ${
                  plan.recommended ? 'ring-4 ring-purple-400' : ''
                } ${plan.current ? 'opacity-60' : ''}`}
              >
                {plan.recommended && (
                  <div className="absolute top-0 right-0 bg-purple-500 text-white text-xs font-bold px-3 py-1 rounded-bl-lg">
                    추천 ⭐
                  </div>
                )}
                {plan.badge && (
                  <div className="absolute top-0 left-0 bg-red-500 text-white text-xs font-bold px-3 py-1 rounded-br-lg">
                    {plan.badge}
                  </div>
                )}
                {plan.current && (
                  <div className="absolute top-0 left-0 right-0 bg-green-500 text-white text-xs font-bold py-2 text-center">
                    현재 플랜
                  </div>
                )}

                <div className={`p-6 ${plan.current ? 'pt-12' : 'pt-6'}`}>
                  <h3 className="text-xl font-bold text-gray-800 mb-2">{plan.name}</h3>
                  <div className="mb-4">
                    <span className="text-3xl font-bold text-gray-900">{plan.price}</span>
                    <span className="text-gray-600">/{plan.period}</span>
                  </div>
                  <div className="mb-4 pb-4 border-b">
                    <span className="text-sm text-gray-600">검사 쿼터</span>
                    <p className="text-lg font-bold text-purple-600">{plan.quota}</p>
                  </div>
                  <ul className="space-y-2 mb-6">
                    {plan.features.map((feature, idx) => (
                      <li key={idx} className="text-sm text-gray-700 flex items-start gap-2">
                        <span className="text-green-500 mt-0.5">✓</span>
                        <span>{feature}</span>
                      </li>
                    ))}
                  </ul>
                  {!plan.current && (
                    <button
                      onClick={async () => {
                        if (plan.type === 'free') {
                          alert('이미 무료 체험을 이용 중입니다.');
                          return;
                        }
                        if (confirm(`${plan.name} 플랜으로 변경하시겠습니까?\n\n가격: ${plan.price}/${plan.period}\n쿼터: ${plan.quota}`)) {
                          try {
                            // 결제 처리 (가상)
                            const amount = parseInt(plan.price.replace(/,/g, '').replace('원', ''));
                            const paymentResult = await api.processPayment(counselorPhone, plan.type, amount);
                            
                            if (paymentResult.success) {
                              alert(`✅ ${plan.name} 구독이 완료되었습니다!\n\n✨ AI 실시간 분석이 무제한으로 활성화되었습니다.`);
                              // 구독 정보 새로고침
                              const subResult = await api.getSubscription(counselorPhone);
                              if (subResult.success) {
                                setSubscription(subResult.data);
                              }
                              // 유료 플랜 전환 시 AI 분석 횟수 카운터 초기화 (무제한 전환)
                              setAiUsageCount(0);
                              if (counselorPhone) {
                                localStorage.removeItem("ai_usage_" + counselorPhone);
                              }
                              // 기존에 막혀있던 AI 분석 에러 상태 초기화
                              setAiError({});
                              setView("counselorDashboard");
                            } else {
                              alert('❌ 결제 실패: ' + paymentResult.error);
                            }
                          } catch (error) {
                            alert('❌ 결제 처리 중 오류가 발생했습니다.');
                          }
                        }
                      }}
                      className={`w-full py-3 rounded-lg font-bold text-white transition ${
                        plan.color === 'gray' ? 'bg-gray-400 hover:bg-gray-500' :
                        plan.color === 'blue' ? 'bg-blue-600 hover:bg-blue-700' :
                        plan.color === 'purple' ? 'bg-purple-600 hover:bg-purple-700' :
                        plan.color === 'green' ? 'bg-green-600 hover:bg-green-700' :
                        'bg-pink-600 hover:bg-pink-700'
                      }`}
                    >
                      {plan.type === 'free' ? '무료 시작' : '구독하기'}
                    </button>
                  )}
                  {plan.current && (
                    <div className="w-full py-3 rounded-lg font-bold text-center bg-gray-200 text-gray-600">
                      사용 중
                    </div>
                  )}
                </div>
              </div>
            ))}
          </div>

          <div className="mt-8 bg-white rounded-xl shadow-lg p-6 max-w-3xl mx-auto">
            <h3 className="font-bold text-lg mb-4">💡 플랜 선택 가이드</h3>
            <div className="space-y-3 text-sm text-gray-700">
              <p>• <strong>무료 체험</strong>: 처음 시작하는 상담사에게 적합 (5회 무료)</p>
              <p>• <strong>Basic</strong>: 월 10-30명의 내담자를 관리하는 개인 상담사</p>
              <p>• <strong>Professional</strong>: 월 30-100명 이상의 내담자를 관리하는 전문 상담사</p>
              <p>• <strong>연간 플랜</strong>: 20% 할인 혜택 (장기 사용 시 추천)</p>
            </div>
          </div>
        </div>
      </div>
    );
  }

  // 번아웃 검사 결과 화면
  if (view === "burnoutResult") {
    
    // 응답이 없는 경우 경고
    if (Object.keys(burnoutResponses).length === 0) {
      return (
        <div className="min-h-screen bg-gray-50 p-4 flex items-center justify-center">
          <div className="bg-white rounded-xl shadow-lg p-8 text-center">
            <h1 className="text-2xl font-bold text-red-600 mb-4">⚠️ 데이터 오류</h1>
            <p className="text-gray-600 mb-4">검사 응답 데이터를 찾을 수 없습니다.</p>
            <p className="text-sm text-gray-500 mb-4">세션 ID: {sessionId || 'N/A'}</p>
            <button 
              onClick={() => setView(isCounselor ? "counselorResults" : "login")} 
              className="bg-gray-400 text-white px-6 py-2 rounded-lg hover:bg-gray-500"
            >
              ← 돌아가기
            </button>
          </div>
        </div>
      );
    }
    
    try {
      const result = calcBurnout();
      
      if (!result || !result.domains) {
        return (
          <div className="min-h-screen bg-gray-50 p-4 flex items-center justify-center">
            <div className="bg-white rounded-xl shadow-lg p-8 text-center">
              <h1 className="text-2xl font-bold text-red-600 mb-4">⚠️ 데이터 오류</h1>
              <p className="text-gray-600 mb-4">검사 결과를 계산할 수 없습니다.</p>
              <button 
                onClick={() => setView(isCounselor ? "counselorResults" : "login")} 
                className="bg-gray-400 text-white px-6 py-2 rounded-lg hover:bg-gray-500"
              >
                ← 돌아가기
              </button>
            </div>
          </div>
        );
      }
      
      const { domains, totalScore, percentage, level, crisis, domainCrisis } = result;
      
      
      // 레벨별 색상 및 아이콘
      const levelConfig = {
        "매우 낮음": { color: "bg-green-100 text-green-800 border-green-300", icon: "😊" },
        "낮음": { color: "bg-blue-100 text-blue-800 border-blue-300", icon: "🙂" },
        "보통": { color: "bg-yellow-100 text-yellow-800 border-yellow-300", icon: "😐" },
        "높음": { color: "bg-orange-100 text-orange-800 border-orange-300", icon: "😰" },
        "매우 높음": { color: "bg-red-100 text-red-800 border-red-300", icon: "🔥" }
      };
      
      const config = levelConfig[level] || levelConfig["보통"];
    
    return (
      <div className="min-h-screen bg-gray-50 p-4">
        <div className="max-w-5xl mx-auto bg-white rounded-xl shadow-lg p-6">
          <div className="flex justify-between items-center mb-6">
            <h1 className="text-3xl font-bold text-red-600">🔥 번아웃 증후군 검사 결과 (K-MBI+)</h1>
            <button onClick={() => setView(isCounselor ? "counselorResults" : "login")} className="bg-gray-400 text-white px-4 py-2 rounded-lg text-sm hover:bg-gray-500">
              ← 목록
            </button>
          </div>
          
          {/* 세션 정보 */}
          <div className="border rounded-lg p-4 mb-6 bg-gray-50">
            <p className="text-sm"><strong>세션 ID:</strong> {sessionId}</p>
            <p className="text-sm"><strong>전화번호:</strong> {userInfo.phone || "N/A"}</p>
          </div>
          
          {/* 위기 경고 배너 */}
          {crisis && (
            <div className="mb-6 bg-red-50 border-2 border-red-400 rounded-lg p-4">
              <div className="flex items-start gap-3">
                <span className="text-3xl">⚠️</span>
                <div>
                  <h3 className="text-lg font-bold text-red-700 mb-2">🚨 심각한 번아웃 상태</h3>
                  <p className="text-sm text-red-600 mb-2">
                    전반적인 번아웃 수준이 매우 높거나, 하나 이상의 영역에서 위기 수준의 점수가 나타났습니다.
                  </p>
                  <p className="text-sm text-red-700 font-semibold">
                    즉각적인 전문가 상담과 휴식이 필요합니다.
                  </p>
                </div>
              </div>
            </div>
          )}
          
          {/* 전체 점수 카드 */}
          <div className={`border-2 rounded-lg p-6 mb-6 ${config.color}`}>
            <div className="flex items-center justify-between mb-4">
              <h2 className="text-2xl font-bold">전체 번아웃 수준</h2>
              <span className="text-5xl">{config.icon}</span>
            </div>
            <div className="flex items-baseline gap-4 mb-2">
              <span className="text-5xl font-bold">{totalScore}</span>
              <span className="text-2xl text-gray-600">/ 240점</span>
              <span className="text-3xl font-bold ml-4">{percentage}%</span>
            </div>
            <div className="w-full bg-gray-200 rounded-full h-6 mb-3">
              <div 
                className={`h-6 rounded-full ${percentage >= 75 ? 'bg-red-600' : percentage >= 50 ? 'bg-orange-500' : percentage >= 30 ? 'bg-yellow-500' : 'bg-green-500'}`}
                style={{ width: `${percentage}%` }}
              ></div>
            </div>
            <p className="text-xl font-bold">{level}</p>
          </div>
          
          {/* 영역별 점수 */}
          <div className="mb-6">
            <h2 className="text-xl font-bold mb-4 text-gray-800">📊 영역별 분석</h2>
            <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
              {domains.map((domain, idx) => {
                const isCrisis = domainCrisis.includes(domain.name);
                
                return (
                  <div key={domain.id || idx} className={`border rounded-lg p-4 ${isCrisis ? 'bg-red-50 border-red-300' : 'bg-white'}`}>
                    <div className="flex justify-between items-center mb-2">
                      <h3 className="font-bold text-lg">{domain.name}</h3>
                      {isCrisis && <span className="text-red-600 font-bold text-sm">⚠️ 위기</span>}
                    </div>
                    <div className="flex items-baseline gap-2 mb-2">
                      <span className="text-3xl font-bold">{domain.score}</span>
                      <span className="text-sm text-gray-600">/ {domain.max}점</span>
                      <span className="text-xl font-bold ml-2">{domain.percentage}%</span>
                    </div>
                    <div className="w-full bg-gray-200 rounded-full h-3 mb-2">
                      <div 
                        className={`h-3 rounded-full ${isCrisis ? 'bg-red-600' : 'bg-blue-500'}`}
                        style={{ width: `${domain.percentage}%` }}
                      ></div>
                    </div>
                    <p className="text-xs text-gray-600 mb-2">
                      <strong>수준:</strong> {domain.level}
                    </p>
                    <p className="text-sm text-gray-700">{domain.description}</p>
                  </div>
                );
              })}
            </div>
          </div>
          
          {/* 해석 및 권고사항 */}
          <div className="bg-blue-50 border border-blue-200 rounded-lg p-6">
            <h2 className="text-xl font-bold mb-4 text-blue-800">💡 결과 해석 및 권고사항</h2>
            <div className="space-y-3 text-sm text-gray-700">
              <div>
                <p className="font-bold text-base mb-1">📌 점수 해석 기준:</p>
                <ul className="list-disc ml-5 space-y-1">
                  <li>0-30%: 매우 낮음 (건강한 상태)</li>
                  <li>31-50%: 낮음 (주의 필요)</li>
                  <li>51-70%: 보통 (관리 필요)</li>
                  <li>71-85%: 높음 (상담 권장)</li>
                  <li>86-100%: 매우 높음 (즉시 개입 필요)</li>
                </ul>
              </div>
              
              <div>
                <p className="font-bold text-base mb-1">🩺 권장 조치:</p>
                <ul className="list-disc ml-5 space-y-1">
                  {percentage < 30 && <li>현재 건강한 상태를 유지하고 있습니다. 지속적인 자기 관리를 권장합니다.</li>}
                  {percentage >= 30 && percentage < 50 && <li>가벼운 번아웃 증상이 나타나고 있습니다. 충분한 휴식과 스트레스 관리가 필요합니다.</li>}
                  {percentage >= 50 && percentage < 70 && <li>번아웃 증상이 보통 수준입니다. 전문가 상담 및 생활 습관 개선을 고려해 보세요.</li>}
                  {percentage >= 70 && percentage < 85 && <li>높은 수준의 번아웃입니다. 전문 상담사와의 상담을 권장합니다.</li>}
                  {percentage >= 85 && <li>매우 심각한 번아웃 상태입니다. 즉시 전문가의 도움을 받으시기 바랍니다.</li>}
                </ul>
              </div>
              
              <div>
                <p className="font-bold text-base mb-1">🌱 자가 관리 팁:</p>
                <ul className="list-disc ml-5 space-y-1">
                  <li>규칙적인 수면 패턴 유지 (하루 7-8시간)</li>
                  <li>업무와 개인 시간의 명확한 경계 설정</li>
                  <li>취미 활동 및 사회적 관계 유지</li>
                  <li>정기적인 신체 활동 (주 3회 이상)</li>
                  <li>마음챙김 명상 및 이완 기법 연습</li>
                </ul>
              </div>
            </div>
          </div>
          <AiAnalysisBox
            aiKey="BURNOUT"
            onRun={() => {
              const r = calcBurnout();
              runAiAnalysis("BURNOUT", "BURNOUT", {
                totalScore: r.totalScore,
                percentage: r.percentage,
                level: r.level,
                domains: r.domains
              });
            }}
          />

          {/* 💬 AI 상담 채팅 */}
          <ChatBox testType="BURNOUT" initialPrompts={[
            "소진 수준이 높은 내담자를 위한 즉각적인 개입 방법은?",
            "K-MBI+ 결과에서 가장 우선적으로 다뤄야 할 영역은?",
            "업무 복귀를 위한 단계적 접근 방법을 알려주세요",
            "번아웃 회복을 위한 장기적인 전략을 제안해주세요"
          ]} />
        </div>
      </div>
    );
    } catch (error) {
      return (
        <div className="min-h-screen bg-gray-50 p-4 flex items-center justify-center">
          <div className="bg-white rounded-xl shadow-lg p-8 text-center">
            <h1 className="text-2xl font-bold text-red-600 mb-4">⚠️ 오류 발생</h1>
            <p className="text-gray-600 mb-4">결과 화면을 표시할 수 없습니다.</p>
            <p className="text-sm text-gray-500 mb-4">{error.toString()}</p>
            <button 
              onClick={() => setView(isCounselor ? "counselorResults" : "login")} 
              className="bg-gray-400 text-white px-6 py-2 rounded-lg hover:bg-gray-500"
            >
              ← 돌아가기
            </button>
          </div>
        </div>
      );
    }
  }

  if (view === "big5Result") {
    const result = calcBig5();
    return (
      <div className="min-h-screen bg-gray-50 p-4">
        <div className="max-w-4xl mx-auto bg-white rounded-xl shadow p-6">
          <div className="flex justify-between items-center mb-6">
            <h1 className="text-2xl font-bold text-purple-800">🌟 Big5 성격검사 결과</h1>
            <button onClick={() => setView(isCounselor ? "counselorResults" : "login")} className="bg-gray-400 text-white px-4 py-2 rounded-lg text-sm hover:bg-gray-500">
              ← 목록
            </button>
          </div>
          <div className="border rounded-lg p-4 mb-6 bg-gray-50">
            <p className="text-sm"><strong>세션 ID:</strong> {sessionId}</p>
            <p className="text-sm"><strong>전화번호:</strong> {userInfo.phone || "N/A"}</p>
          </div>
          <div className="space-y-4">
            {Object.entries(result).map(([factor, score]) => (
              <div key={factor} className="border rounded-lg p-4 bg-white">
                <div className="flex justify-between items-center mb-2">
                  <h3 className="font-bold text-lg">{factor}</h3>
                  <span className="text-2xl font-bold text-purple-600">{score}</span>
                </div>
                <div className="w-full bg-gray-200 rounded-full h-3">
                  <div className="bg-purple-600 h-3 rounded-full" style={{ width: `${(score / 5) * 100}%` }}></div>
                </div>
                <p className="text-xs text-gray-500 mt-1">
                  {factor === "외향성" && (score >= 3.5 ? "사교적이고 활동적입니다" : "조용하고 내성적입니다")}
                  {factor === "친화성" && (score >= 3.5 ? "협조적이고 친절합니다" : "독립적이고 경쟁적입니다")}
                  {factor === "성실성" && (score >= 3.5 ? "계획적이고 책임감이 강합니다" : "융통성 있고 자발적입니다")}
                  {factor === "신경성" && (score >= 3.5 ? "감정적으로 민감합니다" : "정서적으로 안정적입니다")}
                  {factor === "개방성" && (score >= 3.5 ? "창의적이고 호기심이 많습니다" : "실용적이고 현실적입니다")}
                </p>
              </div>
            ))}
          </div>
          <div className="mt-6 p-4 bg-purple-50 rounded-lg">
            <h3 className="font-bold mb-2">해석 안내</h3>
            <p className="text-sm text-gray-700">
              각 요인은 1-5점 범위로 측정됩니다. 3.5점 이상은 해당 특성이 강함을, 
              2.5점 이하는 해당 특성이 약함을 의미합니다. 중간 범위(2.5-3.5)는 
              균형 잡힌 특성을 나타냅니다.
            </p>
          </div>
          <AiAnalysisBox
            aiKey="BIG5"
            onRun={() => {
              const r = calcBig5();
              runAiAnalysis("BIG5", "BIG5", { factors: r });
            }}
          />

          {/* 💬 AI 상담 채팅 */}
          <ChatBox testType="BIG5" initialPrompts={[
            "성격 특성을 상담에 어떻게 활용할 수 있나요?",
            "Big-5 결과에서 가장 주목해야 할 요인은 무엇인가요?",
            "성격 강점을 발견하고 개발하는 방법은?",
            "성격 특성 간의 상호작용이 삶에 어떤 영향을 미치나요?"
          ]} />
        </div>
      </div>
    );
  }

  if (view === "lostResult") {
    const { axisAvg, typeCode, typeInfo, stressStyle, stabilityStyle } = calcLost();
    const counselingType = activeLinkData?.counselingType || "psychological";
    const counselingLabel = counselingType === "biblical" ? "🕊️ 성경적 상담" : "🧠 심리상담";
    const counselingColor = counselingType === "biblical" ? "bg-purple-50 border-purple-200 text-purple-700" : "bg-teal-50 border-teal-200 text-teal-700";

    const AXIS_LABELS = {
      E: { label:"에너지 방향", low:"내향(I)", high:"외향(E)", color:"teal" },
      D: { label:"의사결정",   low:"감정(F)", high:"논리(T)", color:"blue" },
      S: { label:"행동 속도",  low:"신중(J)", high:"빠름(P)", color:"orange" },
      N: { label:"안정성",     low:"안정(N)", high:"변화(C)", color:"green" },
      R: { label:"관계 민감도",low:"독립(I)", high:"관계중심(R)", color:"purple" },
      T: { label:"스트레스",   low:"회피(V)", high:"직면(A)", color:"red" },
    };
    const barColorMap = { teal:"bg-teal-500", blue:"bg-blue-500", orange:"bg-orange-400", green:"bg-green-500", purple:"bg-purple-500", red:"bg-red-400" };

    return (
      <div className="min-h-screen bg-gray-50 p-4">
        <div className="max-w-4xl mx-auto space-y-4">
          {/* 헤더 */}
          <div className="bg-white rounded-xl shadow p-6">
            <div className="flex justify-between items-center mb-4">
              <h1 className="text-2xl font-bold text-teal-800">🧭 LOST 행동 운영체계 검사 결과</h1>
              <button onClick={() => setView(isCounselor ? "counselorResults" : isAdmin ? "admin" : "login")} className="bg-gray-400 text-white px-4 py-2 rounded-lg text-sm hover:bg-gray-500">← 목록</button>
            </div>
            <div className={`border rounded-lg p-3 mb-4 ${counselingColor}`}>
              <p className="text-sm"><strong>상담 유형:</strong> {counselingLabel}</p>
              <p className="text-sm"><strong>세션 ID:</strong> {sessionId}</p>
              <p className="text-sm"><strong>전화번호:</strong> {userInfo.phone || "N/A"}</p>
            </div>

            {/* 유형 카드 */}
            <div className="bg-gradient-to-br from-teal-600 to-teal-800 rounded-2xl p-6 text-white text-center mb-4">
              <div className="text-6xl mb-2">{typeInfo.icon}</div>
              <div className="text-3xl font-black mb-1">{typeInfo.name}</div>
              <div className="text-teal-200 text-sm font-semibold mb-2">{typeInfo.eng} · 유형 코드: {typeCode}</div>
              <p className="text-teal-100 text-sm leading-relaxed max-w-md mx-auto">{typeInfo.desc}</p>
              <div className="mt-3 flex justify-center gap-2 flex-wrap">
                <span className="bg-white/20 text-white text-xs px-3 py-1 rounded-full font-semibold">
                  스트레스: {stressStyle === "A" ? "직면형" : "회피형"}
                </span>
                <span className="bg-white/20 text-white text-xs px-3 py-1 rounded-full font-semibold">
                  변화 선호도: {stabilityStyle}
                </span>
              </div>
            </div>

            {/* 핵심 특징 */}
            <div className="flex flex-wrap gap-2 justify-center mb-2">
              {typeInfo.traits.map(t => (
                <span key={t} className="bg-teal-50 border border-teal-200 text-teal-800 px-3 py-1 rounded-full text-sm font-semibold">{t}</span>
              ))}
            </div>
          </div>

          {/* 6축 레이더/바 차트 */}
          <div className="bg-white rounded-xl shadow p-6">
            <h2 className="text-lg font-bold text-gray-800 mb-4">📊 6축 프로파일</h2>
            <div className="space-y-4">
              {Object.entries(AXIS_LABELS).map(([k, info]) => {
                const val = axisAvg[k] || 3;
                const pct = ((val - 1) / 4) * 100;
                return (
                  <div key={k}>
                    <div className="flex justify-between items-center mb-1">
                      <span className="text-sm font-semibold text-gray-700">{info.label}</span>
                      <div className="flex gap-2 items-center">
                        <span className="text-xs text-gray-400">{info.low}</span>
                        <span className="text-sm font-bold text-gray-800">{Number(val).toFixed(2)}</span>
                        <span className="text-xs text-gray-400">{info.high}</span>
                      </div>
                    </div>
                    <div className="w-full bg-gray-200 rounded-full h-3 relative">
                      <div className={`h-3 rounded-full transition-all ${barColorMap[info.color]}`} style={{width:`${pct}%`}}></div>
                      <div className="absolute top-0 left-1/2 w-0.5 h-3 bg-gray-400 opacity-50"></div>
                    </div>
                    <div className="flex justify-between text-xs text-gray-400 mt-0.5">
                      <span>1.0</span><span>3.0 (중립)</span><span>5.0</span>
                    </div>
                  </div>
                );
              })}
            </div>
          </div>

          {/* 강점 · 약점 */}
          <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
            <div className="bg-white rounded-xl shadow p-5">
              <h2 className="text-base font-bold text-green-700 mb-3">💪 강점</h2>
              <ul className="space-y-2">
                {typeInfo.strength.map((s, i) => (
                  <li key={i} className="flex gap-2 text-sm text-gray-700"><span className="text-green-500 font-bold mt-0.5">✓</span>{s}</li>
                ))}
              </ul>
            </div>
            <div className="bg-white rounded-xl shadow p-5">
              <h2 className="text-base font-bold text-orange-600 mb-3">⚠️ 성장 포인트</h2>
              <ul className="space-y-2">
                {typeInfo.weakness.map((w, i) => (
                  <li key={i} className="flex gap-2 text-sm text-gray-700"><span className="text-orange-400 font-bold mt-0.5">△</span>{w}</li>
                ))}
              </ul>
            </div>
          </div>

          {/* 상황별 행동 팁 */}
          <div className="bg-white rounded-xl shadow p-5">
            <h2 className="text-base font-bold text-gray-800 mb-3">💡 상황별 행동 팁</h2>
            <div className="grid grid-cols-1 md:grid-cols-3 gap-3">
              <div className="bg-blue-50 border border-blue-100 rounded-lg p-3">
                <p className="text-xs font-bold text-blue-700 mb-1">🏢 직장</p>
                <p className="text-sm text-gray-700">{typeInfo.work}</p>
              </div>
              <div className="bg-pink-50 border border-pink-100 rounded-lg p-3">
                <p className="text-xs font-bold text-pink-700 mb-1">💑 연애·관계</p>
                <p className="text-sm text-gray-700">{typeInfo.love}</p>
              </div>
              <div className="bg-yellow-50 border border-yellow-100 rounded-lg p-3">
                <p className="text-xs font-bold text-yellow-700 mb-1">😤 스트레스</p>
                <p className="text-sm text-gray-700">{typeInfo.stress}</p>
              </div>
            </div>
          </div>

          {/* 궁합 유형 */}
          <div className="bg-white rounded-xl shadow p-5">
            <h2 className="text-base font-bold text-gray-800 mb-3">🤝 유형 궁합</h2>
            <div className="grid grid-cols-2 gap-3">
              <div>
                <p className="text-sm font-semibold text-green-700 mb-2">✅ 잘 맞는 유형</p>
                <div className="flex flex-wrap gap-2">
                  {typeInfo.match.map(m => {
                    const matchType = Object.values(LOST_TYPES).find(t => t.name === m);
                    return (
                      <span key={m} className="bg-green-50 border border-green-200 text-green-800 px-3 py-1 rounded-full text-sm font-semibold">
                        {matchType ? matchType.icon : "🤝"} {m}
                      </span>
                    );
                  })}
                </div>
              </div>
              <div>
                <p className="text-sm font-semibold text-red-600 mb-2">⚡ 마찰이 있을 수 있는 유형</p>
                <div className="flex flex-wrap gap-2">
                  {typeInfo.conflict.map(c => {
                    const conflictType = Object.values(LOST_TYPES).find(t => t.name === c);
                    return (
                      <span key={c} className="bg-red-50 border border-red-200 text-red-800 px-3 py-1 rounded-full text-sm font-semibold">
                        {conflictType ? conflictType.icon : "⚡"} {c}
                      </span>
                    );
                  })}
                </div>
              </div>
            </div>
          </div>

          {/* 전체 16유형 맵 */}
          <div className="bg-white rounded-xl shadow p-5">
            <h2 className="text-base font-bold text-gray-800 mb-3">🗺️ 전체 16유형 맵</h2>
            <div className="grid grid-cols-2 md:grid-cols-4 gap-2">
              {Object.entries(LOST_TYPES).map(([code, t]) => (
                <div key={code} className={`rounded-lg p-2 border text-center text-xs transition ${code === typeCode ? "border-teal-500 bg-teal-50 shadow-md scale-105" : "border-gray-200 bg-gray-50"}`}>
                  <div className="text-xl mb-0.5">{t.icon}</div>
                  <div className={`font-bold text-xs ${code === typeCode ? "text-teal-800" : "text-gray-700"}`}>{t.name}</div>
                  <div className="text-gray-400 text-xs">{code}</div>
                </div>
              ))}
            </div>
          </div>

          {/* AI 분석 */}
          <div className="bg-white rounded-xl shadow p-5">
            <AiAnalysisBox
              aiKey="LOST"
              onRun={() => {
                const r = calcLost();
                runAiAnalysis("LOST", "LOST", {
                  typeCode: r.typeCode,
                  typeName: r.typeInfo.name,
                  axisAvg: r.axisAvg,
                  stressStyle: r.stressStyle,
                  stabilityStyle: r.stabilityStyle,
                });
              }}
            />
          </div>

          {/* AI 채팅 */}
          <div className="bg-white rounded-xl shadow p-5">
            <ChatBox testType="LOST" initialPrompts={[
              "이 유형의 가장 큰 강점을 상담에서 어떻게 활용할 수 있나요?",
              "행동 유형이 대인관계에 미치는 영향을 설명해 주세요",
              "스트레스 반응 방식을 개선하는 방법은 무엇인가요?",
              "이 내담자에게 가장 적합한 상담 접근법은?"
            ]} />
          </div>
        </div>
      </div>
    );
  }
}

function SessionList({ sessions, onView }) {
  const [currentTime, setCurrentTime] = React.useState(Date.now());
  
  // 1초마다 시간 업데이트 (카운트다운)
  React.useEffect(() => {
    const timer = setInterval(() => {
      setCurrentTime(Date.now());
    }, 1000);
    return () => clearInterval(timer);
  }, []);
  
  if (sessions.length === 0) return (
    <div className="text-center py-12 text-gray-400">
      <div className="text-5xl mb-3">📋</div>
      <p>제출된 검사가 없습니다</p>
    </div>
  );
  
  // 만료 시간 계산 함수
  const getTimeRemaining = (createdAt) => {
    const now = currentTime;
    const createdTime = new Date(createdAt).getTime();
    const TWENTY_FOUR_HOURS = 24 * 60 * 60 * 1000;
    const elapsed = now - createdTime;
    const remaining = TWENTY_FOUR_HOURS - elapsed;
    
    if (remaining <= 0) {
      return { expired: true, text: "만료됨", color: "text-red-600" };
    }
    
    const hours = Math.floor(remaining / (60 * 60 * 1000));
    const minutes = Math.floor((remaining % (60 * 60 * 1000)) / (60 * 1000));
    const seconds = Math.floor((remaining % (60 * 1000)) / 1000);
    
    let color = "text-green-600";
    if (hours < 3) color = "text-red-600";
    else if (hours < 6) color = "text-orange-600";
    
    return {
      expired: false,
      text: `${hours}시간 ${minutes}분 ${seconds}초`,
      color: color,
      hours: hours
    };
  };
  
  // JSON 다운로드 함수
  const downloadJson = (sessionId, e) => {
    e.stopPropagation();
    const r = localStorage.getItem("session_" + sessionId);
    if (!r) {
      alert('❌ 검사 결과를 찾을 수 없습니다.');
      return;
    }
    
    const sessionData = JSON.parse(r);
    const jsonStr = JSON.stringify(sessionData, null, 2);
    const blob = new Blob([jsonStr], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `검사결과_${sessionData.testType}_${sessionId}_${Date.now()}.json`;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
    
    alert('✅ 검사 결과가 JSON 파일로 다운로드되었습니다!');
  };
  
  return (
    <div className="space-y-4">
      <div className="bg-yellow-50 border border-yellow-200 rounded-lg p-4">
        <p className="text-sm text-yellow-800 font-semibold">⚠️ 검사 결과는 24시간 후 자동 삭제됩니다</p>
        <p className="text-xs text-yellow-700 mt-1">중요한 결과는 <strong>💾 JSON 저장</strong> 버튼으로 로컬에 저장해주세요!</p>
      </div>
      
      <div className="overflow-x-auto">
        <table className="w-full text-sm border-collapse">
          <thead>
            <tr className="bg-gray-100">
              {["#", "검사 유형", "전화번호", "제출 시간", "⏱️ 남은 시간", "액션"].map(h => <th key={h} className="border p-2 text-left">{h}</th>)}
            </tr>
          </thead>
          <tbody>
            {sessions.map((s, i) => {
              const timeInfo = getTimeRemaining(s.createdAt);
              return (
                <tr key={s.sessionId} className={`hover:bg-gray-50 ${timeInfo.expired ? 'opacity-50 bg-red-50' : ''}`}>
                  <td className="border p-2 text-center text-gray-400">{i + 1}</td>
                  <td className="border p-2">
                    <span className={`px-2 py-0.5 rounded text-xs font-bold ${
                      s.testType === "SCT" ? "bg-blue-100 text-blue-800" : 
                      s.testType === "DSI" ? "bg-green-100 text-green-800" : 
                      s.testType === "PHQ9" ? "bg-yellow-100 text-yellow-800" : 
                      s.testType === "GAD7" ? "bg-orange-100 text-orange-800" : 
                      s.testType === "DASS21" ? "bg-pink-100 text-pink-800" : 
                      s.testType === "BIG5" ? "bg-purple-100 text-purple-800" : 
                      s.testType === "BURNOUT" ? "bg-red-100 text-red-800" : 
                      s.testType === "LOST" ? "bg-teal-100 text-teal-800" :
                      "bg-gray-100 text-gray-800"
                    }`}>
                      {s.testType === "SCT" ? "📝 문장완성" : 
                       s.testType === "DSI" ? "🔍 자아분화" : 
                       s.testType === "PHQ9" ? "😔 PHQ-9" : 
                       s.testType === "GAD7" ? "😰 GAD-7" : 
                       s.testType === "DASS21" ? "📊 DASS-21" : 
                       s.testType === "BIG5" ? "🌟 Big5" : 
                       s.testType === "BURNOUT" ? "🔥 번아웃" : 
                       s.testType === "LOST" ? "🧭 LOST" :
                       s.testType}
                    </span>
                  </td>
                  <td className="border p-2">{s.userPhone}</td>
                  <td className="border p-2 text-xs text-gray-600">{new Date(s.createdAt).toLocaleString("ko-KR")}</td>
                  <td className="border p-2">
                    <span className={`font-bold text-xs ${timeInfo.color}`}>
                      {timeInfo.expired ? '🔴 만료됨' : `⏱️ ${timeInfo.text}`}
                    </span>
                    {!timeInfo.expired && timeInfo.hours < 6 && (
                      <div className="text-xs text-red-600 mt-1 font-semibold">
                        ⚠️ 곧 삭제됩니다!
                      </div>
                    )}
                  </td>
                  <td className="border p-2">
                    <div className="flex flex-col gap-1">
                      {!timeInfo.expired ? (
                        <>
                          <button 
                            onClick={() => onView(s.sessionId)} 
                            className="bg-blue-600 text-white px-3 py-1.5 rounded text-xs font-semibold hover:bg-blue-700 w-full"
                          >
                            📊 결과 보기
                          </button>
                          <button 
                            onClick={(e) => downloadJson(s.sessionId, e)} 
                            className="bg-green-600 text-white px-3 py-1.5 rounded text-xs font-semibold hover:bg-green-700 w-full"
                            title="로컬에 JSON 파일로 저장"
                          >
                            💾 저장
                          </button>
                        </>
                      ) : (
                        <span className="text-xs text-red-600 font-semibold px-2 py-1">삭제됨</span>
                      )}
                    </div>
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
    </div>
  );

}


// 로딩 화면 제거
const loadingEl = document.getElementById('app-loading');
if (loadingEl) loadingEl.remove();
window.__REACT_RENDERED__ = true;

// Render
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <ErrorBoundary>
    <PsychologicalTestSystem />
  </ErrorBoundary>
);

