// 이 파일이 하는 일: 주차별 과제 목록을 요일(일차)별로 묶어 보여주고, 각 과제에 대해
// 제출 폼(내용 + 링크)과 내 제출 상태·멘토 피드백을 표시한다.
import { useEffect, useState } from 'react';
import client from '../api/client';
import Badge from '../components/Badge';

const WEEKS = [1, 2, 3, 4, 5, 6, 7, 8];

// 과제 하나 = 카드 하나. 제출 폼의 입력 상태는 이 컴포넌트가 각자 가진다.
// 학습 포인트: 폼 상태를 부모(페이지)에 모으면 과제 수만큼 상태 관리가 꼬인다.
// "각 카드가 자기 폼을 책임진다"가 훨씬 단순하다.
function AssignmentCard({ assignment, submission, onSubmitted }) {
  const [content, setContent] = useState(submission?.content || '');
  const [link, setLink] = useState(submission?.link || '');
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState('');
  const [savedMessage, setSavedMessage] = useState('');

  async function handleSubmit(e) {
    e.preventDefault();
    setError('');
    setSavedMessage('');
    if (!content.trim()) {
      setError('제출 내용을 적어 주세요.');
      return;
    }
    setSaving(true);
    try {
      // 같은 과제에 다시 제출하면 서버가 기존 제출을 갱신해 준다.
      await client.post('/submissions', {
        assignmentId: assignment.id,
        content,
        link: link.trim() || null,
      });
      setSavedMessage(submission ? '다시 제출했어요.' : '제출 완료!');
      onSubmitted(); // 부모에게 "내 제출 목록 다시 불러와" 신호
    } catch {
      setError('제출 중 문제가 생겼어요. 잠시 후 다시 시도해 주세요.');
    } finally {
      setSaving(false);
    }
  }

  return (
    // 제출된 과제는 카드 왼쪽에 청록 띠가 붙는다 (.assign-card.submitted — global.css 참고)
    <div className={`card assign-card${submission ? ' submitted' : ''}`}>
      <div className="assign-title-row">
        <Badge value={assignment.kind} />
        {submission ? (
          <Badge value={submission.status} />
        ) : (
          <span className="badge badge-rose">미제출</span>
        )}
      </div>
      <div className="assign-title">{assignment.title}</div>
      <p className="muted" style={{ margin: '6px 0 12px', whiteSpace: 'pre-line', fontSize: 14 }}>
        {assignment.summary}
      </p>

      {/* 멘토 피드백이 있으면 눈에 띄게 보여준다 */}
      {submission?.feedback && (
        <div className="tip" style={{ marginBottom: 12 }}>
          <b>멘토 피드백</b>
          <div style={{ whiteSpace: 'pre-line', marginTop: 4 }}>{submission.feedback}</div>
        </div>
      )}

      {/* 학습 포인트: <details>는 JS 없이도 접기/펼치기가 되는 HTML 기본 태그.
          제출 완료된 과제는 폼을 접어두고, 미제출 과제는 펼쳐서 바로 쓰게 한다. */}
      <details className="fold" open={!submission}>
        <summary>{submission ? '다시 제출하기' : '제출하기'}</summary>
        <form onSubmit={handleSubmit}>
          <div className="field">
            <label>제출 내용</label>
            <textarea
              className="textarea"
              value={content}
              onChange={(e) => setContent(e.target.value)}
              placeholder="무엇을 했고, 무엇을 배웠는지 적어 주세요."
            />
          </div>
          <div className="field">
            <label>링크 (선택)</label>
            <input
              className="input"
              value={link}
              onChange={(e) => setLink(e.target.value)}
              placeholder="예: Gitea 저장소 주소, 결과물 링크"
            />
          </div>
          {error && <p className="error-text">{error}</p>}
          <button className="btn btn-primary" type="submit" disabled={saving}>
            {saving ? '제출 중...' : submission ? '다시 제출하기' : '제출하기'}
          </button>
          {submission && (
            <span className="muted" style={{ fontSize: 13, marginLeft: 10 }}>
              마지막 제출: {new Date(submission.submittedAt).toLocaleString('ko-KR')}
            </span>
          )}
        </form>
      </details>

      {/* 성공 메시지는 details "바깥"에 둔다 — 첫 제출 시 폼이 접혀도(open={!submission})
          메시지는 계속 보여야 하니까. 접히는 영역 안에 두면 성공하자마자 같이 숨어 버린다. */}
      {savedMessage && (
        <p style={{ color: 'var(--teal)', fontSize: 14, marginTop: 10, marginBottom: 0 }}>
          ✅ {savedMessage}
        </p>
      )}
    </div>
  );
}

export default function AssignmentsPage() {
  const [week, setWeek] = useState(1);
  const [assignments, setAssignments] = useState([]);
  const [mySubmissions, setMySubmissions] = useState([]);
  const [loading, setLoading] = useState(true);

  // 내 제출 목록만 다시 불러오는 함수 — 제출 직후에도 호출한다.
  function loadMySubmissions() {
    return client.get('/submissions/me').then((res) => setMySubmissions(res.data));
  }

  useEffect(() => {
    let cancelled = false;
    setLoading(true);
    Promise.all([
      client.get('/assignments', { params: { week } }),
      client.get('/submissions/me'),
    ])
      .then(([assignmentsRes, submissionsRes]) => {
        if (cancelled) return;
        setAssignments(assignmentsRes.data);
        setMySubmissions(submissionsRes.data);
      })
      .finally(() => {
        if (!cancelled) setLoading(false);
      });
    return () => {
      cancelled = true;
    };
  }, [week]);

  // 학습 포인트: 과제 목록과 내 제출 목록은 별도 API다.
  // assignmentId로 짝을 맞춰(매칭) 과제 카드에 제출 상태를 얹는다.
  function findSubmission(assignmentId) {
    return mySubmissions.find((s) => s.assignmentId === assignmentId) || null;
  }

  // 이번 주 제출 현황 요약 (히어로에 표시)
  const submittedCount = assignments.filter((a) => findSubmission(a.id)).length;
  const percent =
    assignments.length === 0 ? 0 : Math.round((submittedCount / assignments.length) * 100);

  // 요일(일차)별로 묶는다 — 대시보드와 같은 방식이라 화면 리듬이 익숙해진다.
  const groups = new Map();
  for (const assignment of assignments) {
    const key = `${assignment.day}일차`;
    if (!groups.has(key)) groups.set(key, []);
    groups.get(key).push(assignment);
  }

  return (
    <div>
      <div className="hero compact">
        <div className="eyebrow">Assignments</div>
        <h1>{week}주차 과제</h1>
        <p>
          매일 16:30까지 제출해요. 본 과제가 일찍 끝나면 예비 과제로 —
          예비 과제도 평가에 반영됩니다.
        </p>
        <div className="chip-row" style={{ alignItems: 'center' }}>
          <div className="stat">
            <span className="stat-num">{percent}%</span>
            <span className="stat-label">
              {submittedCount} / {assignments.length} 제출
            </span>
          </div>
          <div className="progress-track" style={{ flex: 1, minWidth: 160 }}>
            <div className="progress-fill" style={{ width: `${percent}%` }} />
          </div>
        </div>
      </div>

      <div className="tabs">
        {WEEKS.map((w) => (
          <button
            key={w}
            className={`tab${w === week ? ' active' : ''}`}
            onClick={() => setWeek(w)}
          >
            {w}주차
          </button>
        ))}
      </div>

      {loading ? (
        <p className="empty">불러오는 중...</p>
      ) : assignments.length === 0 ? (
        <div className="card">
          <p className="empty">
            이 주차에는 등록된 과제가 없어요.
            <br />
            <span style={{ fontSize: 13 }}>5주차부터는 실전 티켓이 과제를 대신해요.</span>
          </p>
        </div>
      ) : (
        [...groups.entries()].map(([groupName, groupAssignments]) => {
          const groupSubmitted = groupAssignments.filter((a) => findSubmission(a.id)).length;
          return (
            <div key={groupName}>
              <div className="day-head">
                <span className="day-badge">{groupName}</span>
                <span className="day-count">
                  {groupSubmitted} / {groupAssignments.length} 제출
                </span>
              </div>
              {groupAssignments.map((assignment) => (
                <AssignmentCard
                  // 학습 포인트: key는 과제 id만 — 안정된 값이어야 한다.
                  // ⚠️ 원래 key에 제출 id까지 넣었었다("id-none" → "id-123"). 그런데 key가
                  // 바뀌면 React는 "다른 카드"로 보고 통째로 새로 만들기 때문에(리마운트),
                  // 첫 제출 직후 '제출 완료!' 메시지와 입력 상태가 몽땅 초기화되어
                  // 사용자는 성공 안내를 보지 못했다. (과제·제출 데이터는 Promise.all로
                  // 함께 도착하므로 제출 id를 key에 넣을 이유도 애초에 없었다.)
                  key={assignment.id}
                  assignment={assignment}
                  submission={findSubmission(assignment.id)}
                  onSubmitted={loadMySubmissions}
                />
              ))}
            </div>
          );
        })
      )}
    </div>
  );
}
