// 이 파일이 하는 일: 회원가입 폼. 로그인 정보 + 인적사항(개인정보)을 입력받아
// POST /api/auth/signup으로 보내고, 성공하면 로그인 페이지로 안내한다.
// 로그인 전에도 접근할 수 있는 페이지라서 Layout(상단 메뉴) 바깥에 렌더링된다.
import { useState } from 'react';
import { useNavigate, Link, Navigate } from 'react-router-dom';
import { useAuth } from '../AuthContext';
import client from '../api/client';

const TRACKS = [
  { value: 'DEV', label: '개발' },
  { value: 'DESIGN', label: '디자인' },
];

const COMPANY_DOMAIN = 'awesomedev.dev'; // 회사 이메일 도메인은 고정 (백엔드 StudentProfile과 일치)

// 폼 초기값. 필드가 많아지면 useState를 하나씩 두는 대신 객체 하나로 묶는 편이 관리하기 쉽다.
// 학습 포인트: 입력이 3~4개면 useState 여러 개가 낫고, 10개가 넘으면 객체 하나가 낫다.
// "규칙"이 아니라 "그때그때 읽기 쉬운 쪽"을 고른다.
const EMPTY = {
  username: '', password: '', passwordConfirm: '', name: '', track: 'DEV',
  companyEmailLocal: '', birthDate: '', phone: '', address: '', school: '', major: '',
  emergencyName: '', emergencyRelation: '', emergencyPhone: '',
  privacyConsent: false, // 개인정보 수집·이용 동의 — 체크해야만 가입 가능
};

/**
 * 입력 한 줄 부품 (라벨 + input).
 *
 * ⚠️ 학습 포인트 — 실제로 났던 버그가 담긴 자리다.
 * 처음엔 이 컴포넌트를 SignupPage "안에" 정의했다. 그랬더니 모바일에서
 * 글자를 한 자 칠 때마다 키보드가 닫히는 버그가 났다. 왜?
 *   글자 입력 → setForm → SignupPage 재렌더 → 함수 안의 Field가 "새로 정의"됨
 *   → React는 이전 Field와 다른 컴포넌트로 판단 → input을 버리고 새로 만듦(리마운트)
 *   → 그 순간 포커스가 풀림 → 모바일 키보드가 닫힘.
 * 컴포넌트를 밖으로 빼면 Field의 정체(타입)가 항상 같아서 input이 유지된다.
 * 규칙: "컴포넌트 안에서 컴포넌트를 정의하지 말 것" — React의 대표 함정이다.
 * (밖으로 나오면서 form/set에 직접 접근할 수 없으니 value와 onChange를 props로 받는다.)
 */
function Field({ label, k, type = 'text', placeholder, autoComplete, value, onChange }) {
  return (
    <div className="field">
      <label htmlFor={`su-${k}`}>{label}</label>
      <input
        id={`su-${k}`}
        className="input"
        type={type}
        value={value}
        onChange={(e) => onChange(k, e.target.value)}
        placeholder={placeholder}
        autoComplete={autoComplete}
      />
    </div>
  );
}

export default function SignupPage() {
  const { user } = useAuth();
  const navigate = useNavigate();

  const [form, setForm] = useState(EMPTY);
  const [error, setError] = useState('');
  const [submitting, setSubmitting] = useState(false);
  const [done, setDone] = useState(false);

  if (user) {
    return <Navigate to="/" replace />;
  }

  // 입력 하나가 바뀌면 그 필드만 갈아끼운다. (...이전값 펼치고, 바뀐 것 하나 덮어쓰기)
  function set(key, value) {
    setForm((prev) => ({ ...prev, [key]: value }));
  }

  // 학습 포인트: 프론트 검증은 편의(즉시 안내), 진짜 검증은 서버(우회 불가). 둘 다 있어야 한다.
  // ⚠️ 그리고 둘의 "규칙이 같아야" 한다 — 프론트가 느슨하면 사용자는 폼을 다 채운 뒤에야
  // 서버 400을 만난다. 아래 아이디·생년월일 규칙은 서버 SignupRequest의 검증과 일부러 똑같다.
  function validate() {
    if (!/^[a-zA-Z0-9]{4,}$/.test(form.username.trim()))
      return '아이디는 영문·숫자만으로 4자 이상이어야 해요.';
    if (form.password.length < 8) return '비밀번호는 8자 이상이어야 해요.';
    if (form.password !== form.passwordConfirm) return '비밀번호 확인이 일치하지 않아요.';
    if (!form.name.trim()) return '이름을 입력해 주세요.';
    if (!/^[a-z0-9._-]{2,40}$/.test(form.companyEmailLocal))
      return '회사 이메일 아이디는 소문자·숫자·. _ - 만 쓸 수 있어요.';
    if (!form.birthDate) return '생년월일을 입력해 주세요.';
    // 서버의 @Past와 동일 규칙 — 오늘·미래 날짜는 생년월일이 될 수 없다.
    // (문자열 "YYYY-MM-DD"끼리는 사전순 비교가 곧 날짜 비교라 이렇게 써도 안전하다.)
    if (form.birthDate >= new Date().toISOString().slice(0, 10))
      return '생년월일을 다시 확인해 주세요 — 오늘 이전 날짜여야 해요.';
    if (!/^01[0-9]-?[0-9]{3,4}-?[0-9]{4}$/.test(form.phone)) return '연락처 형식을 확인해 주세요.';
    if (!form.address.trim()) return '주소를 입력해 주세요.';
    if (!form.school.trim()) return '학교를 입력해 주세요.';
    if (!form.major.trim()) return '전공을 입력해 주세요.';
    if (!form.emergencyName.trim()) return '비상 연락처 이름을 입력해 주세요.';
    if (!form.emergencyRelation.trim()) return '비상 연락처 관계를 입력해 주세요.';
    if (!/^01[0-9]-?[0-9]{3,4}-?[0-9]{4}$/.test(form.emergencyPhone))
      return '비상 연락처 전화번호 형식을 확인해 주세요.';
    if (!form.privacyConsent) return '개인정보 수집·이용에 동의해야 가입할 수 있어요.';
    return '';
  }

  async function handleSubmit(e) {
    e.preventDefault();
    setError('');
    const message = validate();
    if (message) {
      setError(message);
      return;
    }
    setSubmitting(true);
    try {
      await client.post('/auth/signup', {
        username: form.username.trim(),
        password: form.password,
        name: form.name.trim(),
        track: form.track,
        companyEmailLocal: form.companyEmailLocal.trim(),
        birthDate: form.birthDate, // "2007-03-15" — 백엔드가 LocalDate로 변환
        phone: form.phone.trim(),
        address: form.address.trim(),
        school: form.school.trim(),
        major: form.major.trim(),
        emergencyName: form.emergencyName.trim(),
        emergencyRelation: form.emergencyRelation.trim(),
        emergencyPhone: form.emergencyPhone.trim(),
        privacyConsent: form.privacyConsent, // 서버도 @AssertTrue로 다시 확인한다
      });
      setDone(true);
    } catch (err) {
      if (err.response?.status === 409) {
        setError(err.response.data?.message || '이미 사용 중인 정보가 있어요.');
      } else if (err.response?.status === 400) {
        setError(err.response.data?.message || '입력 내용을 다시 확인해 주세요.');
      } else {
        setError('가입 중 문제가 생겼어요. 잠시 후 다시 시도해 주세요.');
      }
    } finally {
      setSubmitting(false);
    }
  }

  // 입력 부품(Field)은 파일 상단, 컴포넌트 밖에 정의되어 있다 — 이유는 그쪽 주석 참고.

  return (
    <div style={{ minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 20 }}>
      <div className="card" style={{ width: '100%', maxWidth: 460 }}>
        <div style={{ textAlign: 'center', marginBottom: 20 }}>
          <div className="topnav-logo" style={{ fontSize: 18 }}>
            AWESOMEDEV <span>수습 플랫폼</span>
          </div>
          <p className="muted" style={{ fontSize: 14, marginTop: 6 }}>수습생 회원가입</p>
        </div>

        {done ? (
          <div style={{ textAlign: 'center' }}>
            <p style={{ fontWeight: 700, marginBottom: 6 }}>가입 완료! 🎉</p>
            <p className="muted" style={{ fontSize: 14, marginBottom: 16 }}>
              이제 만든 계정으로 로그인해 주세요.
            </p>
            <button className="btn btn-primary" onClick={() => navigate('/login')}
              style={{ width: '100%', justifyContent: 'center' }}>
              로그인하러 가기
            </button>
          </div>
        ) : (
          <form onSubmit={handleSubmit}>
            <div className="section-title" style={{ marginTop: 0 }}>계정</div>
            <Field label="아이디 (영문·숫자 4자 이상)" k="username" autoComplete="username" value={form.username} onChange={set} />
            <Field label="비밀번호 (8자 이상)" k="password" type="password" autoComplete="new-password" value={form.password} onChange={set} />
            <Field label="비밀번호 확인" k="passwordConfirm" type="password" autoComplete="new-password" value={form.passwordConfirm} onChange={set} />

            <div className="field">
              <label>트랙</label>
              <div className="tabs" style={{ marginBottom: 0 }}>
                {TRACKS.map((t) => (
                  <button key={t.value} type="button"
                    className={`tab${form.track === t.value ? ' active' : ''}`}
                    onClick={() => set('track', t.value)}>
                    {t.label}
                  </button>
                ))}
              </div>
            </div>

            <div className="section-title">인적사항</div>
            <Field label="이름" k="name" autoComplete="name" value={form.name} onChange={set} />

            {/* 회사 이메일 — 아이디만 입력하고 도메인은 고정으로 붙여 보여준다 */}
            <div className="field">
              <label htmlFor="su-companyEmailLocal">회사 이메일</label>
              <div style={{ display: 'flex', alignItems: 'stretch', gap: 6 }}>
                <input
                  id="su-companyEmailLocal"
                  className="input"
                  value={form.companyEmailLocal}
                  onChange={(e) => set('companyEmailLocal', e.target.value.toLowerCase())}
                  placeholder="gildong.hong"
                  style={{ flex: 1 }}
                />
                <span className="badge badge-primary" style={{ display: 'flex', alignItems: 'center', fontSize: 14 }}>
                  @{COMPANY_DOMAIN}
                </span>
              </div>
              {/* 권장 규칙 안내 — 회사 이메일은 고객사와의 대외 소통에도 쓰이므로 영문 이름으로 */}
              <p className="muted" style={{ fontSize: 12.5, marginTop: 4 }}>
                영문 이름으로 만들어 주세요 — <strong>이름.성</strong> 형식 권장
                (예: 홍길동 → gildong.hong)
              </p>
              {form.companyEmailLocal && (
                <p className="muted" style={{ fontSize: 12.5, marginTop: 4 }}>
                  → {form.companyEmailLocal}@{COMPANY_DOMAIN}
                </p>
              )}
            </div>

            <Field label="생년월일" k="birthDate" type="date" value={form.birthDate} onChange={set} />
            <Field label="연락처" k="phone" placeholder="010-1234-5678" autoComplete="tel" value={form.phone} onChange={set} />
            <Field label="주소" k="address" placeholder="시/군/구 이하" value={form.address} onChange={set} />
            <Field label="학교" k="school" placeholder="미림마이스터고등학교" value={form.school} onChange={set} />
            <Field label="전공(학과)" k="major" value={form.major} onChange={set} />

            <div className="section-title">비상 연락처</div>
            <Field label="이름" k="emergencyName" value={form.emergencyName} onChange={set} />
            <Field label="관계 (예: 부, 모)" k="emergencyRelation" value={form.emergencyRelation} onChange={set} />
            <Field label="전화번호" k="emergencyPhone" placeholder="010-1234-5678" value={form.emergencyPhone} onChange={set} />

            {/* ── 개인정보 수집·이용 동의 ──
                학습 포인트: 동의를 받으려면 "무엇을, 왜, 얼마나" 수집하는지 먼저 알려야 한다
                (고지 후 동의). 안내문 없이 체크박스만 두면 법적으로 유효한 동의가 아니다. */}
            <div className="section-title">개인정보 수집·이용 동의</div>
            <div className="tip" style={{ marginTop: 0, fontSize: 13, lineHeight: 1.7 }}>
              <strong>수집 항목</strong> — 이름, 생년월일, 연락처, 주소, 학교·전공, 비상 연락처<br />
              <strong>수집 목적</strong> — 수습 기간 인사 관리, 급여·4대보험 등 행정 처리, 비상시 연락<br />
              <strong>보유 기간</strong> — 재직 기간 동안 보관하고, 퇴직 시 관계 법령이 정한 기간이
              지나면 지체 없이 파기합니다.<br />
              <strong>동의 거부 안내</strong> — 동의하지 않을 권리가 있으나, 위 정보는 근로 관계에
              꼭 필요한 최소한의 정보라 동의하지 않으면 가입(채용 절차 진행)이 어렵습니다.<br />
              주민등록번호·계좌번호 같은 민감정보는 <strong>여기서 받지 않아요</strong> —
              근로계약서 작성 때 따로 받습니다.
            </div>
            {/* alignItems: flex-start — 모바일에서 라벨이 두 줄로 꺾여도 체크박스는 첫 줄에 붙는다 */}
            <label style={{ display: 'flex', alignItems: 'flex-start', gap: 8, marginTop: 10,
                            cursor: 'pointer', fontSize: 14, fontWeight: 600 }}>
              <input
                type="checkbox"
                checked={form.privacyConsent}
                onChange={(e) => set('privacyConsent', e.target.checked)}
                style={{ width: 16, height: 16, marginTop: 2, flexShrink: 0,
                         accentColor: 'var(--primary, #4f46e5)' }}
              />
              위 개인정보 수집·이용에 동의합니다. (필수)
            </label>

            {error && <p className="error-text" style={{ marginTop: 10 }}>{error}</p>}
            <button className="btn btn-primary" type="submit" disabled={submitting}
              style={{ width: '100%', justifyContent: 'center', marginTop: 12 }}>
              {submitting ? '가입 중...' : '가입하기'}
            </button>
          </form>
        )}

        <p className="muted" style={{ textAlign: 'center', fontSize: 14, marginTop: 16 }}>
          이미 계정이 있나요? <Link to="/login">로그인</Link>
        </p>
      </div>
    </div>
  );
}
