import { useEffect, useState } from "react";
import type { UseFormReturn } from "react-hook-form";
import { catalogApi } from "@/lib/api/catalog";
import type { ApiCatalogSuggestion, ApiCategory, ApiSubCategory } from "@/lib/api/types";
import {
  productTypeOptions,
  type ProductFormValues,
} from "./product.schema";
import { Field, SectionCard, inputClass } from "./fields";
import ProductNameField from "./ProductNameField";
import { GST_RATES } from "@/lib/validation";

type Props = {
  form: UseFormReturn<ProductFormValues>;
  categories: ApiCategory[];
  /** Server-fetched on the edit screen, so the saved sub-category has an option
   *  to match on the very first render. */
  initialSubCategories?: ApiSubCategory[];
  /* --- Catalog link, owned by the wizard because later steps use it too --- */
  token: string | null;
  linkedName: string | null;
  linking: boolean;
  onCatalogPick: (suggestion: ApiCatalogSuggestion) => void;
  onCatalogClear: () => void;
};

export default function Step1BasicInfo({
  form,
  categories,
  initialSubCategories = [],
  token,
  linkedName,
  linking,
  onCatalogPick,
  onCatalogClear,
}: Props) {
  const {
    register,
    watch,
    setValue,
    getValues,
    formState: { errors },
  } = form;

  const shortLen = (watch("short_description") || "").length;
  const detailLen = (watch("detailed_description") || "").length;

  const categoryId = watch("category");
  // A catalog-linked product is filed where the catalog files it (B07); the
  // server enforces this, the form just stops offering a choice it would undo.
  const locked = !!linkedName;
  const lockedProps = locked
    ? { tabIndex: -1, "aria-disabled": true, className: `${inputClass} pointer-events-none bg-gray-50 text-gray-600` }
    : { className: inputClass };
  const [subCategories, setSubCategories] = useState<ApiSubCategory[]>(initialSubCategories);
  const [loadingSubs, setLoadingSubs] = useState(false);

  useEffect(() => {
    if (!categoryId) {
      setSubCategories([]);
      return;
    }
    let active = true;
    setLoadingSubs(true);
    catalogApi
      .subCategories(Number(categoryId))
      .then((res) => {
        if (active) setSubCategories(res.data ?? []);
      })
      .catch(() => {
        if (active) setSubCategories([]);
      })
      .finally(() => {
        if (active) setLoadingSubs(false);
      });
    return () => {
      active = false;
    };
  }, [categoryId]);

  /*
    Clearing the sub-category belongs to the dropdown, not to the effect above.

    Watching the category and clearing on every change cannot tell a seller
    picking a different category from the form being filled in for them — so a
    catalog product whose category and sub-category arrive together lost its
    sub-category the moment the category landed.
  */
  const { onChange: onCategoryChange, ...categoryField } = register("category");

  /*
    Re-apply the saved selection once its options exist.

    `register` seeds a <select> from form state when it mounts, but on the edit
    screen the category list arrives a request later. A select whose value
    matches no option falls back to blank, and nothing puts it back when the
    options land — so a product with a category showed an empty dropdown. The
    sub-category list is a second request behind that, with the same result.
  */
  useEffect(() => {
    const saved = getValues("category");
    if (saved && categories.some((cat) => String(cat.id) === saved)) {
      setValue("category", saved);
    }
  }, [categories, getValues, setValue]);

  useEffect(() => {
    const saved = getValues("sub_category");
    if (saved && subCategories.some((sub) => String(sub.id) === saved)) {
      setValue("sub_category", saved);
    }
  }, [subCategories, getValues, setValue]);

  return (
    <div className="space-y-4">
      <SectionCard title="Basic Information">
        <div className="grid grid-cols-1 gap-4 md:grid-cols-2">
          <ProductNameField
            form={form}
            token={token}
            linkedName={linkedName}
            linking={linking}
            onPick={onCatalogPick}
            onClear={onCatalogClear}
          />

          <Field
            label="Category"
            required
            error={errors.category?.message}
            hint={locked ? "Set by the Biznie catalog for this product" : undefined}
          >
            <select
              {...categoryField}
              onChange={(event) => {
                onCategoryChange(event);
                setValue("sub_category", "");
              }}
              {...lockedProps}
            >
              <option value="">Select category</option>
              {categories.map((cat) => (
                <option key={cat.id} value={String(cat.id)}>
                  {cat.name}
                </option>
              ))}
            </select>
          </Field>

          <Field label="Sub Category" error={errors.sub_category?.message}>
            <select {...register("sub_category")} disabled={!categoryId || loadingSubs} {...lockedProps}>
              <option value="">
                {!categoryId
                  ? "Select category first"
                  : loadingSubs
                    ? "Loading…"
                    : subCategories.length
                      ? "Select sub category"
                      : "No sub categories"}
              </option>
              {subCategories.map((sub) => (
                <option key={sub.id} value={String(sub.id)}>
                  {sub.name}
                </option>
              ))}
            </select>
          </Field>

          <Field label="Product Type" required error={errors.product_type?.message} className="md:col-span-2">
            <div className="flex flex-wrap gap-6 pt-1">
              {productTypeOptions.map((opt) => (
                <label key={opt.value} className="flex items-center gap-2 text-sm text-gray-700">
                  <input
                    type="radio"
                    value={opt.value}
                    {...register("product_type")}
                    className="h-4 w-4 accent-[#CC1414]"
                  />
                  {opt.label}
                </label>
              ))}
            </div>
          </Field>

          <Field label="Short Description" required error={errors.short_description?.message} className="md:col-span-2">
            <div className="relative">
              <textarea
                {...register("short_description")}
                rows={2}
                maxLength={200}
                className={inputClass}
                placeholder="Enter short description"
              />
              <span className="pointer-events-none absolute bottom-2 right-3 text-[11px] text-gray-400">
                {shortLen}/200
              </span>
            </div>
          </Field>

          <Field label="Detailed Description" error={errors.detailed_description?.message} className="md:col-span-2">
            <div className="relative">
              <textarea
                {...register("detailed_description")}
                rows={4}
                maxLength={1000}
                className={inputClass}
                placeholder="Enter detailed description"
              />
              <span className="pointer-events-none absolute bottom-2 right-3 text-[11px] text-gray-400">
                {detailLen}/1000
              </span>
            </div>
          </Field>
        </div>
      </SectionCard>

      <SectionCard title="HSN Code">
        <div className="grid grid-cols-1 gap-4 md:grid-cols-2">
          <Field label="HSN Code" required error={errors.hsn_code?.message}>
            <input
              {...register("hsn_code", {
                // Digits only: HSN is 4, 6 or 8 digits, never text (B42).
                onChange: (e) => {
                  e.target.value = e.target.value.replace(/\D/g, "").slice(0, 8);
                },
              })}
              className={inputClass}
              placeholder="4, 6 or 8 digits, e.g. 7214"
              inputMode="numeric"
              maxLength={8}
            />
          </Field>

          <Field label="GST Rate" required error={errors.tax_rate?.message}>
            {/* A slab, not free text — "1820%" was accepted before (B42). */}
            <select {...register("tax_rate")} className={inputClass}>
              <option value="">Select GST rate</option>
              {GST_RATES.map((rate) => (
                <option key={rate} value={String(rate)}>
                  {rate}%
                </option>
              ))}
            </select>
          </Field>
        </div>
      </SectionCard>
    </div>
  );
}
