"use client";

/**
 * ZipCodeInput - Japanese ZIP code input with auto-lookup
 *
 * Handles ZIP code formatting (XXX-XXXX) and triggers address lookup
 * when a valid 7-digit ZIP code is entered.
 */

import { useCallback, useEffect, useState } from "react";
import { Search, Loader2, CheckCircle, XCircle } from "lucide-react";
import { Input } from "@/components/atoms";
import { FormField } from "@/components/molecules/FormField/FormField";
import { cn } from "@/shared/utils";
import { formatJapanesePostalCode } from "@/shared/constants";
import { useZipCodeLookup } from "../hooks";
import type { JapanPostAddress } from "@customer-portal/domain/address";

type LookupResult = { count: number; addresses: JapanPostAddress[] } | undefined;

function getStatusIcon(isLoading: boolean, isValidFormat: boolean, lookupResult: LookupResult) {
  if (isLoading) return <Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />;
  if (isValidFormat && lookupResult) {
    return lookupResult.count > 0 ? (
      <CheckCircle className="h-4 w-4 text-success" />
    ) : (
      <XCircle className="h-4 w-4 text-warning" />
    );
  }
  return <Search className="h-4 w-4 text-muted-foreground" />;
}

function getComputedHelperText({
  isLoading,
  isError,
  lookupError,
  isValidFormat,
  lookupResult,
  helperText,
}: {
  isLoading: boolean;
  isError: boolean;
  lookupError: Error | null;
  isValidFormat: boolean;
  lookupResult: LookupResult;
  helperText: string;
}) {
  if (isLoading) return "Looking up address...";
  if (isError && lookupError) return "Something went wrong. Please try again or contact support.";
  if (isValidFormat && lookupResult) {
    if (lookupResult.count === 0) return "No address found. Please check your ZIP code.";
    if (lookupResult.count === 1) return "Address found!";
    return `Found ${lookupResult.count} addresses`;
  }
  return helperText;
}

function useZipCodeDisplayState({
  isLoading,
  isError,
  lookupError,
  isValidFormat,
  lookupResult,
  helperText,
}: {
  isLoading: boolean;
  isError: boolean;
  lookupError: Error | null;
  isValidFormat: boolean;
  lookupResult: LookupResult;
  helperText: string;
}) {
  const statusIcon = getStatusIcon(isLoading, isValidFormat, lookupResult);
  const computedHelperText = getComputedHelperText({
    isLoading,
    isError,
    lookupError,
    isValidFormat,
    lookupResult,
    helperText,
  });
  const hasLookupSuccess = isValidFormat && lookupResult && lookupResult.count > 0;
  const hasLookupWarning = isValidFormat && lookupResult && lookupResult.count === 0;
  return { statusIcon, computedHelperText, hasLookupSuccess, hasLookupWarning };
}

export interface ZipCodeInputProps {
  /** Current ZIP code value */
  value: string;
  /** Called when ZIP code changes */
  onChange: (value: string) => void;
  /** Called when address is found from ZIP lookup */
  onAddressFound?: ((address: JapanPostAddress) => void) | undefined;
  /** Called when lookup completes (found or not found) */
  onLookupComplete?: ((found: boolean, addresses: JapanPostAddress[]) => void) | undefined;
  /** Field error message */
  error?: string | undefined;
  /** Whether the field is required */
  required?: boolean | undefined;
  /** Whether the input is disabled */
  disabled?: boolean | undefined;
  /** Auto-focus the input */
  autoFocus?: boolean | undefined;
  /** Custom label */
  label?: string | undefined;
  /** Helper text below input */
  helperText?: string | undefined;
  /** Whether to auto-trigger lookup on valid ZIP */
  autoLookup?: boolean | undefined;
  /** Debounce delay for auto-lookup (ms) */
  debounceMs?: number | undefined;
}

export function ZipCodeInput({
  value,
  onChange,
  onAddressFound,
  onLookupComplete,
  error,
  required = true,
  disabled = false,
  autoFocus = false,
  label = "Postal Code",
  helperText = "Format: XXX-XXXX",
  autoLookup = true,
  debounceMs = 500,
}: ZipCodeInputProps) {
  // Track debounced ZIP code for lookup
  const [debouncedZip, setDebouncedZip] = useState<string>("");

  // ZIP code lookup hook
  const {
    data: lookupResult,
    isLoading,
    isError,
    error: lookupError,
  } = useZipCodeLookup(autoLookup ? debouncedZip : undefined);

  // Normalize ZIP code (remove hyphen) for validation
  const normalizedZip = value.replace(/-/g, "");
  const isValidFormat = /^\d{7}$/.test(normalizedZip);

  // Handle input change with formatting
  const handleChange = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      const formatted = formatJapanesePostalCode(e.target.value);
      onChange(formatted);
    },
    [onChange]
  );

  // Debounce ZIP code for auto-lookup
  useEffect(() => {
    if (!autoLookup || !isValidFormat) {
      setDebouncedZip("");
      return;
    }

    const timer = setTimeout(() => {
      setDebouncedZip(normalizedZip);
    }, debounceMs);

    return () => clearTimeout(timer);
  }, [normalizedZip, isValidFormat, autoLookup, debounceMs]);

  // Handle lookup result
  useEffect(() => {
    if (!lookupResult) return;

    const addresses = lookupResult.addresses;
    const hasAddresses = addresses.length > 0;

    // Notify parent of lookup completion
    onLookupComplete?.(hasAddresses, addresses);

    // If addresses found, notify with first result
    if (hasAddresses && addresses[0]) {
      onAddressFound?.(addresses[0]);
    }
  }, [lookupResult, onAddressFound, onLookupComplete]);

  const { statusIcon, computedHelperText, hasLookupSuccess, hasLookupWarning } =
    useZipCodeDisplayState({
      isLoading,
      isError,
      lookupError,
      isValidFormat,
      lookupResult,
      helperText,
    });

  return (
    <FormField
      label={label}
      error={error}
      required={required}
      helperText={error ? undefined : computedHelperText}
    >
      <div className="relative">
        <Input
          type="text"
          inputMode="numeric"
          value={value}
          onChange={handleChange}
          placeholder="100-0001"
          autoComplete="postal-code"
          maxLength={8}
          disabled={disabled}
          autoFocus={autoFocus}
          className={cn(
            "pr-10",
            hasLookupSuccess && "border-success focus-visible:border-success",
            hasLookupWarning && "border-warning focus-visible:border-warning"
          )}
          data-field="address.postcode"
        />
        <div className="absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none">
          {statusIcon}
        </div>
      </div>
    </FormField>
  );
}
