"use client";

import { useEffect, useMemo, useState, type FormEvent } from "react";
import { useRouter } from "next/navigation";
import { Panel, AdminButton } from "@/components/admin/ui";
import { Field, FormGrid, TextInput, TextSelect, TextTextarea, slugify } from "@/components/admin/formFields";
import { useAuth } from "@/context/AuthContext";
import { useStore } from "@/context/StoreContext";
import {
  api,
  ApiError,
  mediaOrPlaceholder,
  type AdminProductDetailsApi,
  type AttributeApi,
  type ProductAttributeInput,
  type ProductVariantInput,
} from "@/lib/api";
import type { ProductRecord } from "@/data/ecommerceStore";
import { toast } from "sonner";

export const DUPLICATE_STORAGE_KEY = "gns_glow_product_duplicate_v1";

export type ProductFormValues = {
  category_id: string;
  brand_id: string;
  sku: string;
  barcode: string;
  name: string;
  slug: string;
  description: string;
  cost_price: string;
  selling_price: string;
  sale_price: string;
  stock: string;
  weight: string;
  status: "active" | "inactive";
  featured: boolean;
};

const emptyValues = (): ProductFormValues => ({
  category_id: "",
  brand_id: "",
  sku: "",
  barcode: "",
  name: "",
  slug: "",
  description: "",
  cost_price: "",
  selling_price: "",
  sale_price: "",
  stock: "0",
  weight: "0",
  status: "active",
  featured: false,
});

export function productToFormValues(product: ProductRecord): ProductFormValues {
  return {
    ...emptyValues(),
    category_id: String(product.category_id),
    brand_id: String(product.brand_id),
    sku: product.sku,
    barcode: product.barcode || "",
    name: product.name,
    slug: product.slug,
    description: product.description || "",
    cost_price: String(product.cost_price ?? ""),
    selling_price: String(product.selling_price ?? ""),
    sale_price: product.sale_price != null ? String(product.sale_price) : "",
    stock: String(product.stock ?? 0),
    weight: String(product.weight ?? 0),
    status: product.status === "inactive" ? "inactive" : "active",
    featured: Boolean(product.featured),
  };
}

export type AttributeRow = { name: string; values: string };
export type VariantRow = { sku: string; price: string; stock: string; attributes: string };

export function detailsToAttributeRows(details?: AdminProductDetailsApi | null): AttributeRow[] {
  if (!details?.attributes?.length) return [{ name: "Color", values: "" }];
  return details.attributes.map((attribute) => ({
    name: attribute.name,
    values: attribute.values.map((value) => value.value).join(", "),
  }));
}

export function detailsToVariantRows(details?: AdminProductDetailsApi | null): VariantRow[] {
  if (!details?.variants?.length) return [{ sku: "", price: "", stock: "", attributes: "" }];
  return details.variants.map((variant) => ({
    sku: variant.sku,
    price: String(variant.price ?? ""),
    stock: String(variant.stock ?? 0),
    attributes: (variant.attributes || [])
      .map((attr) => `${attr.attribute_name}:${attr.value}`)
      .join(", "),
  }));
}

export function duplicateProductValues(product: ProductRecord): ProductFormValues {
  const base = productToFormValues(product);
  return {
    ...base,
    name: `${product.name} (Copy)`,
    slug: `${product.slug}-copy`,
    sku: `${product.sku}-COPY`,
    status: "inactive",
  };
}

function appendFormPayload(fd: FormData, values: ProductFormValues) {
  fd.set("category_id", values.category_id);
  fd.set("brand_id", values.brand_id);
  fd.set("sku", values.sku.trim());
  fd.set("barcode", values.barcode.trim());
  fd.set("name", values.name.trim());
  fd.set("slug", values.slug.trim() || slugify(values.name));
  fd.set("description", values.description.trim());
  fd.set("cost_price", values.cost_price || "0");
  fd.set("selling_price", values.selling_price || "0");
  if (values.sale_price) fd.set("sale_price", values.sale_price);
  fd.set("stock", values.stock || "0");
  fd.set("weight", values.weight || "0");
  fd.set("status", values.status);
  fd.set("featured", values.featured ? "1" : "0");
}

function valuesToUpdatePayload(values: ProductFormValues): Record<string, unknown> {
  return {
    category_id: Number(values.category_id),
    brand_id: Number(values.brand_id),
    sku: values.sku.trim(),
    barcode: values.barcode.trim(),
    name: values.name.trim(),
    slug: values.slug.trim() || slugify(values.name),
    description: values.description.trim(),
    cost_price: Number(values.cost_price || 0),
    selling_price: Number(values.selling_price || 0),
    sale_price: values.sale_price ? Number(values.sale_price) : null,
    stock: Number(values.stock || 0),
    weight: Number(values.weight || 0),
    status: values.status,
    featured: values.featured,
  };
}

function parseAttributes(rows: AttributeRow[]): ProductAttributeInput[] {
  return rows
    .map((row) => ({
      name: row.name.trim(),
      values: row.values
        .split(",")
        .map((value) => value.trim())
        .filter(Boolean),
    }))
    .filter((row) => row.name && row.values.length);
}

function parseVariantAttributes(value: string): ProductVariantInput["attributes"] {
  return value
    .split(",")
    .map((part) => part.trim())
    .filter(Boolean)
    .map((part) => {
      const [name, attrValue] = part.split(":").map((x) => x.trim());
      return { name: name || "", value: attrValue || "" };
    })
    .filter((item) => item.name && item.value);
}

function parseVariants(rows: VariantRow[]): ProductVariantInput[] {
  return rows
    .map((row) => ({
      sku: row.sku.trim(),
      price: Number(row.price || 0),
      stock: Number(row.stock || 0),
      attributes: parseVariantAttributes(row.attributes),
    }))
    .filter((variant) => variant.sku);
}

type ProductFormProps = {
  mode: "create" | "edit";
  productId?: string;
  initialValues?: ProductFormValues;
  initialAttributeRows?: AttributeRow[];
  initialVariantRows?: VariantRow[];
  existingMainImage?: string | null;
  existingGallery?: string[];
};

export default function ProductForm({
  mode,
  productId,
  initialValues,
  initialAttributeRows,
  initialVariantRows,
  existingMainImage,
  existingGallery = [],
}: ProductFormProps) {
  const router = useRouter();
  const { token } = useAuth();
  const { store, refreshStore } = useStore();
  const [values, setValues] = useState<ProductFormValues>(initialValues || emptyValues());
  const [slugTouched, setSlugTouched] = useState(Boolean(initialValues?.slug));
  const [attributeRows, setAttributeRows] = useState<AttributeRow[]>(
    initialAttributeRows?.length ? initialAttributeRows : [{ name: "Color", values: "" }],
  );
  const [variantRows, setVariantRows] = useState<VariantRow[]>(
    initialVariantRows?.length ? initialVariantRows : [{ sku: "", price: "", stock: "", attributes: "" }],
  );
  const [attributeCatalog, setAttributeCatalog] = useState<AttributeApi[]>([]);
  const [newAttributeName, setNewAttributeName] = useState("");
  const [selectedAttributeId, setSelectedAttributeId] = useState("");
  const [newAttributeValue, setNewAttributeValue] = useState("");
  const [mainImage, setMainImage] = useState<File | null>(null);
  const [gallery, setGallery] = useState<FileList | null>(null);
  const [error, setError] = useState("");
  const [saving, setSaving] = useState(false);

  useEffect(() => {
    void api.admin
      .attributes(token)
      .then((list) => {
        setAttributeCatalog(list);
        if (!selectedAttributeId && list[0]) setSelectedAttributeId(String(list[0].id));
      })
      .catch(() => {
        // no-op, optional helper data
      });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [token]);

  const setField = <K extends keyof ProductFormValues>(key: K, value: ProductFormValues[K]) => {
    setValues((prev) => {
      const next = { ...prev, [key]: value };
      if (key === "name" && !slugTouched) next.slug = slugify(String(value));
      return next;
    });
  };

  const mainPreview = useMemo(() => {
    if (mainImage) return URL.createObjectURL(mainImage);
    return existingMainImage ? mediaOrPlaceholder(existingMainImage) : "";
  }, [mainImage, existingMainImage]);

  const onSubmit = async (e: FormEvent) => {
    e.preventDefault();
    setError("");
    if (!values.name.trim() || !values.sku.trim() || !values.category_id || !values.brand_id) {
      setError("Name, SKU, category, and brand are required.");
      return;
    }
    if (!values.selling_price) {
      setError("Selling price is required.");
      return;
    }

    const attributes = parseAttributes(attributeRows);
    const variants = parseVariants(variantRows);
    const stock = Number(values.stock || 0);
    const variantStockTotal = variants.reduce((sum, variant) => sum + (variant.stock || 0), 0);
    if (variants.length > 0 && variantStockTotal !== stock) {
      setError(`Variant stock total (${variantStockTotal}) must equal product stock (${stock}).`);
      return;
    }

    setSaving(true);
    try {
      if (mode === "create") {
        const fd = new FormData();
        appendFormPayload(fd, values);
        fd.set("attributes", JSON.stringify(attributes));
        fd.set("variants", JSON.stringify(variants));
        if (mainImage) fd.set("main_image", mainImage);
        if (gallery) {
          Array.from(gallery).forEach((file) => fd.append("images", file));
        }
        await api.admin.createProduct(fd, token);
        toast.success("Product created successfully.");
      } else if (productId) {
        await api.admin.updateProduct(
          productId,
          {
            ...valuesToUpdatePayload(values),
            attributes,
            variants,
          },
          token,
        );
        if (mainImage) {
          const fd = new FormData();
          fd.set("image", mainImage);
          fd.set("is_main", "1");
          await api.admin.uploadProductImage(productId, fd, token);
        }
        if (gallery) {
          for (const file of Array.from(gallery)) {
            const fd = new FormData();
            fd.set("image", file);
            fd.set("is_main", "0");
            await api.admin.uploadProductImage(productId, fd, token);
          }
        }
        toast.success("Product updated successfully.");
      }
      await refreshStore();
      router.push("/admin/products");
    } catch (err) {
      const message = err instanceof ApiError ? err.message : "Failed to save product.";
      setError(message);
      toast.error(message);
    } finally {
      setSaving(false);
    }
  };

  return (
    <form onSubmit={onSubmit} className="space-y-4">
      {error ? (
        <div className="rounded-xl border border-destructive/30 bg-destructive/10 px-4 py-3 text-sm text-destructive">
          {error}
        </div>
      ) : null}

      <Panel title="Product" description="Only API-supported fields">
        <FormGrid cols={2}>
          <Field label="Category *">
            <TextSelect value={values.category_id} onChange={(e) => setField("category_id", e.target.value)} required>
              <option value="">Select category</option>
              {store.categories.map((c) => (
                <option key={c.id} value={c.id}>
                  {c.name}
                </option>
              ))}
            </TextSelect>
          </Field>
          <Field label="Brand *">
            <TextSelect value={values.brand_id} onChange={(e) => setField("brand_id", e.target.value)} required>
              <option value="">Select brand</option>
              {store.brands.map((b) => (
                <option key={b.id} value={b.id}>
                  {b.name}
                </option>
              ))}
            </TextSelect>
          </Field>
          <Field label="SKU *">
            <TextInput value={values.sku} onChange={(e) => setField("sku", e.target.value)} required />
          </Field>
          <Field label="Barcode">
            <TextInput value={values.barcode} onChange={(e) => setField("barcode", e.target.value)} />
          </Field>
          <Field label="Name *">
            <TextInput value={values.name} onChange={(e) => setField("name", e.target.value)} required />
          </Field>
          <Field label="Slug">
            <TextInput
              value={values.slug}
              onChange={(e) => {
                setSlugTouched(true);
                setField("slug", e.target.value);
              }}
            />
          </Field>
          <Field label="Description" className="sm:col-span-2">
            <TextTextarea value={values.description} onChange={(e) => setField("description", e.target.value)} rows={4} />
          </Field>
          <Field label="Cost Price">
            <TextInput type="number" min="0" step="0.01" value={values.cost_price} onChange={(e) => setField("cost_price", e.target.value)} />
          </Field>
          <Field label="Selling Price *">
            <TextInput type="number" min="0" step="0.01" value={values.selling_price} onChange={(e) => setField("selling_price", e.target.value)} required />
          </Field>
          <Field label="Sale Price">
            <TextInput type="number" min="0" step="0.01" value={values.sale_price} onChange={(e) => setField("sale_price", e.target.value)} />
          </Field>
          <Field label="Stock">
            <TextInput type="number" min="0" value={values.stock} onChange={(e) => setField("stock", e.target.value)} />
          </Field>
          <Field label="Weight">
            <TextInput type="number" min="0" step="0.01" value={values.weight} onChange={(e) => setField("weight", e.target.value)} />
          </Field>
          <Field label="Status">
            <TextSelect value={values.status} onChange={(e) => setField("status", e.target.value as "active" | "inactive")}>
              <option value="active">Active</option>
              <option value="inactive">Inactive</option>
            </TextSelect>
          </Field>
          <Field label="Featured">
            <label className="flex h-[38px] items-center gap-2 text-sm">
              <input
                type="checkbox"
                checked={values.featured}
                onChange={(e) => setField("featured", e.target.checked)}
                className="h-4 w-4 rounded border-border"
              />
              Featured product
            </label>
          </Field>
        </FormGrid>
      </Panel>

      <Panel title="Media" description="main_image + images">
        <FormGrid cols={2}>
          <Field label="Main image">
            <TextInput type="file" accept="image/*" onChange={(e) => setMainImage(e.target.files?.[0] || null)} />
            {mainPreview ? (
              // eslint-disable-next-line @next/next/no-img-element
              <img src={mainPreview} alt="Main preview" className="mt-2 h-28 w-28 rounded-lg object-cover border border-border" />
            ) : null}
          </Field>
          <Field label="Gallery images">
            <TextInput type="file" accept="image/*" multiple onChange={(e) => setGallery(e.target.files)} />
            {existingGallery.length > 0 ? (
              <div className="mt-2 flex flex-wrap gap-2">
                {existingGallery.map((src) => (
                  // eslint-disable-next-line @next/next/no-img-element
                  <img key={src} src={mediaOrPlaceholder(src)} alt="" className="h-16 w-16 rounded-lg object-cover border border-border" />
                ))}
              </div>
            ) : null}
          </Field>
        </FormGrid>
      </Panel>

      <Panel title="Attributes" description="Format: name + values[]">
        <div className="space-y-3">
          {attributeRows.map((row, idx) => (
            <div key={`attribute-${idx}`} className="grid gap-2 sm:grid-cols-[1fr_2fr_auto]">
              <TextInput
                placeholder="Attribute name (e.g. Color)"
                value={row.name}
                onChange={(e) =>
                  setAttributeRows((prev) => prev.map((item, i) => (i === idx ? { ...item, name: e.target.value } : item)))
                }
              />
              <TextInput
                placeholder="Values comma separated (e.g. White, Blue)"
                value={row.values}
                onChange={(e) =>
                  setAttributeRows((prev) => prev.map((item, i) => (i === idx ? { ...item, values: e.target.value } : item)))
                }
              />
              <AdminButton
                variant="danger"
                onClick={() =>
                  setAttributeRows((prev) => (prev.length === 1 ? [{ name: "", values: "" }] : prev.filter((_, i) => i !== idx)))
                }
              >
                Remove
              </AdminButton>
            </div>
          ))}
          <AdminButton variant="secondary" onClick={() => setAttributeRows((prev) => [...prev, { name: "", values: "" }])}>
            Add Attribute
          </AdminButton>

          <div className="mt-2 rounded-xl border border-border bg-secondary/20 p-3">
            <p className="text-xs font-semibold">Attribute Library (optional)</p>
            <div className="mt-2 grid gap-2 sm:grid-cols-3">
              <TextInput placeholder="Create attribute name" value={newAttributeName} onChange={(e) => setNewAttributeName(e.target.value)} />
              <AdminButton
                variant="secondary"
                onClick={() => {
                  if (!newAttributeName.trim()) return;
                  void api.admin
                    .createAttribute({ name: newAttributeName.trim() }, token)
                    .then((created) => {
                      setAttributeCatalog((prev) => [...prev, { ...created, values: [] }]);
                      setSelectedAttributeId(String(created.id));
                      setNewAttributeName("");
                      toast.success("Attribute created.");
                    })
                    .catch((err) => toast.error(err instanceof ApiError ? err.message : "Failed to create attribute."));
                }}
              >
                Save Attribute
              </AdminButton>
            </div>
            <div className="mt-2 grid gap-2 sm:grid-cols-3">
              <TextSelect value={selectedAttributeId} onChange={(e) => setSelectedAttributeId(e.target.value)}>
                <option value="">Select attribute</option>
                {attributeCatalog.map((attribute) => (
                  <option key={attribute.id} value={String(attribute.id)}>
                    {attribute.name}
                  </option>
                ))}
              </TextSelect>
              <TextInput placeholder="Create value (e.g. Red)" value={newAttributeValue} onChange={(e) => setNewAttributeValue(e.target.value)} />
              <AdminButton
                variant="secondary"
                onClick={() => {
                  if (!selectedAttributeId || !newAttributeValue.trim()) return;
                  void api.admin
                    .createAttributeValue(selectedAttributeId, { value: newAttributeValue.trim() }, token)
                    .then((created) => {
                      setAttributeCatalog((prev) =>
                        prev.map((item) =>
                          String(item.id) === selectedAttributeId
                            ? { ...item, values: [...(item.values || []), created] }
                            : item,
                        ),
                      );
                      setNewAttributeValue("");
                      toast.success("Attribute value created.");
                    })
                    .catch((err) => toast.error(err instanceof ApiError ? err.message : "Failed to create value."));
                }}
              >
                Save Value
              </AdminButton>
            </div>
          </div>
        </div>
      </Panel>

      <Panel title="Variants" description="sku, price, stock, attributes (Name:Value)">
        <div className="space-y-3">
          {variantRows.map((row, idx) => (
            <div key={`variant-${idx}`} className="rounded-lg border border-border p-3">
              <div className="grid gap-2 sm:grid-cols-4">
                <TextInput
                  placeholder="Variant SKU"
                  value={row.sku}
                  onChange={(e) =>
                    setVariantRows((prev) => prev.map((item, i) => (i === idx ? { ...item, sku: e.target.value } : item)))
                  }
                />
                <TextInput
                  type="number"
                  min="0"
                  step="0.01"
                  placeholder="Price"
                  value={row.price}
                  onChange={(e) =>
                    setVariantRows((prev) => prev.map((item, i) => (i === idx ? { ...item, price: e.target.value } : item)))
                  }
                />
                <TextInput
                  type="number"
                  min="0"
                  placeholder="Stock"
                  value={row.stock}
                  onChange={(e) =>
                    setVariantRows((prev) => prev.map((item, i) => (i === idx ? { ...item, stock: e.target.value } : item)))
                  }
                />
                <AdminButton
                  variant="danger"
                  onClick={() =>
                    setVariantRows((prev) =>
                      prev.length === 1
                        ? [{ sku: "", price: "", stock: "", attributes: "" }]
                        : prev.filter((_, i) => i !== idx),
                    )
                  }
                >
                  Remove
                </AdminButton>
              </div>
              <TextInput
                className="mt-2"
                placeholder="Attributes: Color:White, Capacity:1.5 Ton"
                value={row.attributes}
                onChange={(e) =>
                  setVariantRows((prev) =>
                    prev.map((item, i) => (i === idx ? { ...item, attributes: e.target.value } : item)),
                  )
                }
              />
            </div>
          ))}
          <div className="flex flex-wrap gap-2">
            <AdminButton
              variant="secondary"
              onClick={() => setVariantRows((prev) => [...prev, { sku: "", price: "", stock: "", attributes: "" }])}
            >
              Add Variant
            </AdminButton>
            <span className="self-center text-xs text-muted-foreground">
              Variant stock total: {parseVariants(variantRows).reduce((sum, item) => sum + item.stock, 0)}
            </span>
          </div>
        </div>
      </Panel>

      <div className="flex flex-wrap gap-2">
        <AdminButton type="submit">{saving ? "Saving..." : mode === "create" ? "Create product" : "Save changes"}</AdminButton>
        <AdminButton href="/admin/products" variant="secondary">
          Cancel
        </AdminButton>
      </div>
    </form>
  );
}
