import { useCallback, useEffect, useRef, useState } from "react";
import { Link, Navigate, useLocation, useNavigate, useSearchParams } from "react-router-dom";
import {
  ApiError,
  forgotPassword,
  register,
  resendVerification,
  resetPassword,
  verifyEmail,
} from "../api";
import { useAuth } from "../app/auth/AuthContext";

function errorMessage(error: unknown, fallback: string): string {
  if (error instanceof ApiError) {
    return error.details.length > 0 ? error.details.join("; ") : error.message;
  }
  return fallback;
}

function TurnstileField(props: { onToken(token: string): void }): JSX.Element {
  const ref = useRef<HTMLDivElement | null>(null);
  const siteKey = import.meta.env.VITE_TURNSTILE_SITE_KEY;
  const { onToken } = props;

  useEffect(() => {
    if (!siteKey || !ref.current) {
      onToken("mock-turnstile-token");
      return;
    }

    const scriptId = "turnstile-script";
    if (!document.getElementById(scriptId)) {
      const script = document.createElement("script");
      script.id = scriptId;
      script.src = "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit";
      script.async = true;
      script.defer = true;
      document.head.appendChild(script);
    }

    let widgetId: string | null = null;
    const timer = window.setInterval(() => {
      if (window.turnstile && ref.current && !widgetId) {
        widgetId = window.turnstile.render(ref.current, {
          sitekey: siteKey,
          callback: onToken,
          "expired-callback": () => onToken(""),
        });
        window.clearInterval(timer);
      }
    }, 100);

    return () => {
      window.clearInterval(timer);
      if (widgetId && window.turnstile) {
        window.turnstile.remove(widgetId);
      }
    };
  }, [onToken, siteKey]);

  return <div className="auth-form__captcha" ref={ref} />;
}

export function LoginPage(): JSX.Element {
  const { user, login } = useAuth();
  const navigate = useNavigate();
  const location = useLocation();
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [error, setError] = useState<string | null>(null);
  const [isSubmitting, setIsSubmitting] = useState(false);

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

  const handleSubmit = async (event: React.FormEvent) => {
    event.preventDefault();
    setIsSubmitting(true);
    setError(null);
    try {
      await login(email, password);
      const from = (location.state as { from?: Location } | null)?.from?.pathname ?? "/";
      navigate(from, { replace: true });
    } catch (err) {
      setError(errorMessage(err, "Не удалось войти."));
    } finally {
      setIsSubmitting(false);
    }
  };

  return (
    <section className="page page--auth">
      <h1 className="page__title">Вход</h1>
      <form className="auth-form" onSubmit={handleSubmit}>
        <label className="auth-form__field">
          <span className="auth-form__label">Email</span>
          <input className="auth-form__input" type="email" value={email} onChange={(e) => setEmail(e.target.value)} required />
        </label>
        <label className="auth-form__field">
          <span className="auth-form__label">Пароль</span>
          <input className="auth-form__input" type="password" value={password} onChange={(e) => setPassword(e.target.value)} required />
        </label>
        {error ? <p className="page__subtitle page__subtitle--error">{error}</p> : null}
        <button className="btn btn--primary" type="submit" disabled={isSubmitting}>
          Войти
        </button>
      </form>
      <p className="auth-form__links">
        <Link className="page-link" to="/register">Регистрация</Link>
        <Link className="page-link" to="/forgot-password">Забыли пароль?</Link>
      </p>
    </section>
  );
}

export function RegisterPage(): JSX.Element {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [turnstileToken, setTurnstileToken] = useState("");
  const [message, setMessage] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);

  const handleToken = useCallback((token: string) => setTurnstileToken(token), []);

  const handleSubmit = async (event: React.FormEvent) => {
    event.preventDefault();
    setError(null);
    setMessage(null);
    try {
      await register({ email, password, turnstileToken });
      setMessage("Проверьте почту: мы отправили ссылку для подтверждения email.");
    } catch (err) {
      setError(errorMessage(err, "Не удалось зарегистрироваться."));
    }
  };

  return (
    <section className="page page--auth">
      <h1 className="page__title">Регистрация</h1>
      <form className="auth-form" onSubmit={handleSubmit}>
        <label className="auth-form__field">
          <span className="auth-form__label">Email</span>
          <input className="auth-form__input" type="email" value={email} onChange={(e) => setEmail(e.target.value)} required />
        </label>
        <label className="auth-form__field">
          <span className="auth-form__label">Пароль</span>
          <input className="auth-form__input" type="password" minLength={15} value={password} onChange={(e) => setPassword(e.target.value)} required />
        </label>
        <TurnstileField onToken={handleToken} />
        {message ? <p className="page__subtitle">{message}</p> : null}
        {error ? <p className="page__subtitle page__subtitle--error">{error}</p> : null}
        <button className="btn btn--primary" type="submit" disabled={!turnstileToken}>Создать аккаунт</button>
      </form>
      <p className="auth-form__links">
        <Link className="page-link" to="/login">Уже есть аккаунт</Link>
      </p>
    </section>
  );
}

export function VerifyEmailPage(): JSX.Element {
  const { user, refresh } = useAuth();
  const [params] = useSearchParams();
  const [email, setEmail] = useState(user?.email ?? "");
  const [message, setMessage] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    const token = params.get("token");
    if (!token) {
      return;
    }
    void verifyEmail(token)
      .then(async () => {
        await refresh();
        setMessage("Email подтверждён. Теперь можно пользоваться календарём.");
      })
      .catch((err) => setError(errorMessage(err, "Ссылка недействительна.")));
  }, [params, refresh]);

  const resend = async () => {
    setError(null);
    await resendVerification(email);
    setMessage("Если email зарегистрирован и ещё не подтверждён, письмо отправлено.");
  };

  return (
    <section className="page page--auth">
      <h1 className="page__title">Подтверждение email</h1>
      <p className="page__subtitle">Для доступа к календарю подтвердите email по ссылке из письма.</p>
      <form className="auth-form" onSubmit={(e) => { e.preventDefault(); void resend(); }}>
        <label className="auth-form__field">
          <span className="auth-form__label">Email</span>
          <input className="auth-form__input" type="email" value={email} onChange={(e) => setEmail(e.target.value)} required />
        </label>
        {message ? <p className="page__subtitle">{message}</p> : null}
        {error ? <p className="page__subtitle page__subtitle--error">{error}</p> : null}
        <button className="btn btn--primary" type="submit">Отправить письмо ещё раз</button>
      </form>
    </section>
  );
}

export function ForgotPasswordPage(): JSX.Element {
  const [email, setEmail] = useState("");
  const [message, setMessage] = useState<string | null>(null);

  return (
    <section className="page page--auth">
      <h1 className="page__title">Сброс пароля</h1>
      <form className="auth-form" onSubmit={async (e) => { e.preventDefault(); await forgotPassword(email); setMessage("Если email зарегистрирован, ссылка отправлена."); }}>
        <label className="auth-form__field">
          <span className="auth-form__label">Email</span>
          <input className="auth-form__input" type="email" value={email} onChange={(event) => setEmail(event.target.value)} required />
        </label>
        {message ? <p className="page__subtitle">{message}</p> : null}
        <button className="btn btn--primary" type="submit">Отправить ссылку</button>
      </form>
    </section>
  );
}

export function ResetPasswordPage(): JSX.Element {
  const [params] = useSearchParams();
  const [password, setPassword] = useState("");
  const [message, setMessage] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);

  return (
    <section className="page page--auth">
      <h1 className="page__title">Новый пароль</h1>
      <form className="auth-form" onSubmit={async (e) => {
        e.preventDefault();
        const token = params.get("token") ?? "";
        try {
          await resetPassword(token, password);
          setMessage("Пароль обновлён. Теперь войдите заново.");
        } catch (err) {
          setError(errorMessage(err, "Не удалось обновить пароль."));
        }
      }}>
        <label className="auth-form__field">
          <span className="auth-form__label">Пароль</span>
          <input className="auth-form__input" type="password" minLength={15} value={password} onChange={(event) => setPassword(event.target.value)} required />
        </label>
        {message ? <p className="page__subtitle">{message}</p> : null}
        {error ? <p className="page__subtitle page__subtitle--error">{error}</p> : null}
        <button className="btn btn--primary" type="submit">Сохранить пароль</button>
      </form>
    </section>
  );
}
