"use client";

// components/flow/ReviewStep.tsx
// Screen C: Review and pay (ux.md 2 Screen C). A plain summary card (chances,
// total, name + contact for confirmation, honest odds line), the OPT-IN
// "cubre la comision" toggle (OFF by default, never a dark pattern), and the
// Yape pay panel (Niubiz is the only payment provider, Yape-only).
//
// The amount on the pay button is the SERVER-RETURNED total when an order
// exists; before the order is created it is a preview clearly labeled as such,
// so there is never a surprise on the provider screen. The client never
// computes the authoritative price.

import * as React from "react";
import { Button, Card, PopInNumber, TextSwap } from "@/components/ui";
import { formatPEN } from "@/lib/money";
import { formatReceiptDate } from "./api";
import { useErrorShake } from "./useErrorShake";
import {
  previewForTier,
  type FlowRaffle,
  type PublicPricingTier,
  type RegisterDraft,
} from "./types";

export interface ReviewStepProps {
  raffle: FlowRaffle;
  draft: RegisterDraft;
  selectedTier: PublicPricingTier | null;
  feeOptIn: boolean;
  onToggleFee: (next: boolean) => void;
  /** Server-authoritative total once the order exists; otherwise null. */
  serverAmountCents: number | null;
  serverChances: number | null;
  paying: boolean;
  serverError?: string | null;
  /** Mandatory Niubiz denied-transaction receipt fields, shown with serverError. */
  serverErrorMeta?: { purchaseNumber: string; transactionDate: string } | null;
  onBack: () => void;
  onPay: () => void;
  yapePhone?: string;
  yapeOtp?: string;
  onYapePhoneChange?: (v: string) => void;
  onYapeOtpChange?: (v: string) => void;
}

export function ReviewStep({
  raffle,
  draft,
  selectedTier,
  feeOptIn,
  onToggleFee,
  serverAmountCents,
  serverChances,
  paying,
  serverError,
  serverErrorMeta,
  onBack,
  onPay,
  yapePhone = "",
  yapeOtp = "",
  onYapePhoneChange,
  onYapeOtpChange,
}: ReviewStepProps) {
  const preview = previewForTier(raffle.basePriceCents, selectedTier, feeOptIn);
  const chances = serverChances ?? preview.chances;
  const amountCents = serverAmountCents ?? preview.amountCents;
  const isServerTotal = serverAmountCents !== null;
  // Jolt the payment-error alert when it appears (a "try again" hint).
  const serverErrorRef = useErrorShake<HTMLParagraphElement>(serverError);

  return (
    <div className="flex flex-col gap-md">
      <h1 className="font-display text-heading-lg text-ink-strong">
        Revisa y paga
      </h1>

      <Card elevation="tight" as="section" aria-label="Resumen de tu inscripción">
        <dl className="flex flex-col gap-3">
          <Row term="Evento" value={raffle.name} />
          <Row
            term="Chances"
            value={
              <PopInNumber
                value={`${chances} ${chances === 1 ? "chance" : "chances"}`}
              />
            }
          />
          <Row term="Nombre" value={draft.fullName} />
          <Row term="Correo" value={draft.email} />
          <Row term="Celular" value={draft.phone} />
          <div className="border-t border-hairline pt-3">
            <Row
              term="Total a pagar"
              value={<PopInNumber value={formatPEN(amountCents)} />}
              emphasize
            />
          </div>
        </dl>
        <p className="mt-3 font-body text-caption text-muted-label">
          Más chances significa más posibilidades de ganar. Ganar nunca está
          garantizado.
        </p>
      </Card>

      {raffle.feeOptInEnabled ? (
        <FeeToggle checked={feeOptIn} onChange={onToggleFee} />
      ) : null}

      {/* Niubiz Yape: collect the buyer's phone + codigo de aprobacion. */}
      <YapePanel
        phone={yapePhone}
        otp={yapeOtp}
        onPhoneChange={onYapePhoneChange}
        onOtpChange={onYapeOtpChange}
        disabled={paying}
      />

      {/* Reassurance row. */}
      <p className="font-body text-caption text-muted-label">
        Pago seguro con Yape procesado por Niubiz. No compartas tu código con
        nadie más.
      </p>
      <p className="font-body text-caption text-muted-label">
        Pago seguro. Sorteo supervisado.{" "}
        <a
          href={raffle.basesUrl ?? "/bases"}
          target="_blank"
          rel="noopener noreferrer"
          className="text-steelblue underline"
        >
          Ver las bases
        </a>
        .
      </p>

      {serverError ? (
        <div className="flex flex-col gap-1">
          <p
            ref={serverErrorRef}
            role="alert"
            className="t-shake font-body text-body-md text-primary"
          >
            {serverError}
          </p>
          {serverErrorMeta ? (
            <dl className="flex flex-col gap-0.5 font-body text-caption text-muted-label">
              <div className="flex justify-between gap-2">
                <dt>Número de pedido</dt>
                <dd>{serverErrorMeta.purchaseNumber}</dd>
              </div>
              <div className="flex justify-between gap-2">
                <dt>Fecha y hora</dt>
                <dd>{formatReceiptDate(serverErrorMeta.transactionDate)}</dd>
              </div>
            </dl>
          ) : null}
        </div>
      ) : null}

      <div className="flex flex-col gap-2">
        <Button
          type="button"
          size="lg"
          block
          onClick={onPay}
          disabled={paying}
          aria-busy={paying}
        >
          <TextSwap>
            {paying ? "Confirmando tu Yape..." : `Pagar ${formatPEN(amountCents)} con Yape`}
          </TextSwap>
        </Button>
        {!isServerTotal ? (
          <p className="font-body text-caption text-muted-label">
            El monto final se confirma al abrir el pago.
          </p>
        ) : null}
        <Button type="button" variant="ghost" block onClick={onBack} disabled={paying}>
          Volver
        </Button>
      </div>
    </div>
  );
}

function Row({
  term,
  value,
  emphasize,
}: {
  term: string;
  value: React.ReactNode;
  emphasize?: boolean;
}) {
  return (
    <div className="flex items-baseline justify-between gap-4">
      <dt className="font-body text-body-md text-muted-label">{term}</dt>
      <dd
        className={[
          "text-right font-body",
          emphasize
            ? "text-heading-md font-bold text-primary"
            : "text-body-md font-medium text-ink-strong",
        ].join(" ")}
      >
        {value}
      </dd>
    </div>
  );
}

function FeeToggle({
  checked,
  onChange,
}: {
  checked: boolean;
  onChange: (next: boolean) => void;
}) {
  return (
    <label
      htmlFor="fee-opt-in"
      className="flex cursor-pointer items-start gap-3 rounded-lg border border-hairline p-4 min-h-[44px]"
    >
      <input
        type="checkbox"
        id="fee-opt-in"
        name="feeOptIn"
        checked={checked}
        onChange={(e) => onChange(e.target.checked)}
        className="mt-0.5 h-6 w-6 shrink-0 rounded-sm accent-[var(--brand-primary)] focus-visible:outline focus-visible:outline-[3px] focus-visible:outline-offset-2 focus-visible:outline-steelblue"
      />
      <span className="font-body text-body-md text-ink-strong leading-snug">
        Suma S/1 para cubrir la comisión y que el 100 por ciento de tu aporte
        llegue a Teletón.
      </span>
    </label>
  );
}

/**
 * Yape-only payment surface (Niubiz "codigo de aprobacion" rail). The buyer pays
 * inside their own Yape app and proves it by entering their Yape phone number plus
 * the single-use 6-digit codigo de aprobacion (Yape app menu -> Codigo de
 * aprobacion; it rotates every ~2 minutes and works for one purchase). The server
 * runs the authorization with the server-locked amount and mints on approval.
 */
function YapePanel({
  phone,
  otp,
  onPhoneChange,
  onOtpChange,
  disabled,
}: {
  phone: string;
  otp: string;
  onPhoneChange?: (v: string) => void;
  onOtpChange?: (v: string) => void;
  disabled: boolean;
}) {
  const fieldClass =
    "h-12 w-full rounded-lg border-2 border-track bg-canvas px-4 font-body text-body-lg text-ink-strong tabular-nums tracking-wide focus:border-primary focus-visible:outline focus-visible:outline-[3px] focus-visible:outline-offset-2 focus-visible:outline-steelblue";
  // Pre-filled from registration upstream, so the buyer normally only fills the codigo.
  const phonePrefilled = phone.trim().length > 0;
  return (
    <section
      aria-label="Pago con Yape"
      className="flex flex-col gap-3 rounded-lg border-2 border-primary/30 bg-primary/5 p-4"
    >
      <h2 className="font-body text-heading-md font-bold text-ink-strong">Paga con Yape</h2>
      <ol className="flex list-decimal flex-col gap-1 pl-5 font-body text-caption text-muted">
        <li>Abre Yape, entra al menú y toca Código de aprobación.</li>
        <li>Copia el código de 6 dígitos. Dura 2 minutos y es de un solo uso.</li>
        <li>Pégalo aquí abajo y toca Pagar.</li>
      </ol>

      <label htmlFor="yape-phone" className="flex flex-col gap-1">
        <span className="font-body text-body-md font-medium text-ink-strong">
          Tu número de Yape
        </span>
        <input
          id="yape-phone"
          name="yapePhone"
          type="tel"
          inputMode="numeric"
          autoComplete="tel-national"
          maxLength={9}
          placeholder="9XXXXXXXX"
          value={phone}
          disabled={disabled}
          onChange={(e) => onPhoneChange?.(e.target.value.replace(/\D/g, "").slice(0, 9))}
          className={fieldClass}
        />
        {phonePrefilled ? (
          <span className="font-body text-caption text-muted-label">
            Lo tomamos de tu inscripción. Edítalo solo si pagas desde otro Yape.
          </span>
        ) : null}
      </label>

      <label htmlFor="yape-otp" className="flex flex-col gap-1">
        <span className="font-body text-body-md font-medium text-ink-strong">
          Código de aprobación
        </span>
        <input
          id="yape-otp"
          name="yapeOtp"
          type="text"
          inputMode="numeric"
          autoComplete="one-time-code"
          maxLength={6}
          placeholder="6 dígitos"
          value={otp}
          disabled={disabled}
          onChange={(e) => onOtpChange?.(e.target.value.replace(/\D/g, "").slice(0, 6))}
          className={fieldClass}
        />
        <span className="font-body text-caption text-muted-label">
          Es el único dato que copias de tu app de Yape.
        </span>
      </label>

      <p className="font-body text-caption text-muted-label">
        Necesitas tener activado Compras por Internet en Yape (Ajustes). El máximo
        por día es S/2,000.
      </p>
    </section>
  );
}

