"use client";

import { useEffect } from "react";
import { MapPinIcon, ExclamationTriangleIcon } from "@heroicons/react/24/outline";
import { COUNTRY_OPTIONS, getCountryCodeByName } from "@/lib/constants/countries";
import { useZodForm } from "@customer-portal/validation";
import {
  addressFormSchema,
  type AddressFormData,
  type Address,
} from "@customer-portal/domain/customer";

export interface AddressFormProps {
  // Initial values
  initialAddress?: Partial<Address>;

  // Callbacks
  onChange?: (address: Address, isValid: boolean) => void;
  onValidationChange?: (errors: string[]) => void;

  // Configuration
  title?: string;
  description?: string;
  showTitle?: boolean;
  required?: boolean;

  // Field configuration
  requiredFields?: (keyof Address)[];
  hiddenFields?: (keyof Address)[];
  fieldLabels?: Partial<Record<keyof Address, string>>;
  fieldPlaceholders?: Partial<Record<keyof Address, string>>;

  // Styling
  variant?: "default" | "compact" | "inline";
  disabled?: boolean;

  // Validation
  customValidation?: (address: Partial<Address>) => string[];
}

const normalizeCountryValue = (value?: string | null) => {
  if (!value) return "";
  if (value.length === 2) return value.toUpperCase();
  return getCountryCodeByName(value) ?? value;
};

const DEFAULT_LABELS: Partial<Record<keyof Address, string>> = {
  address1: "Address Line 1",
  address2: "Address Line 2",
  city: "City",
  state: "State/Prefecture",
  postcode: "Postcode",
  country: "Country",
  countryCode: "Country Code",
  phoneNumber: "Phone Number",
  phoneCountryCode: "Country Dialing Code",
};

const DEFAULT_PLACEHOLDERS: Partial<Record<keyof Address, string>> = {
  address1: "123 Main Street",
  address2: "Apartment, suite, etc. (optional)",
  city: "Tokyo",
  state: "Tokyo",
  postcode: "100-0001",
  country: "Select Country",
  countryCode: "JP",
};

const DEFAULT_REQUIRED_FIELDS: (keyof Address)[] = [
  "address1",
  "city",
  "state",
  "postcode",
  "country",
];

const SELECT_COUNTRY_OPTIONS = [{ code: "", name: "Select Country" }, ...COUNTRY_OPTIONS];

export function AddressForm({
  initialAddress = {},
  onChange,
  onValidationChange,
  title = "Address Information",
  description,
  showTitle = true,
  required = true,
  requiredFields = DEFAULT_REQUIRED_FIELDS,
  hiddenFields = [],
  fieldLabels = {},
  fieldPlaceholders = {},
  variant = "default",
  disabled = false,
  customValidation,
}: AddressFormProps) {
  const labels = { ...DEFAULT_LABELS, ...fieldLabels };
  const placeholders = { ...DEFAULT_PLACEHOLDERS, ...fieldPlaceholders };

  // Create initial values with proper defaults
  const initialCountry = normalizeCountryValue(initialAddress.country);
  const initialCountryCode = normalizeCountryValue(initialAddress.countryCode ?? initialCountry);

  const initialValues: AddressFormData = {
    address1: initialAddress.address1 || "",
    address2: initialAddress.address2 || "",
    city: initialAddress.city || "",
    state: initialAddress.state || "",
    postcode: initialAddress.postcode || "",
    country: initialCountry,
    countryCode: initialCountryCode,
    phoneNumber: initialAddress.phoneNumber || "",
    phoneCountryCode: initialAddress.phoneCountryCode || "",
  };

  // Use Zod form with address schema
  const form = useZodForm({
    schema: addressFormSchema,
    initialValues,
  });

  // Handle field changes
  const handleFieldChange = (field: keyof Address, value: string) => {
    if (disabled) return;

    if (field === "country") {
      form.setValue("country", value);
      form.setValue("countryCode", value);
    } else if (field === "countryCode") {
      form.setValue("countryCode", value);
      form.setValue("country", value);
    } else {
      form.setValue(field, value);
    }

    // Custom validation if provided
    if (customValidation) {
      const customErrors = customValidation({ ...form.values, [field]: value });
      // Handle custom errors (could be enhanced to merge with Zod errors)
      onValidationChange?.(customErrors);
    }

    // Check if address is complete and valid
    const updatedValues = { ...form.values, [field]: value } as AddressFormData;
    if (field === "country") {
      updatedValues.country = value;
      updatedValues.countryCode = value;
    } else if (field === "countryCode") {
      updatedValues.countryCode = value;
      updatedValues.country = value;
    }

    const isComplete = requiredFields
      .filter(f => !hiddenFields.includes(f))
      .every(f => updatedValues[f] && String(updatedValues[f]).trim());

    if (onChange && isComplete) {
      onChange(updatedValues as Address, form.isValid);
    }
  };

  // Update form when initialAddress changes
  useEffect(() => {
    if (initialAddress) {
      Object.entries(initialAddress).forEach(([key, value]) => {
        if (value !== undefined) {
          const normalizedValue =
            key === "country" || key === "countryCode"
              ? normalizeCountryValue(value as string | undefined)
              : value || "";
          form.setValue(key as keyof Address, normalizedValue);
        }
      });

      const normalizedCountry = normalizeCountryValue(initialAddress.country);
      const normalizedCountryCode = normalizeCountryValue(
        initialAddress.countryCode ?? initialAddress.country
      );
      form.setValue("country", normalizedCountry);
      form.setValue("countryCode", normalizedCountryCode);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [
    initialAddress?.address1,
    initialAddress?.address2,
    initialAddress?.city,
    initialAddress?.state,
    initialAddress?.postcode,
    initialAddress?.country,
    initialAddress?.countryCode,
    initialAddress?.phoneNumber,
    initialAddress?.phoneCountryCode,
  ]);

  // Notify parent of validation changes
  useEffect(() => {
    const errorMessages = Object.values(form.errors).filter(Boolean) as string[];
    onValidationChange?.(errorMessages);
  }, [form.errors, onValidationChange]);

  const getFieldError = (field: keyof Address) => {
    return form.touched[field] ? form.errors[field] : undefined;
  };

  const renderField = (field: keyof Address, type: "input" | "select" = "input") => {
    if (hiddenFields.includes(field)) return null;

    const isRequired = required && requiredFields.includes(field);
    const fieldError = getFieldError(field);
    const hasError = !!fieldError;

    const baseInputClasses = `w-full px-3 py-2 border rounded-md focus:outline-none focus:ring-2 transition-colors ${
      hasError
        ? "border-red-300 focus:ring-red-500 focus:border-red-500"
        : "border-gray-300 focus:ring-blue-500 focus:border-blue-500"
    } ${disabled ? "bg-gray-50 cursor-not-allowed" : "bg-white"}`;

    return (
      <div key={field} className={variant === "compact" ? "mb-3" : "mb-4"}>
        <label className="block text-sm font-medium text-gray-700 mb-1">
          {labels[field]}
          {isRequired && <span className="text-red-500 ml-1">*</span>}
        </label>

        {type === "select" ? (
          <select
            value={form.values[field] || ""}
            onChange={e => handleFieldChange(field, e.target.value)}
            onBlur={() => form.setTouched(field, true)}
            className={baseInputClasses}
            disabled={disabled}
          >
            {SELECT_COUNTRY_OPTIONS.map(option => (
              <option key={option.code} value={option.code}>
                {option.name}
              </option>
            ))}
          </select>
        ) : (
          <input
            type="text"
            value={form.values[field] || ""}
            onChange={e => handleFieldChange(field, e.target.value)}
            onBlur={() => form.setTouched(field, true)}
            placeholder={placeholders[field]}
            className={baseInputClasses}
            disabled={disabled}
          />
        )}

        {hasError && (
          <div className="mt-1 flex items-center gap-1 text-red-600">
            <ExclamationTriangleIcon className="h-4 w-4 flex-shrink-0" />
            <span className="text-sm">{fieldError}</span>
          </div>
        )}
      </div>
    );
  };

  const containerClasses =
    variant === "inline"
      ? ""
      : variant === "compact"
        ? "p-4 bg-gray-50 rounded-lg border border-gray-200"
        : "p-6 bg-white border border-gray-200 rounded-lg";

  // Get all validation errors
  const allErrors = Object.values(form.errors).filter(Boolean) as string[];
  const hasAnyTouched = Object.values(form.touched).some(Boolean);

  return (
    <div className={containerClasses}>
      {showTitle && (
        <div className="mb-6">
          <div className="flex items-center gap-2 mb-2">
            <MapPinIcon className="h-5 w-5 text-blue-600" />
            <h3 className="text-lg font-semibold text-gray-900">{title}</h3>
          </div>
          {description && <p className="text-sm text-gray-600">{description}</p>}
        </div>
      )}

      <div className="space-y-4">
        {/* Street Address */}
        {renderField("address1")}

        {/* Street Address Line 2 */}
        {renderField("address2")}

        {/* City, State, Postal Code Row */}
        <div
          className={`grid gap-4 ${variant === "compact" ? "grid-cols-1 sm:grid-cols-3" : "grid-cols-1 md:grid-cols-3"}`}
        >
          {renderField("city")}
          {renderField("state")}
          {renderField("postcode")}
        </div>

        {/* Country */}
        {renderField("country", "select")}
      </div>

      {/* Overall validation errors */}
      {allErrors.length > 0 && hasAnyTouched && (
        <div className="mt-4 p-3 bg-red-50 border border-red-200 rounded-lg">
          <div className="flex items-start gap-2">
            <ExclamationTriangleIcon className="h-5 w-5 text-red-500 flex-shrink-0 mt-0.5" />
            <div>
              <p className="text-sm font-medium text-red-800">Please correct the following:</p>
              <ul className="mt-1 text-sm text-red-700 list-disc list-inside">
                {allErrors.map((error, index) => (
                  <li key={index}>{error}</li>
                ))}
              </ul>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}
