"use client";

import { useQuery, type UseQueryOptions, type UseQueryResult } from "@tanstack/react-query";

import { queryKeys } from "@/core/api";
import { type AddressLookupResult } from "@customer-portal/domain/address";
import { addressService, EMPTY_LOOKUP_RESULT } from "../api/address.api";

// ============================================================================
// Type Helpers
// ============================================================================

type ZipLookupQueryKey = ReturnType<typeof queryKeys.address.zipLookup>;
type StatusQueryKey = ReturnType<typeof queryKeys.address.status>;

type ZipLookupQueryOptions = Omit<
  UseQueryOptions<AddressLookupResult, Error, AddressLookupResult, ZipLookupQueryKey>,
  "queryKey" | "queryFn"
>;

type StatusQueryOptions = Omit<
  UseQueryOptions<{ available: boolean }, Error, { available: boolean }, StatusQueryKey>,
  "queryKey" | "queryFn"
>;

// ============================================================================
// Hooks
// ============================================================================

/**
 * Hook for looking up address by ZIP code
 *
 * @param zipCode - Japanese ZIP code (7 digits, with or without hyphen)
 * @param options - React Query options
 * @returns Query result with address data
 *
 * @example
 * ```tsx
 * const { data, isLoading, error } = useZipCodeLookup("100-0001");
 *
 * if (data?.addresses.length > 0) {
 *   const address = data.addresses[0];
 *   console.log(address.prefecture, address.city, address.town);
 * }
 * ```
 */
export function useZipCodeLookup(
  zipCode: string | undefined,
  options?: ZipLookupQueryOptions
): UseQueryResult<AddressLookupResult, Error> {
  // Normalize ZIP code for validation
  const normalizedZip = zipCode?.replace(/-/g, "") ?? "";
  const isValidZip = /^\d{7}$/.test(normalizedZip);

  return useQuery({
    queryKey: queryKeys.address.zipLookup(normalizedZip),
    queryFn: () => addressService.lookupByZipCode(normalizedZip),
    // Only enable when we have a valid 7-digit ZIP code
    enabled: Boolean(zipCode) && isValidZip,
    // Cache results for 5 minutes (ZIP code data rarely changes)
    staleTime: 5 * 60 * 1000,
    // Don't retry on 404s (invalid ZIP code)
    retry: (failureCount, error) => {
      if (error.message.includes("404") || error.message.includes("not found")) {
        return false;
      }
      return failureCount < 2;
    },
    ...options,
  });
}

/**
 * Hook for checking address service availability
 *
 * @param options - React Query options
 * @returns Query result with service status
 */
export function useAddressServiceStatus(
  options?: StatusQueryOptions
): UseQueryResult<{ available: boolean }, Error> {
  return useQuery({
    queryKey: queryKeys.address.status(),
    queryFn: addressService.getStatus,
    staleTime: 60 * 1000, // Check every minute at most
    ...options,
  });
}

/**
 * Get the first address from lookup result
 * Convenience helper for single-address selections
 */
export function getFirstAddress(result: AddressLookupResult | undefined) {
  return result?.addresses[0] ?? null;
}

// Re-export empty result for components that need a default value
export { EMPTY_LOOKUP_RESULT };
