'use client';

import { Button } from '@/components/actions/Button';
import { ErrorSummary, type FormErrorItem } from '@/components/forms/ErrorSummary';
import { FormField } from '@/components/forms/FormField';
import { Select, TextArea, TextInput } from '@/components/forms/TextInput';
import { LiveRegion } from '@/components/foundation/LiveRegion';
import { StatusBadge } from '@/components/foundation/StatusBadge';
import { Dialog } from '@/components/overlays/Dialog';
import type { HomepageMessages } from '@/lib/localization/messages';
import { trackAnalytics } from '@/lib/analytics/client';
import type { AnalyticsContext } from '@/lib/analytics/events';
import {
  demoLeadSchema,
  fleetSizeValues,
  type DemoSource,
  type DemoSubmissionResult,
} from '@/lib/demo/schema';
import type { Locale } from '@/lib/localization/config';
import { getDirection } from '@/lib/localization/config';
import { useEffect, useMemo, useRef, useState } from 'react';
import { demoOpenEventName, type DemoOpenEventDetail } from './DemoTrigger';
import styles from './DemoDialogHost.module.css';

interface DemoDialogHostProps {
  locale: Locale;
  messages: HomepageMessages['form'];
  enabled: boolean;
}

type FormStatus = 'idle' | 'submitting' | 'success' | 'error';
type FieldErrors = Record<string, string>;

function messageForCode(code: string, messages: DemoDialogHostProps['messages']): string {
  switch (code) {
    case 'required':
      return messages.requiredError;
    case 'invalid_email':
      return messages.emailError;
    case 'invalid_fleet_size':
    case 'invalid_source':
    case 'invalid_idempotency_key':
      return messages.invalidOptionError;
    case 'too_long':
      return messages.tooLongError;
    default:
      return messages.genericError;
  }
}

function formMessage(
  result: Extract<DemoSubmissionResult, { ok: false }>,
  messages: DemoDialogHostProps['messages'],
) {
  switch (result.category) {
    case 'configuration':
    case 'consent':
      return messages.configurationError;
    case 'timeout':
      return messages.timeoutError;
    case 'duplicate':
      return messages.duplicateError;
    case 'rate-limit':
      return messages.rateLimitError;
    case 'validation':
      return messages.errorSummary;
    case 'integration':
    case 'abuse':
      return messages.genericError;
  }
}

function analyticsContext(
  locale: Locale,
  source: DemoSource,
  extra: Partial<Pick<AnalyticsContext, 'errorCode' | 'errorCount' | 'reason'>> = {},
): AnalyticsContext {
  const theme = document.documentElement.dataset.theme === 'dark' ? 'dark' : 'light';
  return {
    routeId: 'home',
    locale,
    direction: getDirection(locale),
    resolvedTheme: theme,
    source,
    ...extra,
  };
}

export function DemoDialogHost({ locale, messages, enabled }: DemoDialogHostProps) {
  const [open, setOpen] = useState(false);
  const [source, setSource] = useState<DemoSource>('hero');
  const [status, setStatus] = useState<FormStatus>('idle');
  const [fieldErrors, setFieldErrors] = useState<FieldErrors>({});
  const [formError, setFormError] = useState('');
  const [messageLength, setMessageLength] = useState(0);
  const formRef = useRef<HTMLFormElement>(null);
  const firstFieldRef = useRef<HTMLInputElement>(null);
  const returnFocusRef = useRef<HTMLElement | null>(null);
  const idempotencyKeyRef = useRef('');
  const startedAtRef = useRef(0);
  const closeTrackedRef = useRef(false);

  const summaryErrors = useMemo<FormErrorItem[]>(
    () =>
      Object.entries(fieldErrors).map(([fieldId, code]) => ({
        fieldId,
        message: messageForCode(code, messages),
      })),
    [fieldErrors, messages],
  );

  useEffect(() => {
    const handleOpen = (event: Event) => {
      const detail = (event as CustomEvent<DemoOpenEventDetail>).detail;
      if (!detail || !enabled) return;
      returnFocusRef.current = detail.trigger;
      setSource(detail.source);
      closeTrackedRef.current = false;
      setOpen(true);
      setStatus('idle');
      setFieldErrors({});
      setFormError('');
      idempotencyKeyRef.current = crypto.randomUUID();
      startedAtRef.current = Date.now();
      trackAnalytics('demo_open', analyticsContext(locale, detail.source));
    };
    window.addEventListener(demoOpenEventName, handleOpen);
    return () => window.removeEventListener(demoOpenEventName, handleOpen);
  }, [enabled, locale]);

  const reset = () => {
    formRef.current?.reset();
    setMessageLength(0);
    setStatus('idle');
    setFieldErrors({});
    setFormError('');
    idempotencyKeyRef.current = crypto.randomUUID();
    startedAtRef.current = Date.now();
    window.requestAnimationFrame(() => firstFieldRef.current?.focus());
  };

  const close = () => {
    if (status === 'submitting' || closeTrackedRef.current) return;
    closeTrackedRef.current = true;
    setOpen(false);
    trackAnalytics('demo_close', analyticsContext(locale, source, { reason: 'user' }));
  };

  return (
    <Dialog
      open={open}
      onOpenChange={(nextOpen) => {
        if (!nextOpen) close();
        else {
          closeTrackedRef.current = false;
          setOpen(true);
        }
      }}
      title={messages.title}
      description={messages.body}
      closeLabel={messages.close}
      initialFocusRef={firstFieldRef}
      returnFocusRef={returnFocusRef}
      dismissible={status !== 'submitting'}
    >
      {status === 'success' ? (
        <section className={styles.success} aria-live="polite">
          <StatusBadge tone="success">{messages.localModeLabel}</StatusBadge>
          <h3>{messages.successTitle}</h3>
          <p>{messages.successBody}</p>
          <div className={styles.actions}>
            <Button intent="primary" onClick={reset}>
              {messages.submitAnother}
            </Button>
            <Button intent="secondary" onClick={close}>
              {messages.close}
            </Button>
          </div>
        </section>
      ) : (
        <form
          ref={formRef}
          className={styles.form}
          noValidate
          onSubmit={async (event) => {
            event.preventDefault();
            if (status === 'submitting') return;

            const form = event.currentTarget;
            const values = new FormData(form);
            const leadInput = {
              fullName: String(values.get('fullName') ?? ''),
              workEmail: String(values.get('workEmail') ?? ''),
              company: String(values.get('company') ?? ''),
              fleetSize: String(values.get('fleetSize') ?? ''),
              market: String(values.get('market') ?? ''),
              preferredLanguage: String(values.get('preferredLanguage') ?? locale),
              message: String(values.get('message') ?? ''),
              idempotencyKey: idempotencyKeyRef.current || crypto.randomUUID(),
              source,
            };

            const clientResult = demoLeadSchema.safeParse(leadInput);
            if (!clientResult.success) {
              const nextErrors: FieldErrors = {};
              for (const issue of clientResult.error.issues) {
                const field = issue.path.at(-1);
                if (typeof field === 'string' && !nextErrors[field])
                  nextErrors[field] = issue.message;
              }
              setFieldErrors(nextErrors);
              setFormError(messages.errorSummary);
              trackAnalytics(
                'demo_validation_error',
                analyticsContext(locale, source, { errorCount: Object.keys(nextErrors).length }),
              );
              window.requestAnimationFrame(() => {
                const firstInvalid = form.querySelector<HTMLElement>('[aria-invalid="true"]');
                firstInvalid?.focus();
              });
              return;
            }

            setStatus('submitting');
            setFieldErrors({});
            setFormError('');
            trackAnalytics('demo_submit_attempt', analyticsContext(locale, source));

            try {
              const response = await fetch('/api/demo', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json', 'X-RDG-Form': 'demo-v1' },
                body: JSON.stringify({
                  lead: clientResult.data,
                  guard: {
                    honeypot: String(values.get('website') ?? ''),
                    startedAtMs: startedAtRef.current,
                  },
                }),
              });
              const result = (await response.json()) as DemoSubmissionResult;
              if (result.ok) {
                setStatus('success');
                trackAnalytics('demo_submit_success', analyticsContext(locale, source));
                return;
              }

              const serverErrors = Object.fromEntries(
                Object.entries(result.fieldErrors ?? {}).map(([field, code]) => [field, code]),
              );
              setFieldErrors(serverErrors);
              setFormError(formMessage(result, messages));
              setStatus('error');
              trackAnalytics(
                'demo_submit_failure',
                analyticsContext(locale, source, { errorCode: result.category }),
              );
              window.requestAnimationFrame(() => {
                const firstInvalid = form.querySelector<HTMLElement>('[aria-invalid="true"]');
                firstInvalid?.focus();
              });
            } catch {
              setFormError(messages.genericError);
              setStatus('error');
              trackAnalytics(
                'demo_submit_failure',
                analyticsContext(locale, source, { errorCode: 'network' }),
              );
            }
          }}
        >
          <div className={styles.notice}>
            <StatusBadge tone="info">{messages.localModeLabel}</StatusBadge>
            <p>{messages.privacy}</p>
          </div>

          {formError ? (
            <ErrorSummary
              title={formError}
              errors={
                summaryErrors.length > 0
                  ? summaryErrors
                  : [{ fieldId: 'demo-submit', message: formError }]
              }
            />
          ) : null}

          <div className={styles.grid}>
            <FormField
              id="fullName"
              label={messages.name}
              required
              error={
                fieldErrors.fullName ? messageForCode(fieldErrors.fullName, messages) : undefined
              }
            >
              <TextInput
                ref={firstFieldRef}
                id="fullName"
                name="fullName"
                autoComplete="name"
                required
                maxLength={120}
                invalid={Boolean(fieldErrors.fullName)}
                describedBy={fieldErrors.fullName ? 'fullName-error' : undefined}
              />
            </FormField>

            <FormField
              id="workEmail"
              label={messages.email}
              required
              error={
                fieldErrors.workEmail ? messageForCode(fieldErrors.workEmail, messages) : undefined
              }
            >
              <TextInput
                id="workEmail"
                name="workEmail"
                type="email"
                inputMode="email"
                autoComplete="email"
                required
                maxLength={254}
                invalid={Boolean(fieldErrors.workEmail)}
                describedBy={fieldErrors.workEmail ? 'workEmail-error' : undefined}
              />
            </FormField>

            <FormField
              id="company"
              label={messages.company}
              required
              error={
                fieldErrors.company ? messageForCode(fieldErrors.company, messages) : undefined
              }
            >
              <TextInput
                id="company"
                name="company"
                autoComplete="organization"
                required
                maxLength={160}
                invalid={Boolean(fieldErrors.company)}
                describedBy={fieldErrors.company ? 'company-error' : undefined}
              />
            </FormField>

            <FormField
              id="fleetSize"
              label={messages.fleet}
              required
              error={
                fieldErrors.fleetSize ? messageForCode(fieldErrors.fleetSize, messages) : undefined
              }
            >
              <Select
                id="fleetSize"
                name="fleetSize"
                required
                defaultValue=""
                invalid={Boolean(fieldErrors.fleetSize)}
                describedBy={fieldErrors.fleetSize ? 'fleetSize-error' : undefined}
              >
                <option value="">{messages.fleetOptions[0]}</option>
                {fleetSizeValues.map((value, index) => (
                  <option key={value} value={value}>
                    {messages.fleetOptions[index + 1]}
                  </option>
                ))}
              </Select>
            </FormField>

            <FormField id="market" label={messages.market} optionalLabel={messages.optional}>
              <TextInput id="market" name="market" autoComplete="country-name" maxLength={100} />
            </FormField>

            <FormField
              id="preferredLanguage"
              label={messages.language}
              optionalLabel={messages.optional}
            >
              <Select id="preferredLanguage" name="preferredLanguage" defaultValue={locale}>
                {(['en', 'fr', 'ar'] as const).map((value, index) => (
                  <option key={value} value={value}>
                    {messages.langOptions[index]}
                  </option>
                ))}
              </Select>
            </FormField>

            <FormField
              id="message"
              label={messages.message}
              optionalLabel={messages.optional}
              supportingText={messages.messageHelp}
              className={styles.spanAll}
              error={
                fieldErrors.message ? messageForCode(fieldErrors.message, messages) : undefined
              }
            >
              <TextArea
                id="message"
                name="message"
                rows={5}
                maxLength={1000}
                invalid={Boolean(fieldErrors.message)}
                describedBy={fieldErrors.message ? 'message-help message-error' : 'message-help'}
                characterCount={{ current: messageLength, max: 1000, label: messages.messageCount }}
                onInput={(event) => setMessageLength(event.currentTarget.value.length)}
              />
            </FormField>
          </div>

          <div className={styles.honeypot} aria-hidden="true">
            <label htmlFor="website">Website</label>
            <input id="website" name="website" tabIndex={-1} autoComplete="off" />
          </div>

          <div className={styles.actions}>
            <Button
              id="demo-submit"
              type="submit"
              intent="conversion"
              loading={status === 'submitting'}
            >
              {status === 'submitting'
                ? messages.submitting
                : status === 'error'
                  ? messages.retry
                  : messages.submit}
            </Button>
            <Button
              type="button"
              intent="tertiary"
              disabled={status === 'submitting'}
              onClick={close}
            >
              {messages.close}
            </Button>
          </div>
          <LiveRegion politeness="polite">
            {status === 'submitting' ? messages.submitting : ''}
          </LiveRegion>
        </form>
      )}
    </Dialog>
  );
}
