// [REQ F1]  System uwierzytelniania – formularz logowania + ekran weryfikacji 2FA
// [REQ D2]  Zaawansowane formularze – Formik + Zod (toFormikValidationSchema)
// [REQ T8]  Obsługa formularzy i walidacja – walidacja e-mail i hasła, błędy inline
import { useEffect, useState } from 'react';
import { useNavigate, useLocation, Link } from 'react-router-dom';
import { ShieldCheck, Loader2 } from 'lucide-react';
import { useFormik } from 'formik';
import { z } from 'zod';
import { toFormikValidationSchema } from 'zod-formik-adapter';
import { useAuth } from '../context/AuthContext';
import styles from './LoginPage.module.scss';
// kkonfiguracaj schematu walidacji formularza logowania dla Zod
const schema = z.object({
  email: z.string().email('Enter a valid email address.'),
  password: z.string().min(6, 'Password must be at least 6 characters.'),
});
// komponent LoginPage to strona logowania, która obsługuje zarówno formularz logowania jak i ekran weryfikacji 2FA
const LoginPage = () => {
  // wyciągnięcie funkcji i stanów z useAuth - login do logowania, 
  // user do sprawdzania czy użytkownik jest zalogowany, error do wyświetlania błędów logowania, 
  // clearError do czyszczenia błędów, pendingUser do sprawdzania czy jesteśmy w trakcie weryfikacji 
  // 2FA, twoFACode do przechowywania kodu 2FA, verify2FA do weryfikacji kodu 2FA, cancel2FA do anulowania procesu 2FA
  const { login, user, error, clearError, pendingUser, twoFACode, verify2FA, cancel2FA } = useAuth();
  // useState do przechowywania stanu inputa 2FA oraz błędu 2FA, które są używane tylko w ekranie weryfikacji 2FA
  const [twoFAInput, setTwoFAInput] = useState('');
  const [twoFAError, setTwoFAError] = useState('');
  // useNavigate i useLocation do nawigacji i sprawdzania aktualnej lokalizacji w aplikacji React Router
  const navigate = useNavigate();
  // useLocation zwraca obiekt reprezentujący aktualną lokalizację, który zawiera informacje o ścieżce, stanie i innych parametrach URL.
  const location = useLocation();
  // useEffect do przekierowywania zalogowanego użytkownika na odpowiednią stronę po zalogowaniu, wywoływany przy zmianie stanu user
  useEffect(() => {
    if (user) navigate(user.role === 'admin' ? '/admin' : '/dashboard', { replace: true });
  }, [user, navigate]);
  // konfiguracja hooka useFormik do obsługi formularza logowania, który przyjmuje initialValues, validationSchema i onSubmit
  const formik = useFormik({
    initialValues: { email: '', password: '' },
    validationSchema: toFormikValidationSchema(schema),
    onSubmit: async ({ email, password }) => {
      clearError();
      try {
        await login(email, password);
        // login returns { twoFAPending: true } — LoginPage will show 2FA step
      } catch {
        // error state is managed by AuthContext
      }
    },
  });
  // funkcja do obsługi weryfikacji 2FA, która jest wywoływana po submitowaniu formularza weryfikacji 2FA
  const handle2FA = (e) => {
    //e.preventDefault() zapobiega domyślnej akcji submitowania formularza, która powodowałaby przeładowanie strony, dzięki temu możemy obsłużyć weryfikację 2FA bez przeładowania strony
    e.preventDefault();
    // wyczyszczenie błędu 2FA przed próbą weryfikacji
    setTwoFAError('');
    try {
      // loggedIn to wynik funkcji verify2FA, która sprawdza czy wprowadzony kod 2FA jest poprawny, jeśli jest poprawny zwraca obiekt zalogowanego użytkownika, jeśli nie jest poprawny rzuca błąd
      const loggedIn = verify2FA(twoFAInput.trim());
      // uzyskanie ścieżki, z której użytkownik został przekierowany na stronę logowania, jeśli istnieje, lub ustawienie domyślnej ścieżki w zależności od roli użytkownika (admin -> /admin, client -> /dashboard)
      const from = location.state?.from?.pathname;
      navigate(from || (loggedIn.role === 'admin' ? '/admin' : '/dashboard'), { replace: true });
    } catch (err) {
      setTwoFAError(err.message);
    }
  };

  // 2FA screen
  // pendingUser to stan z AuthContext, który jest ustawiany na obiekt użytkownika po poprawnym logowaniu hasła
  // , ale przed weryfikacją 2FA, jeśli pendingUser jest ustawiony to wyświetlamy ekran weryfikacji 2FA zamiast formularza logowania
  // jest to fake email
  if (pendingUser) {
    return (
      <div className={styles['login']}>
        <div className={styles['login__card']}>
          <div className={styles['login__header']}>
            <ShieldCheck size={36} className={styles['login__twofa-icon']} />
            <h1 className={styles['login__title']}>Two-Factor Auth</h1>
            <p className={styles['login__subtitle']}>
              A 6-digit code was sent to <strong>{pendingUser.email}</strong>
            </p>
          </div>

          {/* Fake email preview showing the code */}
          <div className={styles['login__code-preview']}>
            <div className={styles['login__code-bar']}>
              <span className={styles['login__code-dot']} />
              <span className={styles['login__code-dot']} />
              <span className={styles['login__code-dot']} />
              <span className={styles['login__code-bar-label']}>Security email</span>
            </div>
            <div className={styles['login__code-body']}>
              <p>Hello {pendingUser.name ?? pendingUser.email},</p>
              <p>Your verification code is:</p>
              <p className={styles['login__code-number']}>{twoFACode}</p>
              <p className={styles['login__code-note']}>This code expires in 5 minutes.</p>
            </div>
          </div>

          <form onSubmit={handle2FA} className={styles['login__form']}>
            {twoFAError && (
              <div className={styles['login__alert']} role="alert">
                <span>{twoFAError}</span>
              </div>
            )}
            <div className={styles['login__field']}>
              <label htmlFor="code" className={styles['login__label']}>Enter code</label>
              <input
                id="code"
                type="text"
                inputMode="numeric"
                maxLength={6}
                className={styles['login__input']}
                placeholder="000000"
                value={twoFAInput}
                onChange={(e) => setTwoFAInput(e.target.value)}
                autoFocus
              />
            </div>
            <button type="submit" className={styles['login__submit']}>
              Verify & Sign in
            </button>
            <button
              type="button"
              className={styles['login__register-link']}
              style={{ background: 'none', border: 'none', cursor: 'pointer', textAlign: 'center', width: '100%' }}
              onClick={() => { cancel2FA(); setTwoFAInput(''); setTwoFAError(''); }}
            >
              Back to login
            </button>
          </form>
        </div>
      </div>
    );
  }
  // renderujemy normalny ekran logowania jeśli nie jesteśmy w trakcie weryfikacji 2FA (pendingUser jest null)
  return (
    <div className={styles['login']}>
      <div className={styles['login__card']}>
        <div className={styles['login__header']}>
          <h1 className={styles['login__title']}>Reservation System</h1>
          <p className={styles['login__subtitle']}>Sign in to your account</p>
        </div>

        <form className={styles['login__form']} onSubmit={formik.handleSubmit} noValidate>
          {location.state?.registered && (
            <div className={styles['login__success']} role="status">
              Account verified! You can now sign in.
            </div>
          )}

          {error && (
            <div className={styles['login__alert']} role="alert">
              <span>{error}</span>
              <button
                type="button"
                className={styles['login__alert-close']}
                onClick={clearError}
              >
                x
              </button>
            </div>
          )}

          <div className={styles['login__field']}>
            <label htmlFor="email" className={styles['login__label']}>Email</label>
            <input
              id="email"
              type="email"
              className={[
                styles['login__input'],
                formik.touched.email && formik.errors.email ? styles['login__input--error'] : '',
              ].join(' ')}
              placeholder="you@example.com"
              autoComplete="email"
              {...formik.getFieldProps('email')}
            />
            {formik.touched.email && formik.errors.email && (
              <p className={styles['login__field-error']}>{formik.errors.email}</p>
            )}
          </div>

          <div className={styles['login__field']}>
            <label htmlFor="password" className={styles['login__label']}>Password</label>
            <input
              id="password"
              type="password"
              className={[
                styles['login__input'],
                formik.touched.password && formik.errors.password ? styles['login__input--error'] : '',
              ].join(' ')}
              placeholder="password"
              autoComplete="current-password"
              {...formik.getFieldProps('password')}
            />
            {formik.touched.password && formik.errors.password && (
              <p className={styles['login__field-error']}>{formik.errors.password}</p>
            )}
          </div>

          <button
            type="submit"
            className={styles['login__submit']}
            disabled={formik.isSubmitting}
          >
            {formik.isSubmitting ? 'Signing in...' : 'Sign in'}
          </button>
        </form>

        <p className={styles['login__register-link']}>
          Don't have an account?{' '}
          <Link to="/register" className={styles['login__link']}>Sign up</Link>
        </p>

        <div className={styles['login__hint']}>
          <p><strong>Admin:</strong> admin@reservations.dev / Admin1234!</p>
          <p><strong>Client:</strong> anna.kowalski@example.com / Client1234!</p>
        </div>
      </div>
    </div>
  );
};
// eksportowanie komponentu LoginPage jako domyślnego eksportu z tego pliku, dzięki czemu można go importować w innych częściach aplikacji
export default LoginPage;
