"use client";

import {
  useEffect,
  useState,
  useMemo,
  useRef,
  useImperativeHandle,
  forwardRef,
} from "react";
import { useForm, Controller } from "react-hook-form";
import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { toast } from "react-toastify";
import { Form } from "@/components/ui/form";
import { FormFieldWrapper } from "@/components/ui/form-field";
import { useTranslation } from "react-i18next";
import { useCheckout } from "@/context/helpers/checkout/CheckoutContext";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  FormItem,
  FormLabel,
  FormMessage,
  FormControl,
} from "@/components/ui/form";
import Loading from "@/components/Loading";
import { useRouter } from "next/router";

// Dynamic checkout form that generates fields from API
const CheckoutForm = forwardRef((_, ref) => {
  const { t, i18n } = useTranslation("checkout");
  const isArabic = i18n.language === "ar";
  const router = useRouter();

  const {
    getCheckoutForm,
    checkoutFormInputs,
    checkoutFormCountries,
    checkoutFormCities,
    checkoutFormDistricts,
    addresses,
    newAddress,
    setNewAddress,
    selectedAddress,
    setSelectedAddress,
    setOrderAddress,
    setOrderNote,
    isLoading,
    getShippingMethods,
  } = useCheckout();

  const [selectedCountry, setSelectedCountry] = useState(null);
  const [selectedState, setSelectedState] = useState(null);
  const [selectedCity, setSelectedCity] = useState(null);
  const autoPopulatedRef = useRef(false);

  // Fetch checkout form data on mount
  useEffect(() => {
    getCheckoutForm();
  }, []);

  // Auto-select and populate first address when addresses are loaded
  useEffect(() => {
    // Auto-select first address if addresses exist and no address is currently selected
    if (
      addresses &&
      addresses.length > 0 &&
      !selectedAddress &&
      !newAddress &&
      checkoutFormInputs &&
      checkoutFormInputs.length > 0 &&
      !autoPopulatedRef.current
    ) {
      const firstAddress = addresses[0];
      autoPopulatedRef.current = true;
      // Set selected address and populate form
      setSelectedAddress(firstAddress.id);
      handleAddressSelect(firstAddress.id);
    }
    // Also handle case where selectedAddress is already set (e.g., user selection)
    else if (
      selectedAddress &&
      addresses &&
      addresses.length > 0 &&
      !newAddress &&
      checkoutFormInputs &&
      checkoutFormInputs.length > 0 &&
      !autoPopulatedRef.current
    ) {
      const address = addresses.find((addr) => addr.id === selectedAddress);
      if (address) {
        autoPopulatedRef.current = true;
        handleAddressSelect(selectedAddress);
      }
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [addresses, checkoutFormInputs, newAddress, selectedAddress]);

  // Build dynamic Zod schema from API inputs
  const formSchema = useMemo(() => {
    if (!checkoutFormInputs || checkoutFormInputs.length === 0) {
      return z.object({});
    }

    const schemaFields = {};
    checkoutFormInputs.forEach((input) => {
      const fieldName = input.input_name;
      let fieldSchema = z.string();

      if (input.required) {
        fieldSchema = fieldSchema.min(1, `${input.label} is required`);
      } else {
        fieldSchema = fieldSchema.optional();
      }

      schemaFields[fieldName] = fieldSchema;
    });

    // Add optional fields that might not be in inputs
    schemaFields.orderNotes = z.string().optional();

    return z.object(schemaFields);
  }, [checkoutFormInputs]);

  // Setup form with dynamic schema
  const form = useForm({
    resolver: zodResolver(formSchema),
    defaultValues: {},
  });

  // Expose submit handler via ref for external button (must be before any conditional returns)
  useImperativeHandle(ref, () => ({
    submit: () => {
      console.log("Form submit called");
      console.log("Form values:", form.getValues());
      console.log("Form errors:", form.formState.errors);

      form.handleSubmit(
        (values) => {
          console.log("Form validation passed, submitting:", values);
          onSubmit(values);
        },
        (errors) => {
          console.error("Form validation failed:", errors);
          // Show first validation error
          const firstError = Object.values(errors)[0];
          if (firstError?.message) {
            toast.error(firstError.message);
          } else {
            toast.error("Please fill in all required fields.");
          }
        }
      )();
    },
  }));

  // Watch form values to update orderAddress
  // Use ref to track previous values and prevent unnecessary updates
  const prevValuesRef = useRef({});

  useEffect(() => {
    const subscription = form.watch((values) => {
      const addressData = {};
      let hasData = false;

      Object.entries(values || {}).forEach(([key, value]) => {
        if (key !== "orderNotes" && value && value !== "") {
          addressData[key] = value;
          hasData = true;
        }
      });

      // Only update if values actually changed
      const valuesString = JSON.stringify(addressData);
      const prevValuesString = JSON.stringify(prevValuesRef.current);

      if (hasData && valuesString !== prevValuesString) {
        prevValuesRef.current = addressData;
        setOrderAddress(addressData);
      } else if (!hasData && Object.keys(prevValuesRef.current).length > 0) {
        prevValuesRef.current = {};
        setOrderAddress({});
      }
    });

    return () => subscription.unsubscribe();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // Handle saved address selection
  const handleAddressSelect = async (addressId) => {
    setSelectedAddress(addressId);
    const address = addresses.find((addr) => addr.id === addressId);
    if (address) {
      // Set country and state first so dropdowns show correct options
      if (address.country) {
        setSelectedCountry(address.country);
      }

      // Set state/city selection state
      // The city field in the form actually stores state ID
      if (address.city) {
        // Find the state ID that matches the city value
        if (address.country && checkoutFormCities?.[address.country]) {
          const states = checkoutFormCities[address.country];
          // Try to find state by code or name
          const state = states.find(
            (s) =>
              String(s.id) === String(address.city) ||
              s.code === address.city ||
              s.default_name === address.city
          );
          if (state) {
            setSelectedState(String(state.id));
          }
        }
      }

      // Populate form with selected address
      const formData = {
        first_name: address.first_name || "",
        last_name: address.last_name || "",
        email: address.email || "",
        phone: address.phone || "",
        address1: address.address1 || "",
        address2: address.address2 || "",
        postcode: address.postcode || "",
        country: address.country || "",
        city: address.city ? String(address.city) : "",
        state: address.state || "",
        district: address.CityId ? String(address.CityId) : "",
      };
      form.reset(formData);

      // Set order address
      setOrderAddress({
        first_name: address.first_name,
        last_name: address.last_name,
        email: address.email,
        phone: address.phone,
        address1: address.address1,
        address2: address.address2 || "",
        postcode: address.postcode,
        country: address.country,
        city: address.city,
        state: address.state,
        district: address.CityId || "",
      });

      // Get shipping methods for selected address
      if (addressId) {
        await getShippingMethods(addressId);
      }
    }
  };

  // Handle country change
  const handleCountryChange = (countryCode) => {
    setSelectedCountry(countryCode);
    setSelectedState(null);
    setSelectedCity(null);
    form.setValue("state", "");
    form.setValue("city", "");
    form.setValue("district", "");
  };

  // Handle state change
  const handleStateChange = (stateId) => {
    setSelectedState(stateId);
    setSelectedCity(null);
    // Don't clear city field - it should store the state ID
    // Only clear district when state changes
    form.setValue("district", "");
  };

  // Get available states based on selected country
  const availableStates = useMemo(() => {
    if (!selectedCountry || !checkoutFormCities) return [];
    return checkoutFormCities[selectedCountry] || [];
  }, [selectedCountry, checkoutFormCities]);

  // Get state code from state ID
  const getStateCode = (stateId) => {
    if (!selectedCountry || !checkoutFormCities) return null;
    const states = checkoutFormCities[selectedCountry] || [];
    const state = states.find((s) => String(s.id) === String(stateId));
    return state?.code || null;
  };

  // Get available districts (cities) based on selected state
  const availableDistricts = useMemo(() => {
    if (!selectedState || !checkoutFormDistricts) return [];
    const stateCode = getStateCode(selectedState);
    if (!stateCode) return [];
    return checkoutFormDistricts[stateCode] || [];
  }, [
    selectedState,
    checkoutFormDistricts,
    selectedCountry,
    checkoutFormCities,
  ]);

  // Render form field based on input type
  const renderFormField = (input) => {
    const fieldName = input.input_name;
    const label = input.label;
    const isRequired = input.required;
    const fieldType = input.type;

    if (fieldType === "select") {
      // Handle country select
      if (fieldName === "country") {
        return (
          <Controller
            key={fieldName}
            name={fieldName}
            control={form.control}
            render={({ field }) => (
              <FormItem className="space-y-2">
                <FormLabel className="mb-2">
                  {label} {isRequired && "*"}
                </FormLabel>
                <Select
                  onValueChange={(value) => {
                    field.onChange(value);
                    handleCountryChange(value);
                  }}
                  value={field.value ? String(field.value) : ""}
                >
                  <FormControl>
                    <SelectTrigger>
                      <SelectValue placeholder={`Select ${label}`} />
                    </SelectTrigger>
                  </FormControl>
                  <SelectContent>
                    {checkoutFormCountries?.map((country) => (
                      <SelectItem key={country.id} value={country.code}>
                        {country.name}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
                <FormMessage />
              </FormItem>
            )}
          />
        );
      }

      // Handle state/city select
      if (fieldName === "city") {
        return (
          <Controller
            key={fieldName}
            name={fieldName}
            control={form.control}
            render={({ field }) => (
              <FormItem className="space-y-2">
                <FormLabel className="mb-2">
                  {label} {isRequired && "*"}
                </FormLabel>
                <Select
                  onValueChange={(value) => {
                    field.onChange(value);
                    handleStateChange(value);
                  }}
                  value={field.value ? String(field.value) : ""}
                  disabled={!selectedCountry}
                >
                  <FormControl>
                    <SelectTrigger>
                      <SelectValue placeholder={`Select ${label}`} />
                    </SelectTrigger>
                  </FormControl>
                  <SelectContent>
                    {availableStates.map((state) => (
                      <SelectItem key={state.id} value={String(state.id)}>
                        {state.default_name}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
                <FormMessage />
              </FormItem>
            )}
          />
        );
      }

      // Handle district select
      if (fieldName === "district") {
        return (
          <Controller
            key={fieldName}
            name={fieldName}
            control={form.control}
            render={({ field }) => (
              <FormItem className="space-y-2">
                <FormLabel className="mb-2">
                  {label} {isRequired && "*"}
                </FormLabel>
                <Select
                  onValueChange={field.onChange}
                  value={field.value ? String(field.value) : ""}
                  disabled={!selectedState}
                >
                  <FormControl>
                    <SelectTrigger>
                      <SelectValue placeholder={`Select ${label}`} />
                    </SelectTrigger>
                  </FormControl>
                  <SelectContent>
                    {availableDistricts.map((district) => (
                      <SelectItem key={district.id} value={String(district.id)}>
                        {district.default_name}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
                <FormMessage />
              </FormItem>
            )}
          />
        );
      }
    }

    // Default text input
    return (
      <FormFieldWrapper
        key={fieldName}
        control={form.control}
        name={fieldName}
        label={label}
        type="text"
        required={isRequired}
        optional={!isRequired}
      />
    );
  };

  // Submit handler - redirects to review order page
  const onSubmit = async (values) => {
    try {
      // Set order note if provided
      if (values.orderNotes) {
        setOrderNote(values.orderNotes);
      }

      // Prepare address data for order review
      const addressData = {};
      Object.entries(values).forEach(([key, value]) => {
        if (key !== "orderNotes" && value && value !== "") {
          addressData[key] = value;
        }
      });

      // Set order address
      setOrderAddress(addressData);

      // Store address data in localStorage to use on review page
      if (typeof window !== "undefined") {
        localStorage.setItem(
          "checkoutAddressData",
          JSON.stringify(addressData)
        );
      }

      // Redirect to review order page
      router.push("/checkout/review-order");
    } catch (error) {
      console.error("Form submission error", error);
      toast.error("Failed to submit the form. Please try again.");
    }
  };

  if (isLoading && !checkoutFormInputs) {
    return <Loading />;
  }

  // Group inputs for better layout
  const nameInputs =
    checkoutFormInputs?.filter(
      (input) =>
        input.input_name === "first_name" || input.input_name === "last_name"
    ) || [];
  const contactInputs =
    checkoutFormInputs?.filter(
      (input) => input.input_name === "email" || input.input_name === "phone"
    ) || [];
  const locationInputs =
    checkoutFormInputs?.filter(
      (input) =>
        input.input_name === "country" ||
        input.input_name === "city" ||
        input.input_name === "district" ||
        input.input_name === "address1" ||
        input.input_name === "postcode"
    ) || [];
  const otherInputs =
    checkoutFormInputs?.filter(
      (input) =>
        !nameInputs.includes(input) &&
        !contactInputs.includes(input) &&
        !locationInputs.includes(input)
    ) || [];

  return (
    <Form {...form}>
      <form
        onSubmit={form.handleSubmit(onSubmit)}
        className="py-10 space-y-5"
        id="checkout-form"
      >
        {/* Saved Addresses Selection */}
        {addresses && addresses.length > 0 && (
          <section className="mb-6 p-4 border rounded">
            <h3 className="text-lg font-semibold mb-4">
              {t("form.savedAddresses", "Saved Addresses")}
            </h3>
            <RadioGroup
              value={
                selectedAddress
                  ? String(selectedAddress)
                  : newAddress
                    ? "new"
                    : ""
              }
              onValueChange={(value) => {
                if (value === "new") {
                  setNewAddress(true);
                  setSelectedAddress(null);
                  autoPopulatedRef.current = false; // Reset ref when switching to new address
                  // Reset country/state selection state
                  setSelectedCountry(null);
                  setSelectedState(null);
                  setSelectedCity(null);
                  // Reset form to empty values
                  const emptyValues = {};
                  checkoutFormInputs?.forEach((input) => {
                    emptyValues[input.input_name] = "";
                  });
                  form.reset(emptyValues);
                  prevValuesRef.current = {};
                  setOrderAddress({});
                } else {
                  handleAddressSelect(Number(value));
                  setNewAddress(false);
                }
              }}
            >
              {addresses.map((address) => (
                <div
                  key={address.id}
                  className={`flex items-center gap-3 mb-3 p-3 border rounded ${
                    isArabic ? "flex-row-reverse" : ""
                  }`}
                >
                  <RadioGroupItem
                    value={String(address.id)}
                    id={`address-${address.id}`}
                  />
                  <Label
                    htmlFor={`address-${address.id}`}
                    className="flex-1 cursor-pointer"
                  >
                    <div className="text-sm">
                      <div className="font-semibold">
                        {address.first_name} {address.last_name}
                      </div>
                      <div className="text-gray-600">
                        {address.address1}, {address.city}, {address.state}
                      </div>
                      <div className="text-gray-500">{address.phone}</div>
                    </div>
                  </Label>
                </div>
              ))}
              <div
                className={`flex items-center gap-3 p-3 border rounded ${
                  isArabic ? "flex-row-reverse" : ""
                }`}
              >
                <RadioGroupItem value="new" id="address-new" />
                <Label htmlFor="address-new" className="flex-1 cursor-pointer">
                  <div className="text-sm font-semibold">
                    {t("form.newAddress", "Add New Address")}
                  </div>
                </Label>
              </div>
            </RadioGroup>
          </section>
        )}

        {/* New Address Form - Only show if no addresses or new address selected */}
        {(newAddress || !addresses || addresses.length === 0) && (
          <>
            {/* Name fields */}
            {nameInputs.length > 0 && (
              <fieldset className="grid grid-cols-12 gap-4">
                <legend className="sr-only">{t("form.legends.name")}</legend>
                {nameInputs.map((input) => (
                  <div key={input.input_name} className="col-span-6">
                    {renderFormField(input)}
                  </div>
                ))}
              </fieldset>
            )}

            {/* Other individual fields */}
            {otherInputs
              .filter((input) => !nameInputs.includes(input))
              .map((input) => renderFormField(input))}

            {/* Location fields */}
            {locationInputs
              .filter((input) => input.input_name === "country")
              .map((input) => renderFormField(input))}

            {locationInputs
              .filter((input) => input.input_name === "address1")
              .map((input) => renderFormField(input))}

            {/* Contact fields */}
            {contactInputs.length > 0 && (
              <fieldset className="grid grid-cols-12 gap-4">
                <legend className="sr-only">{t("form.legends.contact")}</legend>
                {contactInputs.map((input) => (
                  <div key={input.input_name} className="col-span-6">
                    {renderFormField(input)}
                  </div>
                ))}
              </fieldset>
            )}

            {/* Location fields - City and District */}
            <fieldset className="grid grid-cols-12 gap-4">
              <legend className="sr-only">{t("form.legends.location")}</legend>
              {locationInputs
                .filter(
                  (input) =>
                    input.input_name === "city" ||
                    input.input_name === "district"
                )
                .map((input) => (
                  <div key={input.input_name} className="col-span-6">
                    {renderFormField(input)}
                  </div>
                ))}
            </fieldset>

            {/* Postcode */}
            {locationInputs
              .filter((input) => input.input_name === "postcode")
              .map((input) => renderFormField(input))}
          </>
        )}

        {/* Order notes */}
        <FormFieldWrapper
          control={form.control}
          name="orderNotes"
          label={t("form.orderNotes")}
          type="textarea"
          placeholder={t("form.orderNotesPlaceholder")}
          optional={true}
          inputClassName="rounded"
        />
      </form>
    </Form>
  );
});

CheckoutForm.displayName = "CheckoutForm";

export default CheckoutForm;
