// 인증 게이트 — 미인증 사용자에게 로그인/회원가입 화면을 표시합니다.
// window.AuthGate, window.useAuth 로 노출됩니다.

const {
  useState: useAuthState,
  useEffect: useAuthEffect,
  useCallback: useAuthCallback,
  useRef: useAuthRef,
  createContext: createAuthContext,
  useContext: useAuthContext,
} = React;

// ── 인증 컨텍스트 ────────────────────────────────────────────────
const AuthContext = createAuthContext(null);

function useAuth() {
  return useAuthContext(AuthContext);
}

// GIS 콜백을 전역 ref로 관리 (initialize 이후 handler가 교체될 수 있으므로)
let _gisCallbackRef = null;

// ── Eye 아이콘 ────────────────────────────────────────────────────
function EyeOpen() {
  return (
    <svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor"
      strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
      <path d="M1 8s2.5-5 7-5 7 5 7 5-2.5 5-7 5-7-5-7-5z"/>
      <circle cx="8" cy="8" r="2"/>
    </svg>
  );
}

function EyeClosed() {
  return (
    <svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor"
      strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
      <path d="M2 2l12 12"/>
      <path d="M6.7 6.8A2 2 0 0 0 9.2 9.3"/>
      <path d="M3.4 4.5C2.1 5.5 1 8 1 8s2.5 5 7 5c1.3 0 2.5-.4 3.5-1"/>
      <path d="M9.9 3.2C12.1 4.2 15 8 15 8s-.8 1.6-2 2.8"/>
    </svg>
  );
}

// ── 입력 필드 ────────────────────────────────────────────────────
function AuthInput({ label, type = 'text', value, onChange, placeholder, autoFocus, hint }) {
  const [showPw, setShowPw] = useAuthState(false);
  const isPassword = type === 'password';
  const inputType  = isPassword ? (showPw ? 'text' : 'password') : type;

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
      <label style={{ fontSize: 12, color: 'var(--ink-3)', fontWeight: 500, letterSpacing: '0.03em' }}>
        {label}
      </label>
      <div style={{ position: 'relative' }}>
        <input
          type={inputType}
          value={value}
          onChange={e => onChange(e.target.value)}
          placeholder={placeholder}
          autoFocus={autoFocus}
          style={{
            background: 'var(--bg-3)',
            border: '1px solid var(--line-2)',
            borderRadius: 8,
            padding: isPassword ? '10px 40px 10px 13px' : '10px 13px',
            color: 'var(--ink)',
            fontSize: 14,
            outline: 'none',
            width: '100%',
            boxSizing: 'border-box',
            transition: 'border-color 0.15s',
            fontFamily: 'inherit',
          }}
          onFocus={e => e.target.style.borderColor = 'var(--accent)'}
          onBlur={e => e.target.style.borderColor = 'var(--line-2)'}
        />
        {isPassword && (
          <button
            type="button"
            onClick={() => setShowPw(v => !v)}
            title={showPw ? '비밀번호 숨기기' : '비밀번호 보기'}
            style={{
              position: 'absolute', right: 10, top: '50%', transform: 'translateY(-50%)',
              background: 'none', border: 'none', padding: 4, cursor: 'pointer',
              color: showPw ? 'var(--accent)' : 'var(--ink-4)',
              display: 'flex', alignItems: 'center', transition: 'color 0.15s',
            }}
            onMouseEnter={e => e.currentTarget.style.color = 'var(--ink-2)'}
            onMouseLeave={e => e.currentTarget.style.color = showPw ? 'var(--accent)' : 'var(--ink-4)'}
          >
            {showPw ? <EyeClosed/> : <EyeOpen/>}
          </button>
        )}
      </div>
      {hint && <p style={{ fontSize: 11, color: 'var(--ink-4)', margin: 0 }}>{hint}</p>}
    </div>
  );
}

// ── 구분선 ────────────────────────────────────────────────────────
function Divider() {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
      <div style={{ flex: 1, height: 1, background: 'var(--line-2)' }}/>
      <span style={{ fontSize: 11, color: 'var(--ink-4)' }}>또는</span>
      <div style={{ flex: 1, height: 1, background: 'var(--line-2)' }}/>
    </div>
  );
}

// ── Google 버튼 ───────────────────────────────────────────────────
function GoogleButton({ gisReady }) {
  const ref = useAuthRef(null);

  useAuthEffect(() => {
    if (!gisReady || !ref.current || !window.google?.accounts?.id) return;
    window.google.accounts.id.renderButton(ref.current, {
      theme: 'filled_black',
      size: 'large',
      text: 'signin_with',
      shape: 'rectangular',
      width: 344,
    });
  }, [gisReady]);

  if (!gisReady) return (
    <div style={{
      height: 44, borderRadius: 6,
      background: 'var(--bg-3)', border: '1px solid var(--line-2)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      fontSize: 13, color: 'var(--ink-4)',
    }}>
      Google 로그인 준비 중…
    </div>
  );

  return <div ref={ref} style={{ display: 'flex', justifyContent: 'center' }}/>;
}

// ── 에러 박스 ─────────────────────────────────────────────────────
function ErrorBox({ message }) {
  if (!message) return null;
  return (
    <p style={{
      margin: 0, fontSize: 13, color: '#ff6b81',
      background: 'rgba(255,107,129,0.08)',
      border: '1px solid rgba(255,107,129,0.25)',
      borderRadius: 7, padding: '8px 12px',
    }}>
      {message}
    </p>
  );
}

// ── 회원가입 폼 ──────────────────────────────────────────────────
function RegisterForm({ onSuccess, onSwitch, gisReady, googleError }) {
  const [email, setEmail]       = useAuthState('');
  const [nickname, setNickname] = useAuthState('');
  const [password, setPassword] = useAuthState('');
  const [confirm, setConfirm]   = useAuthState('');
  const [error, setError]       = useAuthState('');
  const [loading, setLoading]   = useAuthState(false);

  async function handleSubmit(e) {
    e.preventDefault();
    setError('');
    if (!email.trim()) return setError('이메일을 입력해 주세요.');
    if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) return setError('이메일 형식이 올바르지 않습니다.');
    if (!nickname.trim() || nickname.trim().length < 2) return setError('닉네임은 2자 이상이어야 합니다.');
    if (nickname.trim().length > 30) return setError('닉네임은 30자 이하여야 합니다.');
    if (password.length < 10) return setError('비밀번호는 10자 이상이어야 합니다.');
    if (password !== confirm) return setError('비밀번호가 일치하지 않습니다.');

    setLoading(true);
    try {
      await window.SongfilmAuth.register(email.trim(), nickname.trim(), password);
      await window.SongfilmAuth.login(email.trim(), password);
      onSuccess(window.SongfilmAuth.getSession());
    } catch (err) {
      setError(err.message || '회원가입 중 오류가 발생했습니다.');
    } finally {
      setLoading(false);
    }
  }

  return (
    <form onSubmit={handleSubmit} style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
      <GoogleButton gisReady={gisReady}/>
      <ErrorBox message={googleError}/>
      <Divider/>
      <AuthInput label="이메일" type="email" value={email} onChange={setEmail}
        placeholder="you@example.com" autoFocus/>
      <AuthInput label="닉네임" value={nickname} onChange={setNickname} placeholder="2~30자"/>
      <AuthInput label="비밀번호" type="password" value={password} onChange={setPassword}
        placeholder="10자 이상" hint="길이 외 제한 없음 — 특수문자, 공백 모두 허용"/>
      <AuthInput label="비밀번호 확인" type="password" value={confirm} onChange={setConfirm}
        placeholder="비밀번호를 다시 입력"/>
      <ErrorBox message={error}/>
      <button type="submit" className="pill-btn primary" disabled={loading}
        style={{ justifyContent: 'center', marginTop: 4, padding: '10px 0', fontSize: 14, fontWeight: 600 }}>
        {loading ? '가입 중…' : '이메일로 회원가입'}
      </button>
      <p style={{ margin: 0, textAlign: 'center', fontSize: 13, color: 'var(--ink-3)' }}>
        이미 계정이 있나요?{' '}
        <button type="button" onClick={onSwitch}
          style={{ background: 'none', border: 'none', color: 'var(--accent)', cursor: 'pointer', fontSize: 13, padding: 0, fontFamily: 'inherit' }}>
          로그인
        </button>
      </p>
    </form>
  );
}

// ── 로그인 폼 ────────────────────────────────────────────────────
function LoginForm({ onSuccess, onSwitch, gisReady, googleError }) {
  const [email, setEmail]       = useAuthState('');
  const [password, setPassword] = useAuthState('');
  const [error, setError]       = useAuthState('');
  const [loading, setLoading]   = useAuthState(false);

  async function handleSubmit(e) {
    e.preventDefault();
    setError('');
    if (!email.trim()) return setError('이메일을 입력해 주세요.');
    if (!password) return setError('비밀번호를 입력해 주세요.');

    setLoading(true);
    try {
      await window.SongfilmAuth.login(email.trim(), password);
      onSuccess(window.SongfilmAuth.getSession());
    } catch (err) {
      setError(err.message || '로그인 중 오류가 발생했습니다.');
    } finally {
      setLoading(false);
    }
  }

  return (
    <form onSubmit={handleSubmit} style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
      <GoogleButton gisReady={gisReady}/>
      <ErrorBox message={googleError}/>
      <Divider/>
      <AuthInput label="이메일" type="email" value={email} onChange={setEmail}
        placeholder="you@example.com" autoFocus/>
      <AuthInput label="비밀번호" type="password" value={password} onChange={setPassword}
        placeholder="비밀번호 입력"/>
      <ErrorBox message={error}/>
      <button type="submit" className="pill-btn primary" disabled={loading}
        style={{ justifyContent: 'center', marginTop: 4, padding: '10px 0', fontSize: 14, fontWeight: 600 }}>
        {loading ? '로그인 중…' : '이메일로 로그인'}
      </button>
      <p style={{ margin: 0, textAlign: 'center', fontSize: 13, color: 'var(--ink-3)' }}>
        아직 계정이 없나요?{' '}
        <button type="button" onClick={onSwitch}
          style={{ background: 'none', border: 'none', color: 'var(--accent)', cursor: 'pointer', fontSize: 13, padding: 0, fontFamily: 'inherit' }}>
          회원가입
        </button>
      </p>
    </form>
  );
}

// ── 인증 모달 ────────────────────────────────────────────────────
function AuthModal({ onAuthenticated, googleClientId }) {
  const [mode, setMode]           = useAuthState('login');
  const [gisReady, setGisReady]   = useAuthState(false);
  const [googleError, setGoogleError] = useAuthState('');

  // GIS 초기화
  useAuthEffect(() => {
    if (!googleClientId) return;

    async function handleCredential(response) {
      setGoogleError('');
      try {
        await window.SongfilmAuth.googleLogin(response.credential);
        onAuthenticated(window.SongfilmAuth.getSession());
      } catch (err) {
        setGoogleError(err.message || 'Google 로그인에 실패했습니다.');
      }
    }

    // _gisCallbackRef를 통해 최신 handler를 항상 호출
    _gisCallbackRef = handleCredential;

    const init = () => {
      window.google.accounts.id.initialize({
        client_id: googleClientId,
        callback: (resp) => _gisCallbackRef?.(resp),
      });
      setGisReady(true);
    };

    if (window.google?.accounts?.id) {
      init();
    } else {
      window.onGoogleLibraryLoad = init;
    }
  }, [googleClientId]);

  return (
    <div style={{
      position: 'fixed', inset: 0, zIndex: 9999,
      background: 'rgba(11,11,15,0.92)',
      backdropFilter: 'blur(6px)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      padding: 16,
    }}>
      <div style={{
        background: 'var(--bg-2)',
        border: '1px solid var(--line-2)',
        borderRadius: 16,
        padding: '32px 28px',
        width: '100%',
        maxWidth: 400,
        boxShadow: '0 24px 64px rgba(0,0,0,0.6)',
      }}>
        <div style={{ marginBottom: 28, textAlign: 'center' }}>
          <div style={{ fontSize: 22, fontWeight: 700, color: 'var(--ink)', fontFamily: 'Fraunces, serif', letterSpacing: '-0.02em' }}>
            Songfilm
          </div>
          <div style={{ fontSize: 13, color: 'var(--ink-3)', marginTop: 6 }}>
            {mode === 'register' ? '새 계정 만들기' : '계정에 로그인'}
          </div>
        </div>

        {mode === 'login'
          ? <LoginForm    onSuccess={onAuthenticated} onSwitch={() => setMode('register')} gisReady={gisReady} googleError={googleError}/>
          : <RegisterForm onSuccess={onAuthenticated} onSwitch={() => setMode('login')}    gisReady={gisReady} googleError={googleError}/>
        }
      </div>
    </div>
  );
}

// ── AuthGate — 앱 최상위 래퍼 ───────────────────────────────────
function AuthGate({ children }) {
  const [authState, setAuthState]       = useAuthState('loading');
  const [session, setSession]           = useAuthState(null);
  const [googleClientId, setGoogleClientId] = useAuthState('');

  useAuthEffect(() => {
    // Google Client ID 로드
    window.SongfilmAuth.fetchConfig()
      .then(cfg => { if (cfg.googleClientId) setGoogleClientId(cfg.googleClientId); })
      .catch(() => {});

    // 로컬 세션 확인
    const local = window.SongfilmAuth.getSession();
    if (local) {
      setSession(local);
      setAuthState('authenticated');
      window.SongfilmAuth.verify().then(verified => {
        if (verified) setSession(s => ({ ...s, expiresAt: verified.expiresAt }));
        else { setSession(null); setAuthState('unauthenticated'); }
      });
    } else {
      setAuthState('unauthenticated');
    }
  }, []);

  // 10분마다 sliding expiry 갱신
  useAuthEffect(() => {
    if (authState !== 'authenticated') return;
    const id = setInterval(async () => {
      const verified = await window.SongfilmAuth.verify();
      if (!verified) { setSession(null); setAuthState('unauthenticated'); }
      else setSession(s => ({ ...s, expiresAt: verified.expiresAt }));
    }, 10 * 60 * 1000);
    return () => clearInterval(id);
  }, [authState]);

  const handleAuthenticated = useAuthCallback((s) => {
    setSession(s);
    setAuthState('authenticated');
  }, []);

  const handleLogout = useAuthCallback(async () => {
    await window.SongfilmAuth.logout();
    setSession(null);
    setAuthState('unauthenticated');
  }, []);

  if (authState === 'loading') {
    return (
      <div style={{ position: 'fixed', inset: 0, background: 'var(--bg)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        <div style={{ color: 'var(--ink-3)', fontSize: 14 }}>로딩 중…</div>
      </div>
    );
  }

  if (authState === 'unauthenticated') {
    return <AuthModal onAuthenticated={handleAuthenticated} googleClientId={googleClientId}/>;
  }

  return (
    <AuthContext.Provider value={{ session, logout: handleLogout }}>
      {children}
    </AuthContext.Provider>
  );
}

window.AuthGate = AuthGate;
window.useAuth  = useAuth;
