import { useEffect, useState } from "react";
import { addressLookupApi } from "@/lib/api/addressLookup";
import type { UseFormReturn } from "react-hook-form";
import type { ApiProductUnit } from "@/lib/api/types";
import {
  countryOptions,
  indianStates,
  type ProductFormValues,
} from "./product.schema";
import { Field, SectionCard, UnitSelect, inputClass } from "./fields";

/** One brand / state / city combination the catalog stocks a product in. */
export type CatalogLocation = { brand_id: number; state: string; cities: string[] };

type Props = {
  form: UseFormReturn<ProductFormValues>;
  units: ApiProductUnit[];
  /**
   * Where the linked catalog product is actually stocked. Null on a product the
   * seller created themselves, where loading details are free text.
   */
  catalogLocations?: CatalogLocation[] | null;
};

export default function Step6LoadingMoq({ form, units, catalogLocations = null }: Props) {
  const {
    register,
    watch,
    setValue,
    formState: { errors },
  } = form;

  const brandId = watch("brand_id");
  const selectedState = watch("loading_state");
  const selectedCity = watch("loading_city");

  /*
    Narrowed to the picked brand, because a catalog product is not stocked in the
    same places under every brand. Before a brand is chosen the union of all its
    locations is the honest answer — hiding everything would read as "this
    product ships from nowhere".
  */
  const scoped = (catalogLocations ?? []).filter(
    (row) => !brandId || String(row.brand_id) === String(brandId)
  );
  const restricted = Boolean(catalogLocations?.length) && scoped.length > 0;

  /*
    A product the seller created themselves picks its loading point from the
    city master (the pincode table buyers and freight use), not free text — a
    typed "test" or "raigarh " could not be priced or matched (B42).
  */
  const [masterStates, setMasterStates] = useState<string[] | null>(null);
  const [masterCities, setMasterCities] = useState<string[]>([]);
  useEffect(() => {
    if (restricted) return;
    let active = true;
    addressLookupApi
      .states()
      .then((list) => active && setMasterStates(list))
      .catch(() => active && setMasterStates(null));
    return () => {
      active = false;
    };
  }, [restricted]);
  useEffect(() => {
    if (restricted || !selectedState) {
      setMasterCities([]);
      return;
    }
    let active = true;
    addressLookupApi
      .cities(selectedState)
      .then((list) => active && setMasterCities(list))
      .catch(() => active && setMasterCities([]));
    return () => {
      active = false;
    };
  }, [restricted, selectedState]);

  const stateOptions = restricted
    ? Array.from(new Set(scoped.map((row) => row.state))).sort()
    : masterStates ?? indianStates;

  const cityOptions = restricted
    ? Array.from(
        new Set(scoped.filter((row) => row.state === selectedState).flatMap((row) => row.cities))
      ).sort()
    : masterCities;

  /*
    Changing the brand can strip the state (and with it the city) out of the
    list. Leaving a value behind that no option matches makes the dropdown look
    blank while the form still holds the old text, and the step would save a
    location the catalog cannot price.
  */
  useEffect(() => {
    if (!restricted) return;
    if (selectedState && !stateOptions.includes(selectedState)) {
      setValue("loading_state", "");
      setValue("loading_city", "");
    } else if (selectedCity && selectedState && !cityOptions.includes(selectedCity)) {
      setValue("loading_city", "");
    }
    // `stateOptions` / `cityOptions` are rebuilt each render; the values they
    // are derived from are the real dependencies.
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [restricted, brandId, selectedState, selectedCity, setValue]);

  const { onChange: onStateChange, ...stateField } = register("loading_state");

  return (
    <div className="space-y-4">
      <SectionCard
        title="Loading Details"
        subtitle={
          restricted
            ? "Pick where you load from. Only the locations this catalog product is stocked in are listed."
            : undefined
        }
      >
        <div className="grid grid-cols-1 gap-4 md:grid-cols-3">
          <Field label="Loading State" required error={errors.loading_state?.message}>
            <select
              {...stateField}
              onChange={(event) => {
                onStateChange(event);
                // The city list is a function of the state, so a stale city
                // must not survive the change.
                setValue("loading_city", "");
              }}
              className={inputClass}
            >
              <option value="">Select state</option>
              {stateOptions.map((s) => (
                <option key={s} value={s}>
                  {s}
                </option>
              ))}
            </select>
          </Field>

          <Field label="Loading City" required error={errors.loading_city?.message}>
            {restricted || masterStates ? (
              <select {...register("loading_city")} className={inputClass} disabled={!selectedState}>
                <option value="">
                  {!selectedState
                    ? "Select state first"
                    : cityOptions.length
                      ? "Select city"
                      : "No cities listed"}
                </option>
                {cityOptions.map((city) => (
                  <option key={city} value={city}>
                    {city}
                  </option>
                ))}
              </select>
            ) : (
              <input {...register("loading_city")} className={inputClass} placeholder="Enter loading city" />
            )}
          </Field>

          <Field label="Country" required error={errors.country?.message}>
            <select {...register("country")} className={inputClass}>
              <option value="">Select country</option>
              {countryOptions.map((c) => (
                <option key={c} value={c}>
                  {c}
                </option>
              ))}
            </select>
          </Field>
        </div>
      </SectionCard>

      <SectionCard title="Minimum Order Quantity (MOQ)">
        <div className="grid grid-cols-1 gap-4 md:grid-cols-2">
          <Field label="MOQ" required error={errors.moq?.message}>
            <input {...register("moq")} className={inputClass} placeholder="Enter minimum order quantity" inputMode="decimal" />
          </Field>

          <Field label="MOQ Unit" required error={errors.moq_unit?.message}>
            <UnitSelect units={units} current={watch("moq_unit")} {...register("moq_unit")} />
          </Field>
        </div>
      </SectionCard>

      <SectionCard title="Supply" subtitle="Buyers see the dispatch time on your offer, and it is copied into every order.">
        <div className="grid grid-cols-1 gap-4 md:grid-cols-2">
          <Field label="Available Quantity (in MOQ unit)" required error={errors.available_quantity?.message}>
            <input {...register("available_quantity")} className={inputClass} placeholder="e.g. 500" inputMode="decimal" />
          </Field>

          <Field label="Dispatch Within (days)" required error={errors.load_within?.message}>
            <input {...register("load_within")} className={inputClass} placeholder="e.g. 3" inputMode="numeric" />
          </Field>
        </div>
      </SectionCard>
    </div>
  );
}
