// 이 파일이 하는 일: (멘토 전용) 학생별 코스 진도 현황을 보고,
// 학생들의 전체 제출물을 테이블로 확인해 피드백을 남긴다.
import { useEffect, useState } from 'react';
import client from '../api/client';
import MentorCodingSection from '../components/MentorCodingSection';
import MentorAnalytics from '../components/MentorAnalytics';
import Card from '../components/Card';
import Badge from '../components/Badge';
import { COURSE_CATEGORIES, ALL_COURSES } from '../courseCatalog';

// 학생 한 명의 진도 카드.
// 학습 포인트: 서버는 "완료한 slug 목록"만 주고, 전체 코스 수·카테고리별 집계는
// 프론트가 카탈로그(courseCatalog)로 계산한다 — 데이터의 주인이 각자 다르다.
function StudentProgressCard({ student }) {
  const done = new Set(student.completedSlugs);
  const total = ALL_COURSES.length;
  const doneCount = ALL_COURSES.filter((c) => done.has(c.slug)).length;
  const percent = total === 0 ? 0 : Math.round((doneCount / total) * 100);

  // 비밀번호 재설정 폼 상태 — 학생이 비밀번호를 잊었을 때 멘토가 대신 바꿔 준다.
  const [resetOpen, setResetOpen] = useState(false);
  const [newPassword, setNewPassword] = useState('');
  const [resetMessage, setResetMessage] = useState('');
  const [resetError, setResetError] = useState('');
  const [resetting, setResetting] = useState(false);

  async function resetPassword(e) {
    e.preventDefault();
    setResetError('');
    setResetMessage('');
    if (newPassword.length < 8) {
      setResetError('8자 이상으로 정해 주세요.');
      return;
    }
    setResetting(true);
    try {
      await client.post(`/mentor/users/${student.userId}/reset-password`, { newPassword });
      setResetMessage(`재설정 완료 — 학생에게 직접 알려주고, 로그인 후 바꾸게 하세요.`);
      setNewPassword('');
    } catch {
      setResetError('재설정 중 문제가 생겼어요.');
    } finally {
      setResetting(false);
    }
  }

  return (
    <div className="card" style={{ height: '100%' }}>
      <div className="assign-title-row">
        <span className="assign-title">{student.name}</span>
        <span className="badge badge-primary">
          {student.track === 'DESIGN' ? '디자인' : '개발'}
        </span>
        <span className="muted" style={{ fontSize: 12.5 }}>@{student.username}</span>
      </div>
      <div className="stat-row" style={{ margin: '10px 0 12px' }}>
        <div className="stat">
          <span className="stat-num" style={{ fontSize: 26 }}>{percent}%</span>
          <span className="stat-label">{doneCount} / {total} 코스</span>
        </div>
        <div className="progress-track" style={{ flex: 1, minWidth: 100 }}>
          <div className="progress-fill" style={{ width: `${percent}%` }} />
        </div>
      </div>
      {/* 카테고리별 완료 수 — 어느 영역을 파고 있는지 한눈에 */}
      <div className="chip-row" style={{ marginTop: 0 }}>
        {COURSE_CATEGORIES.map((group) => {
          const groupDone = group.items.filter((i) => i.slug && done.has(i.slug)).length;
          return (
            <span
              key={group.category}
              className="chip"
              style={groupDone > 0 ? { color: 'var(--teal)', fontWeight: 700 } : undefined}
            >
              {group.category} {groupDone}/{group.items.length}
            </span>
          );
        })}
      </div>

      {/* 비밀번호 재설정 — 학생이 비밀번호를 잊었을 때 멘토가 처리하는 창구.
          학습 포인트: 이 기능은 원래 "아이디+이름만 알면 누구나" 쓸 수 있는 무인증 API였다.
          보안 검토에서 계정 탈취 경로로 확인되어, 멘토 권한 뒤로 옮겼다.
          본인 확인은 "학생 얼굴을 보고 확인한다"는 오프라인 절차가 대신한다. */}
      <div style={{ marginTop: 12, borderTop: '1px solid var(--line)', paddingTop: 10 }}>
        {!resetOpen ? (
          <button
            className="btn btn-ghost"
            style={{ fontSize: 13, padding: '4px 0' }}
            onClick={() => setResetOpen(true)}
          >
            🔑 비밀번호 재설정
          </button>
        ) : (
          <form onSubmit={resetPassword}>
            <div style={{ display: 'flex', gap: 6 }}>
              <input
                className="input"
                type="text"
                value={newPassword}
                onChange={(e) => setNewPassword(e.target.value)}
                placeholder="새 비밀번호 (8자 이상)"
                style={{ fontSize: 13 }}
              />
              <button className="btn btn-primary" type="submit" disabled={resetting}>
                {resetting ? '...' : '설정'}
              </button>
              <button className="btn btn-ghost" type="button" onClick={() => setResetOpen(false)}>
                취소
              </button>
            </div>
            {resetError && <p className="error-text" role="alert" style={{ fontSize: 12.5 }}>{resetError}</p>}
            {resetMessage && (
              <p style={{ color: 'var(--teal)', fontSize: 12.5, marginTop: 6 }}>{resetMessage}</p>
            )}
          </form>
        )}
      </div>
    </div>
  );
}

// 주차별 체크리스트 진도 표.
// 학습 포인트: 서버가 분모(totalByWeek)와 분자(학생별 doneByWeek)를 나눠서 주면,
// 프론트는 표로 배치만 한다. 셀 색은 완료율에 따라 3단계(0 / 진행 중 / 완주)로 표현 —
// 숫자를 읽기 전에 색으로 먼저 상황이 보이게 하는 것이 정보 디자인이다.
function WeeklyChecklistTable({ overview }) {
  // 주차 목록은 분모(totalByWeek)의 키에서 뽑는다. JSON을 거치면 키가 문자열이 되므로
  // 숫자로 되돌려 정렬한다. (학습 포인트: JSON 객체의 키는 항상 문자열!)
  const weeks = Object.keys(overview.totalByWeek)
    .map(Number)
    .sort((a, b) => a - b);

  function cellStyle(done, total) {
    if (total === 0 || done === 0) return { color: 'var(--muted)' };
    if (done >= total) return { color: 'var(--teal)', fontWeight: 800 };
    return { color: 'var(--primary)', fontWeight: 700 };
  }

  return (
    <Card style={{ padding: 0, overflowX: 'auto' }}>
      {/* table--nowrap: 인적사항 표는 셀이 세로로 꺾이면 못 읽는다 — 가로 스크롤로 본다 */}
      <table className="table table-static table--nowrap" style={{ minWidth: 640 }}>
        <thead>
          <tr>
            <th>학생</th>
            {weeks.map((w) => (
              <th key={w} style={{ textAlign: 'center' }}>{w}주차</th>
            ))}
            <th style={{ textAlign: 'center' }}>전체</th>
          </tr>
        </thead>
        <tbody>
          {overview.students.map((student) => {
            let doneSum = 0;
            let totalSum = 0;
            return (
              <tr key={student.userId}>
                <td style={{ fontWeight: 600, whiteSpace: 'nowrap' }}>
                  {student.name}
                  <span className="muted" style={{ fontSize: 12, marginLeft: 6 }}>
                    {student.track === 'DESIGN' ? '디자인' : '개발'}
                  </span>
                </td>
                {weeks.map((w) => {
                  const total = overview.totalByWeek[w] ?? 0;
                  const done = student.doneByWeek[w] ?? 0; // 체크 없는 주차는 키가 없어 0 처리
                  doneSum += done;
                  totalSum += total;
                  return (
                    <td
                      key={w}
                      style={{ textAlign: 'center', fontVariantNumeric: 'tabular-nums', ...cellStyle(done, total) }}
                    >
                      {done}/{total}
                    </td>
                  );
                })}
                <td
                  style={{ textAlign: 'center', fontVariantNumeric: 'tabular-nums', ...cellStyle(doneSum, totalSum) }}
                >
                  {doneSum}/{totalSum}
                </td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </Card>
  );
}

// 수습생 인적사항 명단 — 경리 담당자가 CSV로 내려받을 수 있다.
// 학습 포인트: 개인정보 화면이라 링크가 아니라 표로, 다운로드는 버튼 하나로 명확히 둔다.
function StudentRoster({ students, onChanged }) {
  // 학습 포인트: 파일 다운로드는 axios(JSON) 말고 브라우저의 링크 이동으로 처리한다.
  // withCredentials 링크 이동이면 세션 쿠키도 함께 가서, 서버가 멘토인지 확인할 수 있다.
  const csvUrl = '/api/mentor/students/export.csv';

  // 개인정보 파기 — 되돌릴 수 없는 작업이라 "이름을 그대로 입력"해야만 진행한다(오삭제 방지).
  async function purge(s) {
    const typed = window.prompt(
      `⚠️ ${s.name} 님의 계정과 모든 개인정보·학습기록을 영구히 삭제합니다. 되돌릴 수 없어요.\n` +
      `확인하려면 학생 이름을 그대로 입력하세요: ${s.name}`,
    );
    if (typed === null) return; // 취소
    if (typed.trim() !== s.name) {
      window.alert('이름이 일치하지 않아 취소했어요.');
      return;
    }
    try {
      await client.delete(`/mentor/students/${s.userId}`);
      onChanged(); // 목록 새로고침
    } catch {
      window.alert('삭제 중 문제가 생겼어요. 잠시 후 다시 시도해 주세요.');
    }
  }

  // 기수(코호트) 변경 — 잘못 배정됐거나 재편성할 때.
  async function changeCohort(s) {
    const next = window.prompt(`${s.name} 님의 기수를 입력하세요 (현재: ${s.cohort})`, s.cohort);
    if (next === null) return;
    const v = next.trim();
    if (!v || v === s.cohort) return;
    try {
      await client.post(`/mentor/students/${s.userId}/cohort`, { cohort: v });
      onChanged();
    } catch {
      window.alert('기수 변경 중 문제가 생겼어요. 잠시 후 다시 시도해 주세요.');
    }
  }

  return (
    <Card style={{ padding: 0, overflowX: 'auto' }}>
      <div style={{ padding: '12px 16px', display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 12 }}>
        <span className="muted" style={{ fontSize: 13 }}>
          총 {students.length}명 · 개인정보이니 취급에 주의하세요
        </span>
        <a href={csvUrl} className="btn btn-primary" style={{ fontSize: 13 }}>
          ⬇ CSV 내려받기 (경리용)
        </a>
      </div>
      {/* table--nowrap: "트랙"→"트/랙"처럼 셀이 세로로 꺾이지 않게. 가로 스크롤로 본다 */}
      <table className="table table-static table--nowrap" style={{ minWidth: 720 }}>
        <thead>
          <tr>
            <th>이름</th>
            <th>회사 이메일</th>
            <th>트랙</th>
            <th>기수</th>
            <th>생년월일</th>
            <th>연락처</th>
            <th>학교</th>
            <th>비상 연락</th>
            <th>파기</th>
          </tr>
        </thead>
        <tbody>
          {students.map((s) => (
            <tr key={s.userId}>
              <td style={{ fontWeight: 600, whiteSpace: 'nowrap' }}>{s.name}</td>
              <td style={{ whiteSpace: 'nowrap' }}>{s.companyEmail}</td>
              <td>{s.track === 'DESIGN' ? '디자인' : '개발'}</td>
              <td>
                {/* 기수 배지를 누르면 변경 — 클릭 가능함을 알 수 있게 button으로 감싼다 */}
                <button
                  className="btn btn-ghost"
                  style={{ padding: '2px 6px' }}
                  onClick={() => changeCohort(s)}
                  title="기수 변경"
                >
                  <span className="badge badge-primary">{s.cohort}기</span>
                </button>
              </td>
              <td style={{ whiteSpace: 'nowrap' }}>{s.birthDate}</td>
              <td style={{ whiteSpace: 'nowrap' }}>{s.phone}</td>
              <td style={{ whiteSpace: 'nowrap' }}>{s.school}</td>
              <td style={{ whiteSpace: 'nowrap' }} className="muted">
                {s.emergencyName}({s.emergencyRelation}) {s.emergencyPhone}
              </td>
              <td>
                {/* 퇴직·수습종료 시 개인정보 파기. 동의 화면이 약속한 '파기'를 실제로 지키는 버튼 */}
                <button
                  className="btn btn-ghost"
                  style={{ fontSize: 12.5, color: 'var(--rose)', padding: '2px 8px' }}
                  onClick={() => purge(s)}
                  title={`${s.name} 개인정보 파기`}
                >
                  파기
                </button>
              </td>
            </tr>
          ))}
        </tbody>
      </table>
      <p className="muted" style={{ fontSize: 12, padding: '0 16px 12px' }}>
        ※ [파기]는 학생의 계정·제출물·진도·퀴즈·인적사항을 <b>영구 삭제</b>합니다 —
        수습 종료/퇴직 시 개인정보 파기 의무를 지키는 수단이에요. 되돌릴 수 없습니다.
      </p>
    </Card>
  );
}

// 학생별 퀴즈 성적 요약 표.
// 학습 포인트: 서버는 코스별 최고점 목록만 주고, 응시 수·평균·만점 수 집계는 프론트가 한다.
function QuizResultsTable({ quizResults }) {
  return (
    <Card style={{ padding: 0, overflowX: 'auto' }}>
      <table className="table table-static table--nowrap" style={{ minWidth: 480 }}>
        <thead>
          <tr>
            <th>학생</th>
            <th style={{ textAlign: 'center' }}>응시 코스</th>
            <th style={{ textAlign: 'center' }}>평균 점수</th>
            <th style={{ textAlign: 'center' }}>만점 코스</th>
          </tr>
        </thead>
        <tbody>
          {quizResults.map((student) => {
            const taken = student.results.length;
            const perfect = student.results.filter((r) => r.bestScore === r.total).length;
            // 평균은 백분율로 — 코스마다 문항 수가 다를 수 있어 점수 합산보다 공정하다
            const avg =
              taken === 0
                ? null
                : Math.round(
                    (student.results.reduce((sum, r) => sum + r.bestScore / r.total, 0) / taken) * 100,
                  );
            return (
              <tr key={student.userId}>
                <td style={{ fontWeight: 600, whiteSpace: 'nowrap' }}>
                  {student.name}
                  <span className="muted" style={{ fontSize: 12, marginLeft: 6 }}>
                    {student.track === 'DESIGN' ? '디자인' : '개발'}
                  </span>
                </td>
                <td style={{ textAlign: 'center', fontVariantNumeric: 'tabular-nums' }}>{taken}</td>
                <td
                  style={{
                    textAlign: 'center',
                    fontVariantNumeric: 'tabular-nums',
                    fontWeight: 700,
                    color: avg === null ? 'var(--muted)' : avg >= 80 ? 'var(--teal)' : 'var(--primary)',
                  }}
                >
                  {avg === null ? '—' : `${avg}점`}
                </td>
                <td style={{ textAlign: 'center', fontVariantNumeric: 'tabular-nums' }}>{perfect}</td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </Card>
  );
}

// 감사기록의 행위(action)를 사람이 읽는 한국어로. 서버 enum 이름과 1:1 대응.
const AUDIT_ACTION_LABEL = {
  EXPORT_STUDENT_CSV: '명단 CSV 다운로드',
  VIEW_STUDENT_ROSTER: '명단 조회',
  RESET_STUDENT_PASSWORD: '비밀번호 재설정',
  PURGE_STUDENT: '학생 파기',
};

/**
 * 개인정보 접근 감사기록 표.
 * 학습 포인트: 감사로그는 "남기기"만으로는 반쪽이다. 멘토가 여기서 실제로 들여다볼 수 있어야
 * "누가 명단을 자주 내려받나" 같은 이상 징후를 알아챈다 — 남기기와 보기가 짝을 이뤄야 통제가 산다.
 */
function AuditLogTable({ logs }) {
  return (
    <Card style={{ padding: 0, overflow: 'hidden' }}>
      {/* table--nowrap: 시각·IP가 세로로 꺾이면 못 읽는다 — 가로 스크롤로 본다 */}
      <table className="table table--nowrap" style={{ minWidth: 640 }}>
        <thead>
          <tr>
            <th>시각</th>
            <th>행위자</th>
            <th>행위</th>
            <th>내용</th>
            <th>IP</th>
          </tr>
        </thead>
        <tbody>
          {logs.map((logRow) => (
            <tr key={logRow.id}>
              <td className="muted">{new Date(logRow.createdAt).toLocaleString('ko-KR')}</td>
              <td style={{ fontWeight: 600 }}>{logRow.actor}</td>
              <td>{AUDIT_ACTION_LABEL[logRow.action] || logRow.action}</td>
              <td>{logRow.detail}</td>
              <td className="muted" style={{ fontVariantNumeric: 'tabular-nums' }}>{logRow.ip}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </Card>
  );
}

export default function MentorPage() {
  const [submissions, setSubmissions] = useState([]);
  const [students, setStudents] = useState([]); // 학생별 코스 진도
  const [checklistOverview, setChecklistOverview] = useState(null); // 주차별 체크리스트 진도
  const [quizResults, setQuizResults] = useState([]); // 학생별 퀴즈 성적
  const [roster, setRoster] = useState([]); // 수습생 인적사항 명단
  const [auditLogs, setAuditLogs] = useState([]); // 개인정보 접근 감사기록
  const [loadError, setLoadError] = useState(false); // 일부 데이터 로딩 실패 여부
  const [loading, setLoading] = useState(true);
  const [selectedId, setSelectedId] = useState(null); // 클릭해서 펼친 제출물 id
  const [feedbackDraft, setFeedbackDraft] = useState('');
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState('');

  function load() {
    // 제출물·코스 진도·체크리스트 진도를 함께 불러온다.
    // 학습 포인트: Promise.all은 하나만 실패해도 전체가 실패해서, 잘 되던 섹션까지
    // 빈 화면이 된다. allSettled는 "각자 결과를 따로" 주므로 성공한 섹션은 그대로
    // 보여주고, 실패가 있으면 에러 배너만 띄울 수 있다. (리뷰에서 잡힌 개선점!)
    return Promise.allSettled([
      client.get('/mentor/submissions'),
      client.get('/mentor/course-progress'),
      client.get('/mentor/checklist-progress'),
      client.get('/mentor/quiz-results'),
      client.get('/mentor/students'),
      client.get('/mentor/audit-logs'),
    ])
      .then(([subsRes, progressRes, checklistRes, quizRes, rosterRes, auditRes]) => {
        if (subsRes.status === 'fulfilled') setSubmissions(subsRes.value.data);
        if (progressRes.status === 'fulfilled') setStudents(progressRes.value.data);
        if (checklistRes.status === 'fulfilled') setChecklistOverview(checklistRes.value.data);
        if (quizRes.status === 'fulfilled') setQuizResults(quizRes.value.data);
        if (rosterRes.status === 'fulfilled') setRoster(rosterRes.value.data);
        if (auditRes.status === 'fulfilled') setAuditLogs(auditRes.value.data);
        const anyFailed = [subsRes, progressRes, checklistRes, quizRes, rosterRes, auditRes].some(
          (r) => r.status === 'rejected',
        );
        setLoadError(anyFailed);
      })
      .finally(() => setLoading(false));
  }

  useEffect(() => {
    load();
  }, []);

  const selected = submissions.find((s) => s.id === selectedId) || null;

  function selectRow(submission) {
    // 같은 행을 다시 누르면 닫는다.
    if (selectedId === submission.id) {
      setSelectedId(null);
      return;
    }
    setSelectedId(submission.id);
    // 기존 피드백이 있으면 이어서 수정할 수 있게 미리 채운다.
    setFeedbackDraft(submission.feedback || '');
    setError('');
  }

  async function saveFeedback(e) {
    e.preventDefault();
    if (!feedbackDraft.trim()) {
      setError('피드백 내용을 적어 주세요.');
      return;
    }
    setSaving(true);
    setError('');
    try {
      await client.post(`/mentor/submissions/${selectedId}/feedback`, {
        feedback: feedbackDraft,
      });
      // 저장 후 목록을 다시 불러와 상태(REVIEWED)를 화면에 반영한다.
      await load();
    } catch {
      setError('피드백 저장 중 문제가 생겼어요. 다시 시도해 주세요.');
    } finally {
      setSaving(false);
    }
  }

  if (loading) {
    return <p className="empty">불러오는 중...</p>;
  }

  return (
    <div>
      <h1 className="page-title">멘토 리뷰</h1>
      <p className="page-desc">
        학생별 학습 진도를 확인하고, 제출물에 피드백을 남기세요.
      </p>

      {/* 일부 데이터 로딩 실패 시 — 빈 상태 문구와 구분되는 에러 안내 */}
      {loadError && (
        <p className="error-text" role="alert" style={{ marginBottom: 14 }}>
          일부 데이터를 불러오지 못했어요. 잠시 후 새로고침해 주세요.
        </p>
      )}

      {/* ── 기수(코호트) 분석 대시보드 — 묶어서 본 그림 ── */}
      <MentorAnalytics />

      {/* ── 수습생 명단 (인적사항) ── */}
      <h2 className="section-title">수습생 명단</h2>
      {roster.length === 0 ? (
        <p className="empty">아직 가입한 수습생이 없어요. (학생이 회원가입하면 여기에 표시됩니다)</p>
      ) : (
        <StudentRoster students={roster} onChanged={load} />
      )}

      {/* ── 학생별 코스 진도 ── */}
      <h2 className="section-title" style={{ marginTop: 24 }}>학생별 코스 진도</h2>
      {students.length === 0 ? (
        <p className="empty">아직 학생 계정이 없어요.</p>
      ) : (
        <div className="grid-cards" style={{ marginBottom: 24 }}>
          {students.map((student) => (
            <StudentProgressCard key={student.userId} student={student} />
          ))}
        </div>
      )}

      {/* ── 주차별 체크리스트 진도 ── */}
      <h2 className="section-title">주차별 체크리스트 진도</h2>
      {!checklistOverview || checklistOverview.students.length === 0 ? (
        <p className="empty">아직 학생 계정이 없어요.</p>
      ) : Object.keys(checklistOverview.totalByWeek).length === 0 ? (
        // 시드가 안 들어간 경우 — "아무도 안 했다"와 "항목이 없다"는 다른 상황이다
        <p className="empty">등록된 체크리스트 항목이 없어요.</p>
      ) : (
        <WeeklyChecklistTable overview={checklistOverview} />
      )}

      {/* ── 퀴즈 성적 ── */}
      <h2 className="section-title" style={{ marginTop: 24 }}>퀴즈 성적</h2>
      {quizResults.length === 0 ? (
        <p className="empty">아직 학생 계정이 없어요.</p>
      ) : (
        <QuizResultsTable quizResults={quizResults} />
      )}

      {/* ── 코딩 문제 (진도표 + 제출된 코드 리뷰) ── */}
      <MentorCodingSection />

      {/* ── 제출물 리뷰 ── */}
      <h2 className="section-title" style={{ marginTop: 24 }}>제출물</h2>
      {submissions.length === 0 ? (
        <p className="empty">아직 제출물이 없어요.</p>
      ) : (
        <Card style={{ padding: 0, overflow: 'hidden' }}>
          <table className="table">
            <thead>
              <tr>
                <th>학생</th>
                <th>과제</th>
                <th>제출 시각</th>
                <th>상태</th>
              </tr>
            </thead>
            <tbody>
              {submissions.map((submission) => (
                // a11y: 상세 열기 상호작용을 <tr>이 아니라 셀 안의 진짜 <button>에 둔다.
                // (예전엔 <tr role="button">이었는데, 그러면 스크린리더 표 탐색에서 행이 '버튼'으로만
                //  읽혀 셀-열헤더 연결이 끊긴다. <tr>은 네이티브 row 역할을 유지하고, 버튼이
                //  클릭·Enter·Space·포커스를 기본으로 처리한다 — 표 의미구조도, 키보드도 모두 산다.)
                <tr key={submission.id} className={selectedId === submission.id ? 'is-selected' : undefined}>
                  <td style={{ fontWeight: 600 }}>
                    <button
                      type="button"
                      className="linklike"
                      onClick={() => selectRow(submission)}
                      aria-expanded={selectedId === submission.id}
                      aria-label={`${submission.studentName}의 ${submission.assignmentTitle} 제출물 열기`}
                    >
                      {submission.studentName}
                    </button>
                  </td>
                  <td>{submission.assignmentTitle}</td>
                  <td className="muted">
                    {new Date(submission.submittedAt).toLocaleString('ko-KR')}
                  </td>
                  <td>
                    <Badge value={submission.status} />
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </Card>
      )}

      {/* 학습 포인트: 모달 라이브러리 없이도, 선택된 행의 상세를
          테이블 아래 카드로 펼치는 방식이면 충분히 쓸 만하다. */}
      {selected && (
        <Card style={{ marginTop: 14 }}>
          <div style={{ display: 'flex', gap: 8, alignItems: 'center', marginBottom: 10 }}>
            <strong>{selected.studentName}</strong>
            <span className="muted">—</span>
            <span>{selected.assignmentTitle}</span>
            <Badge value={selected.status} />
          </div>

          <div className="field">
            <label>제출 내용</label>
            <div
              style={{
                background: 'var(--bg)',
                border: '1px solid var(--line)',
                borderRadius: 10,
                padding: '10px 14px',
                whiteSpace: 'pre-line',
              }}
            >
              {selected.content}
            </div>
          </div>

          {selected.link && (
            <div className="field">
              <label>제출 링크</label>
              <a href={selected.link} target="_blank" rel="noreferrer">
                {selected.link}
              </a>
            </div>
          )}

          <form onSubmit={saveFeedback}>
            <div className="field">
              <label>피드백</label>
              <textarea
                className="textarea"
                value={feedbackDraft}
                onChange={(e) => setFeedbackDraft(e.target.value)}
                placeholder="잘한 점과 다음에 시도해 볼 점을 구체적으로 적어 주세요."
              />
            </div>
            {error && <p className="error-text" role="alert">{error}</p>}
            <button className="btn btn-primary" type="submit" disabled={saving}>
              {saving ? '저장 중...' : '피드백 저장'}
            </button>
            <button
              className="btn btn-ghost"
              type="button"
              onClick={() => setSelectedId(null)}
              style={{ marginLeft: 8 }}
            >
              닫기
            </button>
          </form>
        </Card>
      )}

      {/* ── 개인정보 접근 기록 (감사로그) ── */}
      <h2 className="section-title" style={{ marginTop: 24 }}>개인정보 접근 기록</h2>
      <p className="page-desc" style={{ marginTop: -4 }}>
        수습생 개인정보를 누가·언제·어디서 조회/내보냈/파기했는지 기록입니다(최근 200건).
      </p>
      {auditLogs.length === 0 ? (
        <p className="empty">아직 기록이 없어요. (명단 조회·CSV 다운로드 등을 하면 여기에 남습니다)</p>
      ) : (
        <AuditLogTable logs={auditLogs} />
      )}
    </div>
  );
}
