"use client";

// components/flow/RegisterStep.tsx
// Screen A: minimal registration (ux.md 2 Screen A). Three fields in order
// (nombre, celular, correo) with the correct inputMode + autocomplete, then the
// consent block: ONE mandatory unticked data-processing checkbox (Ley 29733,
// legal.md 2), a SEPARATE terms checkbox, and a THIRD optional marketing
// checkbox. None pre-checked. The Turnstile widget (agent G) gates submission.
//
// The base chance is pre-set to 1 server-side; this screen does not pick a
// quantity (the upsell does). The CTA stays disabled until required fields
// validate AND the mandatory consent is checked AND Turnstile returns a token,
// and the disabled reason is stated in TEXT (not color), per WCAG.

import * as React from "react";
import { Button, Checkbox, Input, TextSwap } from "@/components/ui";
import { Turnstile } from "@/components/Turnstile";
import { useErrorShake } from "./useErrorShake";
import type { FlowRaffle, RegisterDraft } from "./types";
import {
  hasErrors,
  validateRegister,
  type RegisterErrors,
} from "./validation";

export interface RegisterStepProps {
  raffle: FlowRaffle;
  /** Preserved input so the user never retypes when navigating back. */
  initial: RegisterDraft;
  submitting: boolean;
  /** Server error surfaced from POST /api/register (Spanish, from the envelope). */
  serverError?: string | null;
  onSubmit: (draft: RegisterDraft, turnstileToken: string) => void;
}

export function RegisterStep({
  raffle,
  initial,
  submitting,
  serverError,
  onSubmit,
}: RegisterStepProps) {
  const [draft, setDraft] = React.useState<RegisterDraft>(initial);
  const [touched, setTouched] = React.useState<Record<string, boolean>>({});
  const [submitAttempted, setSubmitAttempted] = React.useState(false);
  const [turnstileToken, setTurnstileToken] = React.useState<string>("");
  const [turnstileFailed, setTurnstileFailed] = React.useState(false);
  // Jolt the server-error alert when it appears (a "try again" hint).
  const serverErrorRef = useErrorShake<HTMLParagraphElement>(serverError);

  const errors: RegisterErrors = validateRegister(draft);
  const formInvalid = hasErrors(errors);
  const canSubmit = !formInvalid && Boolean(turnstileToken) && !submitting;

  function showError(field: keyof RegisterErrors): string | undefined {
    if (!touched[field] && !submitAttempted) return undefined;
    return errors[field];
  }

  function update<K extends keyof RegisterDraft>(key: K, value: RegisterDraft[K]) {
    setDraft((d) => ({ ...d, [key]: value }));
  }

  function blur(field: string) {
    setTouched((t) => ({ ...t, [field]: true }));
  }

  function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    setSubmitAttempted(true);
    if (!canSubmit) return;
    onSubmit(draft, turnstileToken);
  }

  // The single, text-stated reason the CTA is disabled (never color-only).
  let disabledReason: string | null = null;
  if (formInvalid) {
    disabledReason = "Completa tus datos y marca la autorización para continuar.";
  } else if (!turnstileToken) {
    disabledReason = turnstileFailed
      ? "No pudimos verificar que eres una persona. Recarga la página e intenta de nuevo."
      : "Estamos verificando que eres una persona. Espera un momento.";
  }

  return (
    <form noValidate onSubmit={handleSubmit} className="flex flex-col gap-md">
      <div className="flex flex-col gap-1">
        <h1 className="font-display text-heading-lg text-ink-strong">
          Inscríbete en la rifa
        </h1>
        <p className="font-body text-body-md text-muted">
          Pon tus datos. Te toma segundos y ya entras con 1 chance.
        </p>
      </div>

      <fieldset className="flex flex-col gap-md border-0 p-0 m-0">
        <legend className="sr-only">Tus datos</legend>

        <Input
          label="Nombre completo"
          name="fullName"
          type="text"
          autoComplete="name"
          autoCapitalize="words"
          enterKeyHint="next"
          required
          value={draft.fullName}
          error={showError("fullName")}
          onChange={(e) => update("fullName", e.target.value)}
          onBlur={() => blur("fullName")}
        />

        <Input
          label="Celular"
          name="phone"
          type="tel"
          inputMode="tel"
          autoComplete="tel"
          enterKeyHint="next"
          placeholder="987 654 321"
          required
          hint="Número de 9 dígitos. Lo usamos para confirmarte si ganas."
          value={draft.phone}
          error={showError("phone")}
          onChange={(e) => update("phone", e.target.value)}
          onBlur={() => blur("phone")}
        />

        <Input
          label="Correo"
          name="email"
          type="email"
          inputMode="email"
          autoComplete="email"
          autoCapitalize="none"
          enterKeyHint="done"
          placeholder="nombre@correo.com"
          required
          hint="Aquí te llega la confirmación de tu inscripción."
          value={draft.email}
          error={showError("email")}
          onChange={(e) => update("email", e.target.value)}
          onBlur={() => blur("email")}
        />
      </fieldset>

      <fieldset className="flex flex-col gap-md border-0 p-0 m-0">
        <legend className="font-body text-body-md font-medium text-ink-strong">
          Autorizaciones
        </legend>

        {/* (1) Mandatory, unticked, UNBUNDLED data-processing consent (Ley
            29733). Separate from the terms checkbox below; never pre-checked. */}
        <Checkbox
          name="dataConsent"
          required
          checked={draft.dataConsent}
          error={showError("dataConsent")}
          onChange={(e) => {
            update("dataConsent", e.target.checked);
            blur("dataConsent");
          }}
          label={
            <span>
              Autorizo el tratamiento de mis datos personales para participar en
              la rifa, según la{" "}
              <a
                href="/privacidad"
                target="_blank"
                rel="noopener noreferrer"
                className="text-steelblue underline"
              >
                política de privacidad
              </a>
              .
            </span>
          }
        />

        {/* (2) Mandatory, unticked acceptance of the official bases (terms),
            tracked INDEPENDENTLY from the data consent above. */}
        <Checkbox
          name="termsAccepted"
          required
          checked={draft.termsAccepted}
          error={showError("termsAccepted")}
          onChange={(e) => {
            update("termsAccepted", e.target.checked);
            blur("termsAccepted");
          }}
          label={
            <span>
              He leído y acepto las{" "}
              <a
                href={raffle.basesUrl ?? "/bases"}
                target="_blank"
                rel="noopener noreferrer"
                className="text-steelblue underline"
              >
                bases del sorteo
              </a>
              .
            </span>
          }
        />

        {/* (3) Optional, separate, unticked marketing consent. Never bundled. */}
        <Checkbox
          name="marketingConsent"
          checked={draft.marketingConsent}
          onChange={(e) => update("marketingConsent", e.target.checked)}
          label="Quiero recibir novedades de Teletón por correo. (Opcional)"
        />
      </fieldset>

      <div className="flex flex-col gap-2">
        {/* Agent G's Turnstile reads its site key from
            NEXT_PUBLIC_TURNSTILE_SITE_KEY itself; we only consume the token. It
            surfaces expiry + errors through onExpire (token cleared), so a
            cleared token re-disables the CTA with a text reason. */}
        <Turnstile
          action="register"
          onVerify={(token: string) => {
            setTurnstileToken(token);
            setTurnstileFailed(false);
          }}
          onExpire={() => {
            setTurnstileToken("");
            setTurnstileFailed(true);
          }}
        />
      </div>

      {serverError ? (
        <p
          ref={serverErrorRef}
          role="alert"
          className="t-shake font-body text-body-md text-primary"
        >
          {serverError}
        </p>
      ) : null}

      <div className="flex flex-col gap-2">
        <Button type="submit" size="lg" block disabled={!canSubmit}>
          <TextSwap>{submitting ? "Inscribiendo..." : "Continuar"}</TextSwap>
        </Button>
        {disabledReason ? (
          <p className="font-body text-caption text-muted-label">
            {disabledReason}
          </p>
        ) : null}
      </div>
    </form>
  );
}
