'use client';

import Link from 'next/link';
import { useActionState, useEffect, useRef, useState } from 'react';
import { Button, ButtonLink } from '@/components/ui/Button';
import { ChipCheckbox, ChoiceGroup, Field, Input, Textarea } from '@/components/ui/Field';
import { AlertIcon, ArrowRightIcon, CheckIcon, PlayIcon } from '@/components/ui/icons';
import { HONEYPOT_FIELD, NIGHT_LABELS, NIGHTS, TOKEN_FIELD } from '@/lib/pilot';
import type { PilotField, PilotFormState, PilotFormValues } from '@/lib/pilot';
import { issuePilotFormToken, submitPilotApplication } from './actions';

const initialState: PilotFormState = { status: 'idle' };
/** Well inside the server's 2-hour token lifetime (lib/form-token.ts MAX_TOKEN_AGE_MS). */
const TOKEN_REFRESH_MS = 90 * 60 * 1000;

const fieldIds: Record<PilotField, string> = {
  venueName: 'pilot-venue-name',
  address: 'pilot-address',
  contactName: 'pilot-contact-name',
  email: 'pilot-email',
  phone: 'pilot-phone',
  tvCount: 'pilot-tv-count',
  busiestNights: 'pilot-night-MON',
  currentEntertainment: 'pilot-entertainment',
  message: 'pilot-message',
};

const fieldLabels: Record<PilotField, string> = {
  venueName: 'Venue name',
  address: 'Address',
  contactName: 'Your name',
  email: 'Email',
  phone: 'Phone',
  tvCount: 'Number of TVs',
  busiestNights: 'Busiest nights',
  currentEntertainment: 'Current entertainment',
  message: 'Message',
};

const emptyValues: PilotFormValues = {
  venueName: '',
  address: '',
  contactName: '',
  email: '',
  phone: '',
  tvCount: '',
  busiestNights: [],
  currentEntertainment: '',
  message: '',
};

export function PilotForm() {
  const [state, formAction, pending] = useActionState(submitPilotApplication, initialState);
  const [token, setToken] = useState('');
  const summaryRef = useRef<HTMLDivElement>(null);
  const successRef = useRef<HTMLHeadingElement>(null);

  // The page is statically rendered, so fetch the signed start-time token once the form is live.
  // Tokens are single-use and expire after about two hours, so a new one is fetched when the server
  // says the current one is spent or expired, and ahead of expiry on a page left open.
  const tokenRequest = state.status === 'error' && state.refreshToken ? state : null;
  useEffect(() => {
    let cancelled = false;
    const fetchToken = () => {
      issuePilotFormToken()
        .then((value) => {
          if (!cancelled) setToken(value);
        })
        .catch(() => {
          // Submitting without a token returns a clear "reload the page" message from the server.
        });
    };
    fetchToken();
    const timer = setInterval(fetchToken, TOKEN_REFRESH_MS);
    return () => {
      cancelled = true;
      clearInterval(timer);
    };
  }, [tokenRequest]);

  // Move focus to the outcome so keyboard and screen-reader users hear what happened.
  useEffect(() => {
    if (state.status === 'error') summaryRef.current?.focus();
    if (state.status === 'success') successRef.current?.focus();
  }, [state]);

  if (state.status === 'success') {
    return (
      <div className="flex flex-col gap-6 text-center sm:text-left">
        <span className="grid size-16 place-items-center self-center rounded-2xl bg-lime text-on-bright shadow-glow-lime sm:self-start">
          <CheckIcon className="size-9" strokeWidth={2.5} />
        </span>
        <h2 ref={successRef} tabIndex={-1} className="font-display text-2xl leading-tight font-bold tracking-[-0.02em] outline-none sm:text-3xl">
          You’re on the list{state.venueName ? `, ${state.venueName}` : ''}!
        </h2>
        <p className="text-lg leading-relaxed text-muted">
          Thanks — your pilot application is in. We’ll be in touch at <strong className="text-fg">{state.email}</strong>.
        </p>
        <div className="rounded-tile border border-line bg-night/50 p-5 text-left">
          <h3 className="mb-3 font-display font-bold">What happens next</h3>
          <ol className="flex flex-col gap-3 text-muted">
            {[
              'We review your application and get back to you.',
              'A short call to plan your screens, setup and game nights.',
              'Your first PintRush night — with us on hand to help.',
            ].map((step, index) => (
              <li key={step} className="flex gap-3">
                <span className="num grid size-7 shrink-0 place-items-center rounded-lg bg-violet/25 font-display text-sm font-bold text-violet-soft">
                  {index + 1}
                </span>
                {step}
              </li>
            ))}
          </ol>
        </div>
        <div className="flex flex-col gap-3 sm:flex-row">
          <ButtonLink href="/demo" size="lg">
            <PlayIcon /> Try the live demo
          </ButtonLink>
          <ButtonLink href="/how-it-works" size="lg" variant="secondary">
            How the game works
          </ButtonLink>
        </div>
      </div>
    );
  }

  const errors = state.status === 'error' ? state.fieldErrors : {};
  const values = state.status === 'error' ? state.values : emptyValues;
  const errorEntries = Object.entries(errors) as [PilotField, string][];

  return (
    <form action={formAction} noValidate className="relative flex flex-col gap-6" aria-describedby="pilot-required-note">
      {state.status === 'error' && (
        <div
          ref={summaryRef}
          tabIndex={-1}
          role="alert"
          className="flex flex-col gap-3 rounded-tile border border-danger/60 bg-danger/10 p-5 outline-none focus-visible:outline-3 focus-visible:outline-cyan"
        >
          <p className="flex items-start gap-2 font-semibold text-fg">
            <AlertIcon className="mt-0.5 size-5 shrink-0 text-danger-soft" />
            {state.message}
          </p>
          {errorEntries.length > 0 && (
            <ul className="flex flex-col gap-1 pl-7 text-sm">
              {errorEntries.map(([field, message]) => (
                <li key={field}>
                  <a href={`#${fieldIds[field]}`} className="text-danger-soft underline underline-offset-4 hover:text-fg">
                    {fieldLabels[field]}: {message}
                  </a>
                </li>
              ))}
            </ul>
          )}
        </div>
      )}

      <p id="pilot-required-note" className="text-sm text-subtle">
        Fields marked <span className="text-danger-soft">*</span> are required.
      </p>

      <Field label="Venue name" required error={errors.venueName} id={fieldIds.venueName}>
        <Input name="venueName" autoComplete="organization" defaultValue={values.venueName} maxLength={120} />
      </Field>

      <Field label="Address" required hint="Street, town and state." error={errors.address} id={fieldIds.address}>
        <Input name="address" defaultValue={values.address} maxLength={200} />
      </Field>

      <div className="grid gap-6 sm:grid-cols-2">
        <Field label="Your name" required error={errors.contactName} id={fieldIds.contactName}>
          <Input name="contactName" autoComplete="name" defaultValue={values.contactName} maxLength={80} />
        </Field>
        <Field label="Email" required error={errors.email} id={fieldIds.email}>
          <Input name="email" type="email" inputMode="email" autoComplete="email" defaultValue={values.email} maxLength={254} />
        </Field>
      </div>

      <div className="grid gap-6 sm:grid-cols-2">
        <Field label="Phone" optional error={errors.phone} id={fieldIds.phone}>
          <Input name="phone" type="tel" autoComplete="tel" defaultValue={values.phone} maxLength={32} />
        </Field>
        <Field label="Number of TVs" required hint="Screens that could show the game." error={errors.tvCount} id={fieldIds.tvCount}>
          <Input name="tvCount" type="number" inputMode="numeric" min={1} max={200} step={1} defaultValue={values.tvCount} />
        </Field>
      </div>

      <ChoiceGroup legend="Busiest nights" required hint="Pick every night that gets busy." error={errors.busiestNights}>
        <div className="flex flex-wrap gap-2">
          {NIGHTS.map((night) => (
            <ChipCheckbox
              key={night}
              id={`pilot-night-${night}`}
              name="busiestNights"
              value={night}
              label={NIGHT_LABELS[night]}
              defaultChecked={values.busiestNights.includes(night)}
            />
          ))}
        </div>
      </ChoiceGroup>

      <Field
        label="Current entertainment"
        optional
        hint="For example: live music on Fridays, weekly trivia, karaoke, sports."
        error={errors.currentEntertainment}
        id={fieldIds.currentEntertainment}
      >
        <Input name="currentEntertainment" defaultValue={values.currentEntertainment} maxLength={300} />
      </Field>

      <Field label="Anything else?" optional error={errors.message} id={fieldIds.message}>
        <Textarea name="message" rows={4} defaultValue={values.message} maxLength={2000} />
      </Field>

      {/* Spam trap: invisible to people and assistive tech, irresistible to bots. */}
      <div aria-hidden="true" className="absolute -left-[10000px] size-px overflow-hidden">
        <label htmlFor="pilot-extra-info">Leave this field empty</label>
        <input id="pilot-extra-info" type="text" name={HONEYPOT_FIELD} tabIndex={-1} autoComplete="off" defaultValue="" />
      </div>
      <input type="hidden" name={TOKEN_FIELD} value={token} />

      <div className="flex flex-col gap-4 border-t border-line/70 pt-6">
        <Button type="submit" size="lg" fullWidth disabled={pending} aria-disabled={pending || undefined}>
          {pending ? (
            <>
              <span aria-hidden="true" className="size-5 rounded-full border-2 border-white/40 border-t-white motion-safe:animate-spin" />
              Sending…
            </>
          ) : (
            <>
              Send my application <ArrowRightIcon />
            </>
          )}
        </Button>
        <p className="text-center text-sm leading-relaxed text-subtle">
          We only use these details to talk to you about the pilot. See our{' '}
          <Link href="/legal/privacy" className="font-medium text-violet-soft underline-offset-4 hover:underline">
            privacy notice
          </Link>
          .
        </p>
      </div>
    </form>
  );
}
