import React, { useState, useEffect } from "react";
import { CheckIcon, HomeIcon, PlusIcon } from "lucide-react";
import { cn } from "@/lib/utils";
import { AddressAutocomplete } from "./form-primitives";
import { Button } from "./button";
import { Input } from "./input";
import { Slider } from "./slider";
import { Spinner } from "./spinner";
import { ToggleGroup, ToggleGroupItem } from "./toggle-group";
import {
  InputOTP,
  InputOTPGroup,
  InputOTPSeparator,
  InputOTPSlot,
} from "./input-otp";
import { FormField } from "./signup-form-primitives";

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

const fmt = (v: number) =>
  new Intl.NumberFormat("en-AU", {
    style: "currency",
    currency: "AUD",
    maximumFractionDigits: 0,
  }).format(v);

const GOAL_MIN = 50_000;
const GOAL_MAX = 4_000_000;
const GOAL_STEP = 10_000;

// ---------------------------------------------------------------------------
// Shared OTP verification — used by both the phone and email verify steps
// ---------------------------------------------------------------------------

const OTP_LENGTH = 6;
const RESEND_COUNTDOWN = 60;

/**
 * 6-digit OTP entry state plus the resend countdown. Auto-submits via
 * `onVerify` once all digits are entered; `restartTimer` restarts the
 * countdown when the user requests a new code.
 */
function useOtpTimer(countdown: number, onVerify?: (code: string) => void) {
  const [otp, setOtp] = useState("");
  const [timer, setTimer] = useState(countdown);

  useEffect(() => {
    if (timer <= 0) return;
    const id = setInterval(() => setTimer((t) => t - 1), 1000);
    return () => clearInterval(id);
  }, [timer]);

  const handleChange = (value: string) => {
    setOtp(value);
    if (value.length === OTP_LENGTH) onVerify?.(value);
  };

  const restartTimer = () => setTimer(RESEND_COUNTDOWN);

  return { otp, handleChange, timer, restartTimer };
}

/** The 6-slot OTP input with its inline error message. */
function OtpCodeFields({
  otp,
  onChange,
  disabled,
  error,
  className,
}: {
  otp: string;
  onChange: (value: string) => void;
  disabled?: boolean;
  error?: string;
  className?: string;
}) {
  const invalid = !!error || undefined;
  return (
    <div className={cn("flex flex-col gap-3", className)}>
      <InputOTP
        maxLength={OTP_LENGTH}
        value={otp}
        onChange={onChange}
        disabled={disabled}
        aria-label="6-digit verification code"
      >
        <InputOTPGroup>
          {[0, 1, 2].map((i) => (
            <InputOTPSlot key={i} index={i} aria-invalid={invalid} />
          ))}
        </InputOTPGroup>
        <InputOTPSeparator />
        <InputOTPGroup>
          {[3, 4, 5].map((i) => (
            <InputOTPSlot key={i} index={i} aria-invalid={invalid} />
          ))}
        </InputOTPGroup>
      </InputOTP>
      {error && (
        <p role="alert" className="text-body-small text-destructive">
          {error}
        </p>
      )}
    </div>
  );
}

/** "Verifying…" spinner while submitting, otherwise the resend prompt. */
function VerifyStatus({
  isLoading,
  timer,
  prompt,
  onResend,
}: {
  isLoading?: boolean;
  timer: number;
  prompt: string;
  onResend: () => void;
}) {
  if (isLoading) {
    return (
      <div
        role="status"
        aria-label="Verifying code"
        className="flex items-center gap-2 text-body-small text-muted-foreground"
      >
        <span aria-hidden="true">
          <Spinner className="size-4" />
        </span>
        Verifying…
      </div>
    );
  }
  return (
    <p className="text-body-small text-muted-foreground" aria-live="polite">
      {prompt}{" "}
      {timer > 0 ? (
        <span>Resend it in {timer}s</span>
      ) : (
        <Button
          variant="link"
          size="sm"
          className="h-auto p-0 text-body-small"
          onClick={onResend}
        >
          Resend it
        </Button>
      )}
    </p>
  );
}

// ---------------------------------------------------------------------------
// Step 2 — Phone Verification
// ---------------------------------------------------------------------------

export interface PhoneVerifyStepProps {
  phone?: string;
  countdown?: number;
  error?: string;
  isLoading?: boolean;
  onVerify?: (code: string) => void;
  onResend?: () => void;
}

export function PhoneVerifyStep({
  phone = "+61 412 345 789",
  countdown = 45,
  error = "",
  isLoading = false,
  onVerify,
  onResend,
}: PhoneVerifyStepProps) {
  const { otp, handleChange, timer, restartTimer } = useOtpTimer(
    countdown,
    onVerify,
  );

  const lastFour = phone.slice(-4);

  return (
    <div className="flex flex-col gap-6">
      <div className="flex flex-col gap-1">
        <p className="text-h3 text-foreground">We sent you a text.</p>
        <p className="text-body-small text-muted-foreground">
          Number we have ends in •••• {lastFour}.
        </p>
      </div>

      <OtpCodeFields
        otp={otp}
        onChange={handleChange}
        disabled={isLoading}
        error={error}
      />

      <VerifyStatus
        isLoading={isLoading}
        timer={timer}
        prompt="Didn't receive a code?"
        onResend={() => {
          restartTimer();
          onResend?.();
        }}
      />
    </div>
  );
}

// ---------------------------------------------------------------------------
// Step 2 (email variant) — Email Verification
// ---------------------------------------------------------------------------

/** Masks the local part of an email, e.g. "jamie@example.com" → "j***e@example.com". */
function maskEmail(email: string) {
  const [local, domain] = email.split("@");
  if (!domain || local.length <= 2) return email;
  return `${local[0]}***${local[local.length - 1]}@${domain}`;
}

export interface EmailVerifyStepProps {
  email?: string;
  countdown?: number;
  error?: string;
  isLoading?: boolean;
  onVerify?: (code: string) => void;
  onResend?: () => void;
}

export function EmailVerifyStep({
  email = "jamie@example.com",
  countdown = 45,
  error = "",
  isLoading = false,
  onVerify,
  onResend,
}: EmailVerifyStepProps) {
  const { otp, handleChange, timer, restartTimer } = useOtpTimer(
    countdown,
    onVerify,
  );

  return (
    <div className="flex flex-col items-center gap-6 text-center">
      <div className="flex flex-col gap-1">
        <p className="text-h5 text-foreground">We sent you an email.</p>
        <p className="text-body-small text-muted-foreground">
          Check {maskEmail(email)} for your verification code.
        </p>
      </div>

      <OtpCodeFields
        otp={otp}
        onChange={handleChange}
        disabled={isLoading}
        error={error}
        className="items-center"
      />

      <VerifyStatus
        isLoading={isLoading}
        timer={timer}
        prompt="Didn't receive an email?"
        onResend={() => {
          restartTimer();
          onResend?.();
        }}
      />
    </div>
  );
}

// ---------------------------------------------------------------------------
// Step 3 — Request Broker Access
// ---------------------------------------------------------------------------

export interface BrokerFormValues {
  firstName: string;
  lastName: string;
  email: string;
  phone: string;
}

export interface BrokerRequestStepProps {
  onValuesChange?: (values: BrokerFormValues) => void;
}

export function BrokerRequestStep({ onValuesChange }: BrokerRequestStepProps) {
  const [values, setValues] = useState<BrokerFormValues>({
    firstName: "",
    lastName: "",
    email: "",
    phone: "",
  });

  const update = (field: keyof BrokerFormValues, value: string) => {
    setValues((prev) => {
      const next = { ...prev, [field]: value };
      onValuesChange?.(next);
      return next;
    });
  };

  return (
    <div className="flex flex-col gap-6">
      <p className="text-body-small text-muted-foreground">
        You have access for the first 3 months covered by us. After this date
        you will need to be connected with a mortgage broker or financial
        planner to maintain access.
      </p>

      <div className="flex flex-col gap-4">
        <div className="flex gap-4">
          <FormField label="First Name">
            <Input
              id="broker-first-name"
              autoComplete="given-name"
              placeholder="First Name"
              value={values.firstName}
              onChange={(e) => update("firstName", e.target.value)}
            />
          </FormField>
          <FormField label="Last Name">
            <Input
              id="broker-last-name"
              autoComplete="family-name"
              placeholder="Last Name"
              value={values.lastName}
              onChange={(e) => update("lastName", e.target.value)}
            />
          </FormField>
        </div>
        <FormField label="Email Address">
          <Input
            id="broker-email"
            type="email"
            autoComplete="email"
            placeholder="Email Address"
            value={values.email}
            onChange={(e) => update("email", e.target.value)}
          />
        </FormField>
        <FormField label="Phone Number">
          <Input
            id="broker-phone"
            type="tel"
            autoComplete="tel"
            placeholder="Phone Number"
            value={values.phone}
            onChange={(e) => update("phone", e.target.value)}
          />
        </FormField>
      </div>
    </div>
  );
}

// ---------------------------------------------------------------------------
// Step 4 — Connect Bank
// ---------------------------------------------------------------------------

const BANKS = ["CBA", "ANZ", "NAB", "WBC", "MAC", "BOQ"];

export interface ConnectBankStepProps {
  onConnect?: () => void;
}

export function ConnectBankStep({ onConnect }: ConnectBankStepProps) {
  return (
    <div className="flex flex-col gap-6">
      <button
        type="button"
        aria-label="Connect your bank account"
        onClick={onConnect}
        className="flex flex-col gap-4 border border-border p-6 text-left transition-colors hover:border-primary/60"
      >
        <div className="grid grid-cols-3 gap-3" aria-hidden="true">
          {BANKS.map((abbr) => (
            <div
              key={abbr}
              className="flex h-14 items-center justify-center border border-border bg-muted/30"
            >
              <span className="text-label-medium text-foreground">{abbr}</span>
            </div>
          ))}
        </div>
        <div className="flex items-center justify-between">
          <span className="text-label-medium text-foreground">
            Connect Bank
          </span>
          <div
            aria-hidden="true"
            className="flex h-7 w-7 items-center justify-center bg-primary text-primary-foreground"
          >
            <PlusIcon className="size-4" />
          </div>
        </div>
      </button>
    </div>
  );
}

// ---------------------------------------------------------------------------
// Step 5 — Retrieve Bank Data (loading state)
// ---------------------------------------------------------------------------

export function RetrieveBankDataStep() {
  return (
    <div
      role="status"
      aria-label="Retrieving bank data"
      className="flex flex-col items-center justify-center gap-4 py-16 text-center"
    >
      <span aria-hidden="true">
        <Spinner className="size-10 text-primary" />
      </span>
      <div className="flex flex-col gap-1">
        <p className="text-label-large text-foreground">
          Retrieving your bank data…
        </p>
        <p className="text-body-small text-muted-foreground">
          This may take a few seconds. Please don&apos;t close this window.
        </p>
      </div>
    </div>
  );
}

// ---------------------------------------------------------------------------
// Step 6 — Connect Property
// ---------------------------------------------------------------------------

interface PropertyItem {
  id: string;
  address: string;
  suburb: string;
  state: string;
}

export interface ConnectPropertyStepProps {
  properties?: PropertyItem[];
  onAddProperty?: (address: string) => void;
  onCanProceedChange?: (can: boolean) => void;
  onGoalChange?: (value: number) => void;
}

export function ConnectPropertyStep({
  properties = [],
  onAddProperty,
  onCanProceedChange,
  onGoalChange,
}: ConnectPropertyStepProps) {
  const [hasProperty, setHasProperty] = useState<boolean | null>(null);
  const [addressValue, setAddressValue] = useState("");
  const [goalValue, setGoalValue] = useState(2_000_000);

  const canProceed =
    hasProperty === false || (hasProperty === true && properties.length > 0);

  useEffect(() => {
    onCanProceedChange?.(canProceed);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [canProceed]);

  const handleGoalChange = (v: number) => {
    setGoalValue(v);
    onGoalChange?.(v);
  };

  return (
    <div className="flex flex-col gap-6">
      <ToggleGroup
        type="single"
        variant="outline"
        aria-label="Do you own a property?"
        value={
          hasProperty === true ? ["yes"] : hasProperty === false ? ["no"] : []
        }
        onValueChange={(vals: readonly string[]) => {
          const val = vals[0];
          setHasProperty(val === "yes" ? true : val === "no" ? false : null);
        }}
        className="w-full"
      >
        <ToggleGroupItem value="yes" className="flex-1">
          Yes, I have a property
        </ToggleGroupItem>
        <ToggleGroupItem value="no" className="flex-1">
          No, I don&apos;t
        </ToggleGroupItem>
      </ToggleGroup>

      {hasProperty === true && (
        <>
          <AddressAutocomplete
            value={addressValue}
            onValueChange={setAddressValue}
            onSelect={(opt) => {
              onAddProperty?.(opt.label);
              setAddressValue("");
            }}
          />

          {properties.length > 0 && (
            <ul role="list" className="flex flex-col gap-2">
              {properties.map((p) => (
                <li
                  key={p.id}
                  className="flex items-center justify-between border border-border px-4 py-3"
                >
                  <div className="flex items-center gap-3">
                    <HomeIcon
                      aria-hidden="true"
                      className="size-4 shrink-0 text-muted-foreground"
                    />
                    <div>
                      <p className="text-label-medium text-foreground">
                        {p.address}
                      </p>
                      <p className="text-caption text-muted-foreground">
                        {p.suburb}, {p.state}
                      </p>
                    </div>
                  </div>
                  <CheckIcon
                    aria-hidden="true"
                    className="size-4 text-success"
                  />
                </li>
              ))}
            </ul>
          )}
        </>
      )}

      {hasProperty === false && (
        <div className="flex flex-col gap-4 border border-border p-6">
          <div className="flex flex-col gap-1">
            <p className="text-label-medium text-foreground">
              What&apos;s your property budget?
            </p>
            <p className="text-caption text-muted-foreground">
              Set your estimated buying goal to help us tailor your experience.
            </p>
          </div>
          <p
            aria-live="polite"
            className="tabular-nums text-h1 text-foreground"
          >
            {fmt(goalValue)}
          </p>
          <Slider
            min={GOAL_MIN}
            max={GOAL_MAX}
            step={GOAL_STEP}
            value={goalValue}
            onValueChange={handleGoalChange}
            aria-label="Property buying goal"
          />
          <div
            aria-hidden="true"
            className="flex justify-between text-caption text-muted-foreground"
          >
            <span>{fmt(GOAL_MIN)}</span>
            <span>{fmt(GOAL_MAX)}</span>
          </div>
        </div>
      )}
    </div>
  );
}

// ---------------------------------------------------------------------------
// BuyingGoalStep — standalone step (used in template stories)
// ---------------------------------------------------------------------------

export interface BuyingGoalStepProps {
  initialValue?: number;
  isLoading?: boolean;
  onConfirm?: (value: number) => void;
}

export function BuyingGoalStep({
  initialValue = 2_000_000,
  isLoading = false,
  onConfirm,
}: BuyingGoalStepProps) {
  const [value, setValue] = useState(initialValue);

  return (
    <div className="flex flex-col gap-8">
      <div className="flex flex-col gap-6 border border-border p-6">
        <div className="flex items-center justify-between">
          <p
            aria-live="polite"
            className="tabular-nums text-h1 text-foreground"
          >
            {fmt(value)}
          </p>
          <Button
            variant="default"
            onClick={() => onConfirm?.(value)}
            disabled={isLoading}
          >
            {isLoading ? (
              <>
                <span aria-hidden="true">
                  <Spinner className="size-4" />
                </span>
                Adding…
              </>
            ) : (
              "Confirm"
            )}
          </Button>
        </div>

        <Slider
          min={GOAL_MIN}
          max={GOAL_MAX}
          step={GOAL_STEP}
          value={value}
          onValueChange={(v) => setValue(v)}
          disabled={isLoading}
          aria-label="Buying goal"
        />

        <div
          aria-hidden="true"
          className="flex justify-between text-caption text-muted-foreground"
        >
          <span>{fmt(GOAL_MIN)}</span>
          <span>{fmt(GOAL_MAX)}</span>
        </div>
      </div>
    </div>
  );
}

// ---------------------------------------------------------------------------
// Step 7 — Success
// ---------------------------------------------------------------------------

export interface FrontendSuccessStepProps {
  firstName?: string;
  onGoToDashboard?: () => void;
}

export function FrontendSuccessStep({
  firstName = "Alex",
  onGoToDashboard,
}: FrontendSuccessStepProps) {
  return (
    <div className="flex min-h-full flex-col items-center justify-center gap-6 px-4 py-16 text-center">
      <div
        aria-hidden="true"
        className="flex size-16 items-center justify-center bg-success/10"
      >
        <CheckIcon className="size-8 text-success" strokeWidth={2} />
      </div>

      <div className="flex flex-col gap-2">
        <h2 className="text-h3 text-foreground">
          You&apos;re all set, {firstName}!
        </h2>
        <p className="max-w-[360px] text-body-small text-muted-foreground">
          Your account is ready. Head to your dashboard to explore your
          financial overview and next steps.
        </p>
      </div>

      <Button variant="default" size="lg" onClick={onGoToDashboard}>
        Go to Dashboard
      </Button>
    </div>
  );
}
