import {
  Button,
  Input,
  Label,
} from '@learnitive/ui-components';
import { CircleUserRound, GitBranch, LoaderCircle, Mail } from 'lucide-react';
import React from 'react';
import {
  requestMagicLogin,
  SaasApiError,
  type PublicSaasConfig,
} from './saas-api';

export function safeClientReturnPath(
  value: string | null | undefined,
  fallback = '/projects',
): string {
  if (typeof window === 'undefined') return fallback;
  if (!value || !value.startsWith('/') || value.startsWith('//') || value.includes('\\')) return fallback;
  try {
    const target = new URL(value, window.location.origin);
    return target.origin === window.location.origin
      ? `${target.pathname}${target.search}${target.hash}`
      : fallback;
  } catch {
    return fallback;
  }
}

export function currentClientReturnPath(fallback = '/projects'): string {
  if (typeof window === 'undefined') return fallback;
  return safeClientReturnPath(
    `${window.location.pathname}${window.location.search}${window.location.hash}`,
    fallback,
  );
}

type TurnstileApi = {
  render: (container: HTMLElement, options: Record<string, unknown>) => string;
  remove?: (widgetId: string) => void;
};

function MagicEmailCaptcha({
  siteKey,
  onToken,
  onError,
}: {
  siteKey: string;
  onToken: (token: string) => void;
  onError: (message: string) => void;
}) {
  const host = React.useRef<HTMLDivElement>(null);
  React.useEffect(() => {
    let active = true;
    let widgetId = '';
    const render = () => {
      if (!active || !host.current) return;
      const api = (window as Window & { turnstile?: TurnstileApi }).turnstile;
      if (!api) return;
      widgetId = api.render(host.current, {
        sitekey: siteKey,
        action: 'magic-login',
        theme: 'auto',
        callback: (token: string) => onToken(token),
        'expired-callback': () => onToken(''),
        'error-callback': () => {
          onToken('');
          onError('Verification could not load. Please try again.');
        },
      });
    };
    const existing = document.querySelector<HTMLScriptElement>(
      'script[data-learnitive-turnstile]',
    );
    if ((window as Window & { turnstile?: TurnstileApi }).turnstile) {
      render();
    } else if (existing) {
      existing.addEventListener('load', render, { once: true });
    } else {
      const script = document.createElement('script');
      script.src = 'https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit';
      script.async = true;
      script.defer = true;
      script.dataset.learnitiveTurnstile = 'true';
      script.addEventListener('load', render, { once: true });
      script.addEventListener(
        'error',
        () => onError('Verification could not load. Please try again.'),
        { once: true },
      );
      document.head.appendChild(script);
    }
    return () => {
      active = false;
      if (widgetId) {
        (window as Window & { turnstile?: TurnstileApi }).turnstile?.remove?.(
          widgetId,
        );
      }
    };
  }, [onError, onToken, siteKey]);

  return (
    <div
      className="interactive-magic-captcha"
      ref={host}
      aria-label="Email sign in verification"
    />
  );
}

export function InteractiveAuthCard({
  config,
  returnTo,
  eyebrow = 'Welcome back',
  title = 'Sign in',
  description = 'Continue with Google, GitHub or a secure email link',
  continueWithoutAccountHref = '/projects',
  onContinueWithoutAccount,
  providersLoading = false,
  providerError,
}: {
  config?: PublicSaasConfig;
  returnTo: string;
  eyebrow?: string;
  title?: string;
  description?: React.ReactNode;
  continueWithoutAccountHref?: string;
  onContinueWithoutAccount?: () => void;
  providersLoading?: boolean;
  providerError?: string;
}) {
  const safeReturnTo = safeClientReturnPath(returnTo);
  const emailInputId = React.useId();
  const [email, setEmail] = React.useState('');
  const [captchaToken, setCaptchaToken] = React.useState('');
  const [sending, setSending] = React.useState(false);
  const [emailSent, setEmailSent] = React.useState(false);
  const [error, setError] = React.useState('');
  const captchaSiteKey = config?.captcha?.siteKey || '';
  const onCaptchaToken = React.useCallback((token: string) => {
    setCaptchaToken(token);
    if (token) setError('');
  }, []);
  const onCaptchaError = React.useCallback(
    (message: string) => setError(message),
    [],
  );

  React.useEffect(() => {
    setEmailSent(false);
    setError('');
    setCaptchaToken('');
  }, [safeReturnTo]);

  const requestEmail = async (event: React.FormEvent) => {
    event.preventDefault();
    if (!captchaToken) {
      setError('Complete the verification before requesting a sign in link.');
      return;
    }
    setSending(true);
    setError('');
    try {
      await requestMagicLogin(email, captchaToken, safeReturnTo);
      setEmailSent(true);
    } catch (reason) {
      const code = reason instanceof SaasApiError ? reason.code : '';
      setError(
        code === 'magic_link_rate_limited'
          ? 'Too many sign in requests. Please wait before trying again.'
          : code === 'captcha_failed' || code === 'captcha_required'
            ? 'Verification failed. Please try again.'
            : 'We could not send the sign in email. Please try again shortly.',
      );
    } finally {
      setSending(false);
    }
  };

  const noProviders = Boolean(
    config
      && !config.googleAuthEnabled
      && !config.githubAuthEnabled
      && !config.magicEmailEnabled,
  );

  return (
    <div className="interactive-auth-card">
      <a className="interactive-brand" href="/" aria-label="Learnitive home">
        <img
          className="interactive-brand-logo"
          alt=""
          src="/learnitive-logo-mobile.png"
        />
        <span className="interactive-brand-name">Learnitive</span>
      </a>
      <span className="interactive-eyebrow">{eyebrow}</span>
      <h1 className="interactive-display">{title}</h1>
      <p>{description}</p>

      {config?.googleAuthEnabled ? (
        <a
          className="interactive-button interactive-button-primary interactive-button-lg"
          href={`/api/auth/google?returnTo=${encodeURIComponent(safeReturnTo)}`}
        >
          <CircleUserRound className="size-5" /> Continue with Google
        </a>
      ) : null}

      {config?.githubAuthEnabled ? (
        <a
          className="interactive-button interactive-button-secondary interactive-button-lg"
          href={`/api/auth/github?returnTo=${encodeURIComponent(safeReturnTo)}`}
        >
          <GitBranch className="size-5" /> Continue with GitHub
        </a>
      ) : null}

      {config?.magicEmailEnabled ? (
        <>
          <div className="interactive-auth-divider">
            <span>or continue with email</span>
          </div>
          {emailSent ? (
            <div className="interactive-success">
              <strong>Check your email.</strong>
              <br />
              We sent a secure sign in link. It expires shortly and can only be used once.
            </div>
          ) : (
            <form className="interactive-magic-login-form" onSubmit={requestEmail}>
              <Label htmlFor={emailInputId}>Email address</Label>
              <Input
                id={emailInputId}
                type="email"
                autoComplete="email"
                required
                value={email}
                onChange={(event) => setEmail(event.currentTarget.value)}
                placeholder="you@example.com"
              />
              {captchaSiteKey ? (
                <MagicEmailCaptcha
                  siteKey={captchaSiteKey}
                  onToken={onCaptchaToken}
                  onError={onCaptchaError}
                />
              ) : null}
              {error ? (
                <div className="interactive-error" role="alert">
                  {error}
                </div>
              ) : null}
              <Button type="submit" disabled={sending || !captchaToken}>
                {sending ? (
                  <>
                    <LoaderCircle className="size-4 animate-spin" /> Sending…
                  </>
                ) : (
                  <>
                    <Mail className="size-4" /> Email me a magic sign in link
                  </>
                )}
              </Button>
            </form>
          )}
        </>
      ) : null}

      {providersLoading ? (
        <p className="interactive-muted text-sm" role="status">
          Loading sign in options…
        </p>
      ) : null}
      {providerError ? (
        <div className="interactive-error" role="alert">
          {providerError}
        </div>
      ) : null}
      {noProviders ? (
        <div className="interactive-error" role="alert">
          No account sign in provider is configured on this Learnitive deployment.
        </div>
      ) : null}

      {onContinueWithoutAccount ? (
        <button
          className="interactive-text-link interactive-auth-text-button"
          type="button"
          onClick={onContinueWithoutAccount}
        >
          Continue without an account
        </button>
      ) : (
        <a className="interactive-text-link" href={continueWithoutAccountHref}>
          Continue without an account
        </a>
      )}
    </div>
  );
}
