import {
  loginWithMagicLink,
  signUpWithMagicLink,
  verifyMagicLinkOtp,
} from '@chat-app/shared/auth';
import {
  extractErrorCode,
  isSupportedLocale,
  type SupportedLocale,
} from '@chat-app/shared/i18n';
import { useCallback, useId, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Navigate } from 'react-router-dom';

import {
  AlertIcon,
  ArrowRightIcon,
  AtIcon,
  CheckCircleIcon,
  LockIcon,
  LogoMark,
  MailIcon,
  ShieldIcon,
  SparklesIcon,
  SpinnerIcon,
  TicketIcon,
} from '../components/icons';
import { LanguageSwitcher } from '../components/LanguageSwitcher';
import { useAuth } from '../context/AuthContext';
import { env } from '../lib/env';
import { supabase } from '../lib/supabase';

type Mode = 'signup' | 'login';

type UiState =
  | { kind: 'idle' }
  | { kind: 'sending' }
  | { kind: 'sent'; email: string }
  | { kind: 'error'; message: string };

const USERNAME_PATTERN = /^[A-Za-z0-9_]{3,32}$/;

export function AuthPage() {
  const { session } = useAuth();
  const { t, i18n } = useTranslation(['auth', 'common', 'errors']);
  const [ui, setUi] = useState<UiState>({ kind: 'idle' });
  const [mode, setMode] = useState<Mode>('signup');
  const [email, setEmail] = useState('');
  const [username, setUsername] = useState('');
  const [inviteCode, setInviteCode] = useState('DEV-INVITE-001');

  const usernameValid = useMemo(() => USERNAME_PATTERN.test(username), [username]);

  const handleSubmit = useCallback(
    async (e: React.FormEvent) => {
      e.preventDefault();
      setUi({ kind: 'sending' });
      try {
        if (mode === 'signup') {
          const activeLocale = i18n.resolvedLanguage ?? i18n.language;
          await signUpWithMagicLink(supabase, {
            email,
            username,
            inviteCode,
            redirectTo: env.authRedirectUrl,
            ...(isSupportedLocale(activeLocale)
              ? { locale: activeLocale satisfies SupportedLocale }
              : {}),
          });
        } else {
          await loginWithMagicLink(supabase, email, env.authRedirectUrl);
        }
        setUi({ kind: 'sent', email });
      } catch (err: unknown) {
        const code = extractErrorCode(err);
        const message = code
          ? t('errors:' + code, { defaultValue: t('errors:generic') })
          : err instanceof Error
            ? err.message
            : t('errors:generic');
        setUi({ kind: 'error', message });
      }
    },
    [mode, email, username, inviteCode, i18n, t],
  );

  // Already signed in? Bounce to chats. Guards take it from here.
  if (session) return <Navigate to="/chats" replace />;

  return (
    <Shell>
      <BrandPanel />
      <FormCard
        mode={mode}
        onModeChange={setMode}
        email={email}
        onEmailChange={setEmail}
        username={username}
        onUsernameChange={setUsername}
        usernameValid={usernameValid}
        inviteCode={inviteCode}
        onInviteChange={setInviteCode}
        ui={ui}
        onSubmit={handleSubmit}
      />
    </Shell>
  );
}

// ---------------------------------------------------------------------------
// Layout
// ---------------------------------------------------------------------------

function Shell({ children }: { children: React.ReactNode }) {
  return (
    <main className="relative min-h-screen overflow-hidden bg-ink-950 text-neutral-100">
      <BackgroundStage />
      <div className="relative z-10 grid min-h-screen w-full grid-cols-1 gap-0 lg:grid-cols-[minmax(0,1fr)_minmax(440px,560px)]">
        {children}
      </div>
    </main>
  );
}

function BackgroundStage() {
  return (
    <div aria-hidden="true" className="pointer-events-none absolute inset-0">
      <div className="bg-grid absolute inset-0 opacity-[0.28]" />
      <div className="absolute -left-40 top-[22%] h-[560px] w-[560px] -translate-y-1/2 rounded-full bg-brand-500/30 blur-3xl animate-blob-a xl:h-[680px] xl:w-[680px] 2xl:h-[820px] 2xl:w-[820px]" />
      <div className="absolute left-[38%] top-[60%] h-[520px] w-[520px] -translate-y-1/2 rounded-full bg-fuchsia-500/20 blur-3xl animate-blob-b xl:h-[640px] xl:w-[640px] 2xl:h-[780px] 2xl:w-[780px]" />
      <div className="absolute -right-32 top-[12%] h-[420px] w-[420px] rounded-full bg-indigo-500/20 blur-3xl animate-blob-b xl:h-[520px] xl:w-[520px]" />
      <div className="absolute -right-20 bottom-0 h-[460px] w-[460px] rounded-full bg-rose-500/10 blur-3xl animate-blob-a xl:h-[560px] xl:w-[560px]" />
      <div className="absolute inset-0 bg-gradient-to-b from-transparent via-transparent to-ink-950/80" />
      <div className="absolute inset-0 bg-[radial-gradient(ellipse_at_center,transparent_40%,rgba(5,5,7,0.65)_100%)]" />
    </div>
  );
}

function BrandPanel() {
  const { t } = useTranslation(['auth', 'common']);
  return (
    <section className="relative hidden lg:block">
      <div className="grid h-full grid-rows-[auto_1fr_auto] px-10 py-10 xl:px-14 xl:py-14 2xl:px-20 2xl:py-16">
        <header className="flex items-center justify-between gap-3">
          <div className="flex items-center gap-3">
            <LogoMark className="h-9 w-9" />
            <span className="font-display text-lg font-semibold tracking-tight">
              {t('common:app_name')}
            </span>
          </div>
          <LanguageSwitcher />
        </header>

        <div className="flex items-center">
          <div className="w-full max-w-xl animate-fade-in xl:max-w-2xl 2xl:max-w-3xl">
            <p className="inline-flex items-center gap-2 rounded-full border border-white/10 bg-white/5 px-3 py-1 text-xs font-medium text-neutral-300 backdrop-blur">
              <ShieldIcon className="h-3.5 w-3.5 text-emerald-400" />
              {t('auth:brand.badge')}
            </p>
            <h1 className="mt-6 font-display text-4xl font-semibold leading-[1.05] tracking-tight text-white xl:text-5xl 2xl:text-6xl">
              {t('auth:brand.title_line_1')}
              <br />
              {t('auth:brand.title_line_2')}
            </h1>
            <p className="mt-5 max-w-lg text-base leading-relaxed text-neutral-400 xl:text-lg 2xl:max-w-xl">
              {t('auth:brand.subtitle')}
            </p>

            <dl className="mt-10 grid grid-cols-1 gap-4 sm:grid-cols-2 xl:mt-12 xl:gap-5 2xl:grid-cols-3">
              <Feature
                icon={<LockIcon className="h-5 w-5 text-brand-300" />}
                title={t('auth:brand.feature_zk_title')}
                desc={t('auth:brand.feature_zk_desc')}
              />
              <Feature
                icon={<SparklesIcon className="h-5 w-5 text-brand-300" />}
                title={t('auth:brand.feature_selfhost_title')}
                desc={t('auth:brand.feature_selfhost_desc')}
              />
              <Feature
                icon={<ShieldIcon className="h-5 w-5 text-brand-300" />}
                title={t('auth:brand.feature_invite_title')}
                desc={t('auth:brand.feature_invite_desc')}
              />
            </dl>
          </div>
        </div>

        <footer className="flex items-center justify-between text-xs text-neutral-500">
          <span>v0.1.0 · {t('common:dev_build')}</span>
          <span className="inline-flex items-center gap-1.5 text-neutral-600">
            <span className="h-1.5 w-1.5 rounded-full bg-emerald-400" />
            {t('common:local_stack_online')}
          </span>
        </footer>
      </div>
    </section>
  );
}

function Feature({ icon, title, desc }: { icon: React.ReactNode; title: string; desc: string }) {
  return (
    <div className="rounded-xl border border-white/5 bg-white/5 p-4 backdrop-blur">
      <div className="flex items-center gap-2">
        {icon}
        <dt className="text-sm font-semibold text-white">{title}</dt>
      </div>
      <dd className="mt-1.5 text-sm text-neutral-400">{desc}</dd>
    </div>
  );
}

interface FormCardProps {
  mode: Mode;
  onModeChange: (m: Mode) => void;
  email: string;
  onEmailChange: (v: string) => void;
  username: string;
  onUsernameChange: (v: string) => void;
  usernameValid: boolean;
  inviteCode: string;
  onInviteChange: (v: string) => void;
  ui: UiState;
  onSubmit: (e: React.FormEvent) => void;
}

function FormCard({
  mode,
  onModeChange,
  email,
  onEmailChange,
  username,
  onUsernameChange,
  usernameValid,
  inviteCode,
  onInviteChange,
  ui,
  onSubmit,
}: FormCardProps) {
  const { t } = useTranslation(['auth']);
  const busy = ui.kind === 'sending';
  const emailId = useId();
  const usernameId = useId();
  const inviteId = useId();

  const titleKey = mode === 'signup' ? 'auth:signup.title' : 'auth:login.title';
  const subtitleKey = mode === 'signup' ? 'auth:signup.subtitle' : 'auth:login.subtitle';
  const ctaKey = mode === 'signup' ? 'auth:signup.cta' : 'auth:login.cta';
  const ctaSendingKey = mode === 'signup' ? 'auth:signup.cta_sending' : 'auth:login.cta_sending';

  return (
    <section className="relative flex items-center justify-center px-5 py-10 sm:px-8 lg:px-10 xl:px-16">
      <div className="absolute left-6 right-6 top-6 flex items-center justify-between lg:hidden">
        <div className="flex items-center gap-2.5">
          <LogoMark className="h-7 w-7" />
          <span className="font-display text-base font-semibold tracking-tight">ChatApp</span>
        </div>
        <LanguageSwitcher compact />
      </div>

      <div className="w-full max-w-md animate-slide-up">
        <div className="rounded-2xl border border-white/10 bg-ink-900/70 p-6 shadow-glow backdrop-blur-xl sm:p-8">
          <header className="mb-6">
            <h2 className="font-display text-2xl font-semibold tracking-tight text-white">
              {t(titleKey)}
            </h2>
            <p className="mt-1.5 text-sm text-neutral-400">{t(subtitleKey)}</p>
          </header>

          <Segmented mode={mode} onChange={onModeChange} />

          <form onSubmit={onSubmit} className="mt-6 space-y-4" noValidate>
            <Field
              id={emailId}
              label={t('auth:fields.email')}
              icon={<MailIcon className="h-4 w-4" />}
              input={
                <input
                  id={emailId}
                  type="email"
                  name="email"
                  inputMode="email"
                  autoComplete="email"
                  required
                  placeholder={t('auth:fields.email_placeholder')}
                  value={email}
                  onChange={(e) => onEmailChange(e.target.value)}
                  className="w-full rounded-lg border border-white/10 bg-ink-800 py-2.5 pl-10 pr-3 text-sm text-white placeholder-neutral-500 transition focus:border-brand-400 focus:outline-none focus:ring-2 focus:ring-brand-500/40"
                />
              }
            />

            {mode === 'signup' && (
              <>
                <Field
                  id={usernameId}
                  label={t('auth:fields.username')}
                  hint={
                    username.length > 0 && !usernameValid
                      ? t('auth:fields.username_invalid')
                      : t('auth:fields.username_hint')
                  }
                  invalid={username.length > 0 && !usernameValid}
                  icon={<AtIcon className="h-4 w-4" />}
                  input={
                    <input
                      id={usernameId}
                      type="text"
                      name="username"
                      autoComplete="username"
                      autoCapitalize="none"
                      autoCorrect="off"
                      spellCheck={false}
                      required
                      placeholder={t('auth:fields.username_placeholder')}
                      value={username}
                      onChange={(e) => onUsernameChange(e.target.value)}
                      pattern={USERNAME_PATTERN.source}
                      className="w-full rounded-lg border border-white/10 bg-ink-800 py-2.5 pl-10 pr-3 text-sm text-white placeholder-neutral-500 transition focus:border-brand-400 focus:outline-none focus:ring-2 focus:ring-brand-500/40"
                    />
                  }
                />

                <Field
                  id={inviteId}
                  label={t('auth:fields.invite_code')}
                  hint={t('auth:fields.invite_hint')}
                  icon={<TicketIcon className="h-4 w-4" />}
                  input={
                    <input
                      id={inviteId}
                      type="text"
                      name="invite"
                      autoCorrect="off"
                      spellCheck={false}
                      required
                      value={inviteCode}
                      onChange={(e) => onInviteChange(e.target.value)}
                      className="w-full rounded-lg border border-white/10 bg-ink-800 py-2.5 pl-10 pr-3 text-sm font-mono text-white transition focus:border-brand-400 focus:outline-none focus:ring-2 focus:ring-brand-500/40"
                    />
                  }
                />
              </>
            )}

            <button
              type="submit"
              disabled={busy}
              aria-busy={busy}
              className="group inline-flex w-full cursor-pointer items-center justify-center gap-2 rounded-lg bg-gradient-to-br from-brand-400 to-brand-600 px-4 py-3 text-sm font-semibold text-white shadow-glow transition hover:from-brand-300 hover:to-brand-500 focus:outline-none focus:ring-2 focus:ring-brand-400/60 focus:ring-offset-2 focus:ring-offset-ink-900 disabled:cursor-not-allowed disabled:opacity-60"
            >
              {busy ? (
                <>
                  <SpinnerIcon className="h-4 w-4" />
                  <span>{t(ctaSendingKey)}</span>
                </>
              ) : (
                <>
                  <span>{t(ctaKey)}</span>
                  <ArrowRightIcon className="h-4 w-4 transition group-hover:translate-x-0.5" />
                </>
              )}
            </button>

            <StatusBanner ui={ui} />
            {ui.kind === 'sent' && <OtpForm email={ui.email} />}
          </form>

          <Footer mode={mode} onModeChange={onModeChange} />
        </div>

        <p className="mt-6 text-center text-xs text-neutral-500">{t('auth:legal_note')}</p>
      </div>
    </section>
  );
}

function Segmented({ mode, onChange }: { mode: Mode; onChange: (m: Mode) => void }) {
  const { t } = useTranslation(['auth']);
  return (
    <div
      role="tablist"
      aria-label="Authentication mode"
      className="relative grid grid-cols-2 rounded-lg border border-white/10 bg-ink-800 p-1 text-sm"
    >
      <div
        aria-hidden="true"
        className="absolute bottom-1 top-1 w-[calc(50%-4px)] rounded-md bg-brand-500/20 ring-1 ring-brand-400/40 transition-transform duration-200"
        style={{ transform: 'translateX(' + (mode === 'signup' ? '0%' : 'calc(100% + 4px)') + ')' }}
      />
      <SegmentButton active={mode === 'signup'} onClick={() => onChange('signup')}>
        {t('auth:tab_signup')}
      </SegmentButton>
      <SegmentButton active={mode === 'login'} onClick={() => onChange('login')}>
        {t('auth:tab_login')}
      </SegmentButton>
    </div>
  );
}

function SegmentButton({
  active,
  onClick,
  children,
}: {
  active: boolean;
  onClick: () => void;
  children: React.ReactNode;
}) {
  return (
    <button
      type="button"
      role="tab"
      aria-selected={active}
      onClick={onClick}
      className={
        'relative z-10 cursor-pointer rounded-md px-3 py-2 font-medium transition focus:outline-none ' +
        (active ? 'text-white' : 'text-neutral-400 hover:text-neutral-200')
      }
    >
      {children}
    </button>
  );
}

function Field({
  id,
  label,
  hint,
  icon,
  input,
  invalid,
}: {
  id: string;
  label: string;
  hint?: string;
  icon: React.ReactNode;
  input: React.ReactNode;
  invalid?: boolean;
}) {
  return (
    <div className="space-y-1.5">
      <label htmlFor={id} className="block text-xs font-medium uppercase tracking-wide text-neutral-400">
        {label}
      </label>
      <div className="relative">
        <span className="pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-neutral-500">
          {icon}
        </span>
        {input}
      </div>
      {hint && (
        <p className={'text-xs ' + (invalid ? 'text-rose-400' : 'text-neutral-500')}>{hint}</p>
      )}
    </div>
  );
}

function StatusBanner({ ui }: { ui: UiState }) {
  const { t } = useTranslation(['auth']);
  if (ui.kind === 'sent') {
    return (
      <div
        role="status"
        className="flex items-start gap-3 rounded-lg border border-emerald-500/20 bg-emerald-500/10 p-3.5 text-sm text-emerald-100"
      >
        <CheckCircleIcon className="mt-0.5 h-5 w-5 shrink-0 text-emerald-400" />
        <div className="min-w-0 flex-1 space-y-1">
          <p className="break-words font-medium">
            {t('auth:sent_banner', { email: ui.email })}
          </p>
          <p className="break-words text-xs text-emerald-200/80">
            <InbucketHint />
          </p>
        </div>
      </div>
    );
  }

  if (ui.kind === 'error') {
    return (
      <div
        role="alert"
        className="flex items-start gap-3 rounded-lg border border-rose-500/20 bg-rose-500/10 p-3.5 text-sm text-rose-100"
      >
        <AlertIcon className="mt-0.5 h-5 w-5 shrink-0 text-rose-400" />
        <p className="min-w-0 flex-1 break-words">{ui.message}</p>
      </div>
    );
  }

  return null;
}

function InbucketHint() {
  const { t } = useTranslation(['auth']);
  const parts = t('auth:sent_banner_hint').split('Inbucket');
  if (parts.length === 1) return <span>{t('auth:sent_banner_hint')}</span>;
  return (
    <span>
      {parts[0]}
      <a
        href="http://127.0.0.1:54324"
        target="_blank"
        rel="noreferrer"
        className="underline underline-offset-2 hover:text-white"
      >
        Inbucket
      </a>
      {parts[1]}
    </span>
  );
}

function OtpForm({ email }: { email: string }) {
  const { t } = useTranslation(['auth', 'errors']);
  const [token, setToken] = useState('');
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const inputId = useId();

  async function handleVerify(e: React.FormEvent) {
    e.preventDefault();
    e.stopPropagation();
    if (busy || token.length !== 6) return;
    setBusy(true);
    setError(null);
    try {
      await verifyMagicLinkOtp(supabase, email, token);
      // Session updates via Supabase subscription; AuthPage Navigate redirects.
    } catch (err: unknown) {
      const code = extractErrorCode(err);
      setError(
        code
          ? t('errors:' + code, { defaultValue: t('errors:generic') })
          : err instanceof Error
            ? err.message
            : t('errors:generic'),
      );
    } finally {
      setBusy(false);
    }
  }

  return (
    <div className="mt-4 space-y-2 rounded-lg border border-white/10 bg-ink-800/50 p-4">
      <label
        htmlFor={inputId}
        className="block text-xs font-medium uppercase tracking-wide text-neutral-400"
      >
        {t('auth:otp_label')}
      </label>
      <input
        id={inputId}
        type="text"
        inputMode="numeric"
        autoComplete="one-time-code"
        pattern="\d{6}"
        maxLength={6}
        value={token}
        onChange={(e) => setToken(e.target.value.replace(/\D/g, ''))}
        onKeyDown={(e) => {
          if (e.key === 'Enter') {
            e.preventDefault();
            void handleVerify(e);
          }
        }}
        placeholder={t('auth:otp_placeholder')}
        autoFocus
        className="w-full rounded-lg border border-white/10 bg-ink-900 px-3 py-3 text-center font-mono text-xl tracking-[0.4em] text-white placeholder-neutral-600 transition focus:border-brand-400 focus:outline-none focus:ring-2 focus:ring-brand-500/40"
      />
      <p className="text-xs text-neutral-500">{t('auth:otp_hint')}</p>

      {error && (
        <p
          role="alert"
          className="break-words rounded-md border border-rose-500/20 bg-rose-500/10 px-3 py-2 text-xs text-rose-200"
        >
          {error}
        </p>
      )}

      <button
        type="button"
        disabled={busy || token.length !== 6}
        onClick={(e) => void handleVerify(e)}
        aria-busy={busy}
        className="mt-1 inline-flex w-full cursor-pointer items-center justify-center gap-2 rounded-lg bg-gradient-to-br from-brand-400 to-brand-600 px-4 py-2.5 text-sm font-semibold text-white shadow-glow transition hover:from-brand-300 hover:to-brand-500 focus:outline-none focus:ring-2 focus:ring-brand-400/60 disabled:cursor-not-allowed disabled:opacity-60"
      >
        {busy && <SpinnerIcon className="h-4 w-4" />}
        <span>{t(busy ? 'auth:otp_cta_loading' : 'auth:otp_cta')}</span>
      </button>
    </div>
  );
}

function Footer({ mode, onModeChange }: { mode: Mode; onModeChange: (m: Mode) => void }) {
  const { t } = useTranslation(['auth']);
  const promptKey = mode === 'signup' ? 'auth:footer_signup_prompt' : 'auth:footer_login_prompt';
  const switchKey =
    mode === 'signup' ? 'auth:footer_switch_to_login' : 'auth:footer_switch_to_signup';

  return (
    <div className="mt-6 flex items-center justify-between border-t border-white/5 pt-5 text-xs text-neutral-500">
      <span>
        {t(promptKey)}{' '}
        <button
          type="button"
          onClick={() => onModeChange(mode === 'signup' ? 'login' : 'signup')}
          className="cursor-pointer font-medium text-brand-300 underline-offset-2 hover:text-brand-200 hover:underline focus:outline-none focus:ring-2 focus:ring-brand-400/40 focus:ring-offset-2 focus:ring-offset-ink-900"
        >
          {t(switchKey)}
        </button>
      </span>
      <a
        href="http://127.0.0.1:54323"
        target="_blank"
        rel="noreferrer"
        className="hover:text-neutral-300"
      >
        {t('auth:footer_studio')} ↗
      </a>
    </div>
  );
}
