"use client";

import { useState, useCallback } from "react";
import {
  Alert,
  Button,
  Description,
  Input,
  InputGroup,
  Label,
  Spinner,
  TextField,
} from "@heroui/react";
import type { AddressFormData } from "@/lib/checkout/types";

const UK_POSTCODE_REGEX = /^[A-Z]{1,2}\d[A-Z\d]?\s?\d[A-Z]{2}$/i;

type AddressFormProps = {
  initialData?: AddressFormData;
  onSubmit: (data: AddressFormData) => void;
  onCancel?: () => void;
  isSubmitting: boolean;
  validationError?: string | null;
};

type FieldErrors = Partial<Record<keyof AddressFormData, string>>;

export function AddressForm({
  initialData,
  onSubmit,
  onCancel,
  isSubmitting,
  validationError,
}: AddressFormProps) {
  const [firstName, setFirstName] = useState(initialData?.firstName ?? "");
  const [lastName, setLastName] = useState(initialData?.lastName ?? "");
  const [phone, setPhone] = useState(initialData?.phone ?? "");
  const [addressLine1, setAddressLine1] = useState(initialData?.addressLine1 ?? "");
  const [additionalInformation, setAdditionalInformation] = useState(
    initialData?.additionalInformation ?? "",
  );
  const [city, setCity] = useState(initialData?.city ?? "");
  const [postalCode, setPostalCode] = useState(initialData?.postalCode ?? "");
  const [errors, setErrors] = useState<FieldErrors>({});

  const validateForm = useCallback((): boolean => {
    const next: FieldErrors = {};

    if (!firstName.trim()) next.firstName = "First name is required";
    if (!lastName.trim()) next.lastName = "Last name is required";
    if (!phone.trim()) next.phone = "Phone number is required";
    if (!addressLine1.trim()) next.addressLine1 = "Address is required";
    if (!city.trim()) next.city = "City / Town is required";
    if (!postalCode.trim()) {
      next.postalCode = "Postcode is required";
    } else if (!UK_POSTCODE_REGEX.test(postalCode.trim())) {
      next.postalCode = "Enter a valid UK postcode (e.g. SW1A 2AA)";
    }

    setErrors(next);
    return Object.keys(next).length === 0;
  }, [firstName, lastName, phone, addressLine1, city, postalCode]);

  const handleSubmit = useCallback(
    (e: React.FormEvent) => {
      e.preventDefault();
      if (!validateForm()) return;

      onSubmit({
        firstName: firstName.trim(),
        lastName: lastName.trim(),
        phone: phone.trim(),
        addressLine1: addressLine1.trim(),
        additionalInformation: additionalInformation.trim() || undefined,
        city: city.trim(),
        postalCode: postalCode.trim().toUpperCase(),
        country: "GB",
      });
    },
    [validateForm, onSubmit, firstName, lastName, phone, addressLine1, additionalInformation, city, postalCode],
  );

  return (
    <form onSubmit={handleSubmit} className="flex flex-col gap-4" noValidate>
      {validationError && (
        <Alert status="danger" role="alert">
          <Alert.Indicator />
          <Alert.Content>
            <Alert.Title>Validation error</Alert.Title>
            <Alert.Description>{validationError}</Alert.Description>
          </Alert.Content>
        </Alert>
      )}

      {/* First name + Last name — stacked on mobile, side-by-side on md: */}
      <div className="grid grid-cols-1 gap-4 md:grid-cols-2">
        <div className="flex flex-col gap-1">
          <Label htmlFor="addr-firstName">First name</Label>
          <Input
            id="addr-firstName"
            name="firstName"
            value={firstName}
            onChange={(e) => setFirstName(e.target.value)}
            placeholder="Jane"
            required
            autoComplete="given-name"
            disabled={isSubmitting}
            aria-required="true"
            aria-invalid={!!errors.firstName || undefined}
            aria-describedby={errors.firstName ? "addr-firstName-err" : undefined}
          />
          {errors.firstName && (
            <p id="addr-firstName-err" className="text-xs text-danger">
              {errors.firstName}
            </p>
          )}
        </div>

        <div className="flex flex-col gap-1">
          <Label htmlFor="addr-lastName">Last name</Label>
          <Input
            id="addr-lastName"
            name="lastName"
            value={lastName}
            onChange={(e) => setLastName(e.target.value)}
            placeholder="Doe"
            required
            autoComplete="family-name"
            disabled={isSubmitting}
            aria-required="true"
            aria-invalid={!!errors.lastName || undefined}
            aria-describedby={errors.lastName ? "addr-lastName-err" : undefined}
          />
          {errors.lastName && (
            <p id="addr-lastName-err" className="text-xs text-danger">
              {errors.lastName}
            </p>
          )}
        </div>
      </div>

      {/* Phone with +44 prefix */}
      <div className="flex flex-col gap-1">
        <TextField name="phone" isRequired isDisabled={isSubmitting}>
          <Label htmlFor="addr-phone">Phone</Label>
          <InputGroup>
            <InputGroup.Prefix>+44</InputGroup.Prefix>
            <InputGroup.Input
              id="addr-phone"
              type="tel"
              value={phone}
              onChange={(e: React.ChangeEvent<HTMLInputElement>) => setPhone(e.target.value)}
              placeholder="7911 123456"
              autoComplete="tel-national"
              aria-required="true"
              aria-invalid={!!errors.phone || undefined}
              aria-describedby={
                [errors.phone ? "addr-phone-err" : null, "addr-phone-desc"]
                  .filter(Boolean)
                  .join(" ") || undefined
              }
            />
          </InputGroup>
          <Description id="addr-phone-desc">
            We will only use this to contact you about your order
          </Description>
        </TextField>
        {errors.phone && (
          <p id="addr-phone-err" className="text-xs text-danger">
            {errors.phone}
          </p>
        )}
      </div>

      {/* Address */}
      <div className="flex flex-col gap-1">
        <Label htmlFor="addr-line1">Address</Label>
        <Input
          id="addr-line1"
          name="addressLine1"
          value={addressLine1}
          onChange={(e) => setAddressLine1(e.target.value)}
          placeholder="10 Downing Street"
          required
          autoComplete="address-line1"
          disabled={isSubmitting}
          aria-required="true"
          aria-invalid={!!errors.addressLine1 || undefined}
          aria-describedby={errors.addressLine1 ? "addr-line1-err" : undefined}
        />
        {errors.addressLine1 && (
          <p id="addr-line1-err" className="text-xs text-danger">
            {errors.addressLine1}
          </p>
        )}
      </div>

      {/* Additional information (optional) */}
      <div className="flex flex-col gap-1">
        <Label htmlFor="addr-additional">
          Apartment, suite, floor, unit, etc. <span className="text-default-400">(optional)</span>
        </Label>
        <Input
          id="addr-additional"
          name="additionalInformation"
          value={additionalInformation}
          onChange={(e) => setAdditionalInformation(e.target.value)}
          placeholder="Flat 4B"
          autoComplete="address-line2"
          disabled={isSubmitting}
        />
      </div>

      {/* City / Town + Postcode — stacked on mobile, side-by-side on md: */}
      <div className="grid grid-cols-1 gap-4 md:grid-cols-2">
        <div className="flex flex-col gap-1">
          <Label htmlFor="addr-city">City / Town</Label>
          <Input
            id="addr-city"
            name="city"
            value={city}
            onChange={(e) => setCity(e.target.value)}
            placeholder="London"
            required
            autoComplete="address-level2"
            disabled={isSubmitting}
            aria-required="true"
            aria-invalid={!!errors.city || undefined}
            aria-describedby={errors.city ? "addr-city-err" : undefined}
          />
          {errors.city && (
            <p id="addr-city-err" className="text-xs text-danger">
              {errors.city}
            </p>
          )}
        </div>

        <div className="flex flex-col gap-1">
          <Label htmlFor="addr-postcode">Postcode</Label>
          <Input
            id="addr-postcode"
            name="postalCode"
            value={postalCode}
            onChange={(e) => setPostalCode(e.target.value)}
            placeholder="SW1A 2AA"
            required
            autoComplete="postal-code"
            disabled={isSubmitting}
            aria-required="true"
            aria-invalid={!!errors.postalCode || undefined}
            aria-describedby={errors.postalCode ? "addr-postcode-err" : undefined}
          />
          {errors.postalCode && (
            <p id="addr-postcode-err" className="text-xs text-danger">
              {errors.postalCode}
            </p>
          )}
        </div>
      </div>

      {/* Country (UK only) */}
      <div className="flex flex-col gap-1">
        <Label htmlFor="addr-country">Country</Label>
        <Input
          id="addr-country"
          name="country"
          value="United Kingdom"
          readOnly
          disabled
          aria-describedby="addr-country-note"
        />
        <p id="addr-country-note" className="text-xs text-default-400">
          We currently ship to the United Kingdom only.
        </p>
      </div>

      {/* Actions */}
      <div className="flex flex-col gap-2 pt-2 md:flex-row md:justify-end">
        {onCancel && (
          <Button
            variant="ghost"
            className="w-full md:w-auto"
            onPress={onCancel}
            isDisabled={isSubmitting}
          >
            Cancel
          </Button>
        )}
        <Button
          type="submit"
          variant="primary"
          className="w-full bg-[#236f6b] font-medium text-white md:w-auto"
          isDisabled={isSubmitting}
          isPending={isSubmitting}
        >
          {({ isPending }) => (
            <>
              {isPending ? <Spinner color="current" size="sm" /> : null}
              Validate &amp; save address
            </>
          )}
        </Button>
      </div>
    </form>
  );
}
