"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import Link from "next/link";
import { useParams, useRouter } from "next/navigation";
import { Loader2, Plus, Trash2, Upload } from "lucide-react";
import MainTitle from "@/components/layout/dashboard/main-title";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import DataService from "@/config/axios";
import { useRequireSuperAdmin } from "@/hooks/use-require-super-admin";
import { getApiErrorMessage } from "@/lib/api-error";
import { uploadAdminProductImage } from "@/lib/upload-admin-product-image";
import { toast } from "sonner";
import { cn } from "@/lib/utils";
import { BlogRichTextEditor } from "@/features/super-admin/blogs/blog-rich-text-editor";

function slugify(value: string) {
  return value
    .toLowerCase()
    .trim()
    .replace(/[^a-z0-9]+/g, "-")
    .replace(/(^-|-$)+/g, "");
}

function htmlToPlain(html: string) {
  return html
    .replace(/<[^>]+>/g, " ")
    .replace(/&nbsp;/gi, " ")
    .replace(/\s+/g, " ")
    .trim();
}

type Category = { _id: string; name: string; slug: string };
type VariantValue = {
  label: string;
  priceModifier: number;
  salePrice: string;
  stock: string;
};
type VariantGroup = { name: string; values: VariantValue[] };

type FeatureRow = { label: string; value: string };

type ProductRow = {
  _id: string;
  title: string;
  slug?: string;
  metaTitle?: string;
  metaDescription?: string;
  description?: string;
  images?: string[];
  price: number;
  salePrice?: number | null;
  stock?: number;
  features?: (string | FeatureRow)[];
  variants?: VariantGroup[];
  shippingCost?: number;
  freeShipping?: boolean;
  expressShipping?: boolean;
  categories?: { _id: string }[];
  status: "draft" | "published";
};

function normalizeFeaturesFromApi(raw: ProductRow["features"]): FeatureRow[] {
  if (!Array.isArray(raw)) return [];
  return raw
    .map((f) => {
      if (typeof f === "string") {
        const t = f.trim();
        return t ? { label: "", value: t } : null;
      }
      if (f && typeof f === "object") {
        return {
          label: String(f.label ?? "").trim(),
          value: String(f.value ?? "").trim(),
        };
      }
      return null;
    })
    .filter((f): f is FeatureRow => f != null && (f.label.length > 0 || f.value.length > 0));
}

type Props = {
  productId: string | null;
};

export default function AdminProductEditorPage({ productId }: Props) {
  const ready = useRequireSuperAdmin();
  const router = useRouter();
  const params = useParams();
  const app = params.app as string;

  const isEdit = Boolean(productId);
  const listHref = `/${app}/admin/products`;

  const [loading, setLoading] = useState(true);
  const [categories, setCategories] = useState<Category[]>([]);
  const [imgUploading, setImgUploading] = useState(false);
  const [saving, setSaving] = useState(false);

  const [form, setForm] = useState({
    title: "",
    slug: "",
    metaTitle: "",
    metaDescription: "",
    description: "",
    images: [] as string[],
    price: "",
    salePrice: "",
    stock: "0",
    shippingCost: "0",
    freeShipping: false,
    expressShipping: false,
    features: [] as FeatureRow[],
    variants: [] as VariantGroup[],
    categoryId: "",
    status: "published" as "draft" | "published",
  });

  const loadCategories = useCallback(async () => {
    const res = await DataService.get("/admin/product-categories");
    const rows: Category[] = res.data?.data || [];
    setCategories(rows);
    return rows;
  }, []);

  const loadProduct = useCallback(async (id: string) => {
    const res = await DataService.get(`/admin/products/${id}`);
    return res.data?.data as ProductRow | undefined;
  }, []);

  useEffect(() => {
    if (!ready) return;
    let cancelled = false;
    (async () => {
      setLoading(true);
      try {
        const cats = await loadCategories();
        if (cancelled) return;
        if (productId) {
          const p = await loadProduct(productId);
          if (cancelled) return;
          if (!p) {
            toast.error("Product not found");
            router.replace(listHref);
            return;
          }
          setForm({
            title: p.title,
            slug: p.slug || "",
            metaTitle: p.metaTitle || "",
            metaDescription: p.metaDescription || "",
            description: p.description || "",
            images: p.images || [],
            price: String(p.price),
            salePrice: p.salePrice != null && p.salePrice >= 0 ? String(p.salePrice) : "",
            stock: String(p.stock ?? 0),
            shippingCost: String(p.shippingCost ?? 0),
            freeShipping: Boolean(p.freeShipping),
            expressShipping: Boolean(p.expressShipping),
            features: normalizeFeaturesFromApi(p.features),
            variants: (p.variants || []).map((g) => ({
              name: g.name,
              values: (g.values || []).map((v) => ({
                label: v.label,
                priceModifier: Number(v.priceModifier) || 0,
                salePrice:
                  v.salePrice != null && Number(v.salePrice) >= 0 ? String(v.salePrice) : "",
                stock: v.stock != null && Number(v.stock) >= 0 ? String(v.stock) : "",
              })),
            })),
            categoryId: (p.categories && p.categories[0]?._id) || "",
            status: p.status || "published",
          });
        } else {
          setForm({
            title: "",
            slug: "",
            metaTitle: "",
            metaDescription: "",
            description: "",
            images: [],
            price: "",
            salePrice: "",
            stock: "0",
            shippingCost: "0",
            freeShipping: false,
            expressShipping: false,
            features: [],
            variants: [],
            categoryId: cats[0]?._id || "",
            status: "published",
          });
        }
      } catch (e: unknown) {
        if (!cancelled) toast.error(getApiErrorMessage(e, "Failed to load"));
      } finally {
        if (!cancelled) setLoading(false);
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [ready, productId, loadProduct, loadCategories, listHref, router]);

  const addFeatureRow = () => {
    setForm((f) => ({
      ...f,
      features: [...f.features, { label: "", value: "" }],
    }));
  };

  const updateFeatureRow = (index: number, row: FeatureRow) => {
    setForm((f) => {
      const next = [...f.features];
      next[index] = row;
      return { ...f, features: next };
    });
  };

  const removeFeatureRow = (index: number) => {
    setForm((f) => ({ ...f, features: f.features.filter((_, i) => i !== index) }));
  };

  const addVariantGroup = () => {
    setForm((f) => ({
      ...f,
      variants: [
        ...f.variants,
        {
          name: "",
          values: [{ label: "", priceModifier: 0, salePrice: "", stock: "" }],
        },
      ],
    }));
  };

  const updateVariantGroup = (idx: number, g: VariantGroup) => {
    setForm((f) => {
      const next = [...f.variants];
      next[idx] = g;
      return { ...f, variants: next };
    });
  };

  const removeVariantGroup = (idx: number) => {
    setForm((f) => ({ ...f, variants: f.variants.filter((_, i) => i !== idx) }));
  };

  const onUploadImage = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    e.target.value = "";
    if (!file) return;
    try {
      setImgUploading(true);
      const url = await uploadAdminProductImage(file);
      setForm((f) => ({ ...f, images: [...f.images, url] }));
      toast.success("Image uploaded");
    } catch (err: unknown) {
      toast.error(err instanceof Error ? err.message : "Upload failed");
    } finally {
      setImgUploading(false);
    }
  };

  const saveProduct = async () => {
    if (!form.title.trim()) {
      toast.error("Title is required");
      return;
    }
    const priceNum = Number(form.price);
    if (!Number.isFinite(priceNum) || priceNum < 0) {
      toast.error("Valid price is required");
      return;
    }
    if (!form.categoryId) {
      toast.error("Select a category");
      return;
    }
    const saleRaw = form.salePrice.trim();
    const saleNum = saleRaw === "" ? null : Number(saleRaw);
    if (saleNum != null && (!Number.isFinite(saleNum) || saleNum < 0)) {
      toast.error("Sale price must be a valid number");
      return;
    }
    const stockNum = Number(form.stock);
    if (!Number.isFinite(stockNum) || stockNum < 0 || !Number.isInteger(stockNum)) {
      toast.error("Stock must be a whole number ≥ 0");
      return;
    }
    for (const g of form.variants) {
      if (!g.name.trim()) {
        toast.error("Each variant type needs a name");
        return;
      }
      for (const v of g.values) {
        if (!v.label.trim()) {
          toast.error("Each variant option needs a label");
          return;
        }
        const vs = v.salePrice.trim();
        if (vs !== "" && (!Number.isFinite(Number(vs)) || Number(vs) < 0)) {
          toast.error("Variant sale prices must be valid numbers");
          return;
        }
        const vst = v.stock.trim();
        if (vst !== "" && (!Number.isFinite(Number(vst)) || Number(vst) < 0 || !Number.isInteger(Number(vst)))) {
          toast.error("Variant stock must be a whole number ≥ 0 or empty");
          return;
        }
      }
    }

    const payload = {
      title: form.title.trim(),
      slug: form.slug.trim(),
      metaTitle: form.metaTitle.trim(),
      metaDescription: form.metaDescription.trim(),
      description: (() => {
        const raw = form.description.trim();
        return htmlToPlain(raw) ? raw : "";
      })(),
      images: form.images,
      price: priceNum,
      salePrice: saleNum,
      stock: stockNum,
      features: form.features.filter((r) => r.label.trim() || r.value.trim()),
      variants: form.variants.map((g) => ({
        name: g.name.trim(),
        values: g.values.map((v) => ({
          label: v.label.trim(),
          priceModifier: Number(v.priceModifier) || 0,
          salePrice: (() => {
            const t = v.salePrice.trim();
            if (t === "") return null;
            const n = Number(t);
            return Number.isFinite(n) && n >= 0 ? n : null;
          })(),
          stock: (() => {
            const t = v.stock.trim();
            if (t === "") return null;
            const n = Math.floor(Number(t));
            return Number.isFinite(n) && n >= 0 ? n : null;
          })(),
        })),
      })),
      shippingCost: Number(form.shippingCost) || 0,
      freeShipping: form.freeShipping,
      expressShipping: form.expressShipping,
      categories: form.categoryId ? [form.categoryId] : [],
      status: form.status,
    };

    try {
      setSaving(true);
      if (isEdit && productId) {
        await DataService.patch(`/admin/products/${productId}`, payload);
        toast.success("Product updated");
      } else {
        await DataService.post("/admin/products", payload);
        toast.success("Product created");
      }
      router.push(listHref);
    } catch (e: unknown) {
      toast.error(getApiErrorMessage(e, "Could not save product"));
    } finally {
      setSaving(false);
    }
  };

  const slugPreview = useMemo(() => {
    const raw = form.slug.trim() || form.title.trim();
    return raw ? slugify(raw) : "";
  }, [form.slug, form.title]);

  if (!ready || loading) {
    return <div className="rounded-md border bg-white p-8 text-center text-gray-500">Loading…</div>;
  }

  return (
    <div className="space-y-6">
      <div className="flex flex-wrap items-center justify-between gap-3">
        <MainTitle title={isEdit ? "Edit product" : "New product"} />
        <Button variant="outline" asChild>
          <Link href={listHref}>Back to list</Link>
        </Button>
      </div>

      <div className="grid gap-6 rounded-md border bg-white p-6">
        <div className="grid gap-2">
          <Label htmlFor="prod-title">Title</Label>
          <Input
            id="prod-title"
            value={form.title}
            onChange={(e) => setForm((f) => ({ ...f, title: e.target.value }))}
          />
        </div>

        <div className="rounded-md border border-dashed bg-slate-50/80 p-4 space-y-4">
          <p className="text-sm font-medium text-slate-800">SEO &amp; URL</p>
          <div className="grid gap-2">
            <Label htmlFor="prod-slug">Slug</Label>
            <Input
              id="prod-slug"
              placeholder="e.g. blue-widget (leave empty to auto-generate from title on create)"
              value={form.slug}
              onChange={(e) => setForm((f) => ({ ...f, slug: e.target.value }))}
            />
            {slugPreview ? (
              <p className="text-xs text-gray-500">
                URL path: <span className="font-mono text-gray-700">/product/{slugPreview}</span>
              </p>
            ) : null}
          </div>
          <div className="grid gap-2">
            <Label htmlFor="prod-meta-title">Meta title</Label>
            <Input
              id="prod-meta-title"
              placeholder="Search / browser title override"
              value={form.metaTitle}
              onChange={(e) => setForm((f) => ({ ...f, metaTitle: e.target.value }))}
            />
          </div>
          <div className="grid gap-2">
            <Label htmlFor="prod-meta-desc">Meta description</Label>
            <Textarea
              id="prod-meta-desc"
              rows={3}
              placeholder="Short summary for search results"
              value={form.metaDescription}
              onChange={(e) => setForm((f) => ({ ...f, metaDescription: e.target.value }))}
            />
          </div>
        </div>

        <div className="grid gap-2">
          <Label>Description</Label>
          <BlogRichTextEditor
            value={form.description}
            onChange={(html) => setForm((f) => ({ ...f, description: html }))}
            placeholder="Product description (formatting, lists, and links are supported)…"
          />
        </div>

        <div className="grid gap-2">
          <Label>Images</Label>
          <div className="flex flex-wrap gap-2">
            {form.images.map((url, i) => (
              <div
                key={`${url}-${i}`}
                className="relative flex h-24 w-24 items-center justify-center overflow-hidden rounded border bg-gray-50 text-xs"
              >
                {/* eslint-disable-next-line @next/next/no-img-element */}
                <img src={url} alt="" className="max-h-full max-w-full object-contain" />
                <button
                  type="button"
                  className="absolute right-1 top-1 rounded bg-white/90 p-1 shadow"
                  onClick={() =>
                    setForm((f) => ({ ...f, images: f.images.filter((_, j) => j !== i) }))
                  }
                  aria-label="Remove image"
                >
                  <Trash2 className="size-3 text-red-600" />
                </button>
              </div>
            ))}
            <label
              className={cn(
                "flex h-24 w-24 cursor-pointer flex-col items-center justify-center gap-1 rounded border border-dashed text-gray-500 hover:bg-gray-50",
                imgUploading && "pointer-events-none opacity-60",
              )}
            >
              {imgUploading ? (
                <Loader2 className="size-6 animate-spin" />
              ) : (
                <>
                  <Upload className="size-5" />
                  <span className="text-[10px]">Upload</span>
                </>
              )}
              <input type="file" accept="image/*" className="hidden" onChange={onUploadImage} />
            </label>
          </div>
        </div>

        <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
          <div className="grid gap-2">
            <Label>Price</Label>
            <Input
              type="number"
              min={0}
              step="0.01"
              value={form.price}
              onChange={(e) => setForm((f) => ({ ...f, price: e.target.value }))}
            />
          </div>
          <div className="grid gap-2">
            <Label>Sale price (optional)</Label>
            <Input
              type="number"
              min={0}
              step="0.01"
              placeholder="—"
              value={form.salePrice}
              onChange={(e) => setForm((f) => ({ ...f, salePrice: e.target.value }))}
            />
          </div>
          <div className="grid gap-2">
            <Label>Stock (main)</Label>
            <Input
              type="number"
              min={0}
              step={1}
              value={form.stock}
              onChange={(e) => setForm((f) => ({ ...f, stock: e.target.value }))}
            />
          </div>
          <div className="grid gap-2">
            <Label>Shipping cost (per unit)</Label>
            <Input
              type="number"
              min={0}
              step="0.01"
              value={form.shippingCost}
              onChange={(e) => setForm((f) => ({ ...f, shippingCost: e.target.value }))}
            />
          </div>
        </div>

        <div className="rounded-md border border-dashed bg-slate-50/80 p-4">
          <p className="text-sm font-medium text-slate-800">Listing badges</p>
          <p className="mt-1 text-xs text-slate-500">
            Choose which shipping badges appear on product cards and product detail pages.
          </p>
          <div className="mt-4 grid gap-3 sm:grid-cols-2">
            <label className="flex cursor-pointer items-start gap-3 rounded-md border bg-white p-3">
              <input
                type="checkbox"
                className="mt-1"
                checked={form.freeShipping}
                onChange={(e) =>
                  setForm((f) => ({ ...f, freeShipping: e.target.checked }))
                }
              />
              <span>
                <span className="block text-sm font-medium text-slate-900">Free Shipping</span>
                <span className="mt-1 block text-xs text-slate-500">
                  Shows the green free shipping badge in listings.
                </span>
              </span>
            </label>
            <label className="flex cursor-pointer items-start gap-3 rounded-md border bg-white p-3">
              <input
                type="checkbox"
                className="mt-1"
                checked={form.expressShipping}
                onChange={(e) =>
                  setForm((f) => ({ ...f, expressShipping: e.target.checked }))
                }
              />
              <span>
                <span className="block text-sm font-medium text-slate-900">Express</span>
                <span className="mt-1 block text-xs text-slate-500">
                  Shows the blue express badge in listings.
                </span>
              </span>
            </label>
          </div>
        </div>

        <div className="grid gap-2">
          <Label>Status</Label>
          <Select
            value={form.status}
            onValueChange={(v) => setForm((f) => ({ ...f, status: v as "draft" | "published" }))}
          >
            <SelectTrigger className="max-w-xs">
              <SelectValue />
            </SelectTrigger>
            <SelectContent>
              <SelectItem value="published">Published</SelectItem>
              <SelectItem value="draft">Draft</SelectItem>
            </SelectContent>
          </Select>
        </div>

        <div className="grid gap-2">
          <Label>Category</Label>
          {categories.length === 0 ? (
            <p className="text-sm text-gray-500">Create categories in the Products admin tab first.</p>
          ) : (
            <Select
              value={form.categoryId}
              onValueChange={(v) => setForm((f) => ({ ...f, categoryId: v }))}
            >
              <SelectTrigger className="max-w-xs">
                <SelectValue placeholder="Select category" />
              </SelectTrigger>
              <SelectContent>
                {categories.map((c) => (
                  <SelectItem key={c._id} value={c._id}>
                    {c.name}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          )}
        </div>

        <div className="grid gap-3">
          <div className="flex items-center justify-between gap-2">
            <Label>Features</Label>
            <Button type="button" variant="outline" size="sm" onClick={addFeatureRow}>
              <Plus className="mr-1 size-4" />
              Add feature
            </Button>
          </div>
          <div className="space-y-2">
            {form.features.length === 0 ? (
              <p className="text-sm text-gray-500">No features yet. Add rows with a label and value.</p>
            ) : (
              form.features.map((feat, i) => (
                <div
                  key={i}
                  className="flex flex-col gap-2 rounded-md border bg-white p-3 sm:flex-row sm:items-end"
                >
                  <div className="grid flex-1 gap-1.5">
                    <Label className="text-xs">Label</Label>
                    <Input
                      placeholder="e.g. Material"
                      value={feat.label}
                      onChange={(e) =>
                        updateFeatureRow(i, { ...feat, label: e.target.value })
                      }
                    />
                  </div>
                  <div className="grid flex-1 gap-1.5">
                    <Label className="text-xs">Value</Label>
                    <Input
                      placeholder="e.g. Cotton"
                      value={feat.value}
                      onChange={(e) =>
                        updateFeatureRow(i, { ...feat, value: e.target.value })
                      }
                    />
                  </div>
                  <Button
                    type="button"
                    variant="outline"
                    size="icon"
                    className="shrink-0"
                    onClick={() => removeFeatureRow(i)}
                    aria-label="Remove feature"
                  >
                    <Trash2 className="size-4 text-red-600" />
                  </Button>
                </div>
              ))
            )}
          </div>
        </div>

        <div className="space-y-3">
          <div className="flex items-center justify-between gap-2">
            <Label>Variants (e.g. Color, Size)</Label>
            <Button type="button" variant="outline" size="sm" onClick={addVariantGroup}>
              <Plus className="mr-1 size-4" />
              Add variant type
            </Button>
          </div>
          {form.variants.map((g, gi) => (
            <div key={gi} className="rounded-md border p-4 space-y-3">
              <div className="flex flex-wrap items-end gap-2">
                <div className="grid flex-1 gap-2 min-w-[160px]">
                  <Label className="text-xs">Type name</Label>
                  <Input
                    placeholder="Color"
                    value={g.name}
                    onChange={(e) =>
                      updateVariantGroup(gi, { ...g, name: e.target.value })
                    }
                  />
                </div>
                <Button type="button" variant="ghost" size="icon" onClick={() => removeVariantGroup(gi)}>
                  <Trash2 className="size-4 text-red-600" />
                </Button>
              </div>
              <div className="space-y-2">
                <Label className="text-xs">Options</Label>
                {g.values.map((v, vi) => (
                  <div key={vi} className="flex flex-wrap gap-2 items-end">
                    <Input
                      placeholder="Label (e.g. Red)"
                      className="max-w-[200px]"
                      value={v.label}
                      onChange={(e) => {
                        const values = [...g.values];
                        values[vi] = { ...v, label: e.target.value };
                        updateVariantGroup(gi, { ...g, values });
                      }}
                    />
                    <div className="grid gap-1">
                      <span className="text-[10px] text-gray-500">Price +/-</span>
                      <Input
                        type="number"
                        step="0.01"
                        className="w-28"
                        value={v.priceModifier}
                        onChange={(e) => {
                          const values = [...g.values];
                          values[vi] = { ...v, priceModifier: Number(e.target.value) || 0 };
                          updateVariantGroup(gi, { ...g, values });
                        }}
                      />
                    </div>
                    <div className="grid gap-1">
                      <span className="text-[10px] text-gray-500">Sale (opt.)</span>
                      <Input
                        type="number"
                        min={0}
                        step="0.01"
                        placeholder="—"
                        className="w-28"
                        value={v.salePrice}
                        onChange={(e) => {
                          const values = [...g.values];
                          values[vi] = { ...v, salePrice: e.target.value };
                          updateVariantGroup(gi, { ...g, values });
                        }}
                      />
                    </div>
                    <div className="grid gap-1">
                      <span className="text-[10px] text-gray-500">Stock (opt.)</span>
                      <Input
                        type="number"
                        min={0}
                        step={1}
                        placeholder="—"
                        className="w-24"
                        value={v.stock}
                        onChange={(e) => {
                          const values = [...g.values];
                          values[vi] = { ...v, stock: e.target.value };
                          updateVariantGroup(gi, { ...g, values });
                        }}
                      />
                    </div>
                    <Button
                      type="button"
                      variant="outline"
                      size="icon"
                      onClick={() => {
                        const values = g.values.filter((_, j) => j !== vi);
                        updateVariantGroup(gi, {
                          ...g,
                          values: values.length
                            ? values
                            : [{ label: "", priceModifier: 0, salePrice: "", stock: "" }],
                        });
                      }}
                    >
                      <Trash2 className="size-4" />
                    </Button>
                  </div>
                ))}
                <Button
                  type="button"
                  variant="secondary"
                  size="sm"
                  onClick={() =>
                    updateVariantGroup(gi, {
                      ...g,
                      values: [...g.values, { label: "", priceModifier: 0, salePrice: "", stock: "" }],
                    })
                  }
                >
                  Add option
                </Button>
              </div>
            </div>
          ))}
        </div>

        <div className="flex gap-3 pt-4">
          <Button onClick={saveProduct} disabled={saving}>
            {saving ? "Saving…" : "Save product"}
          </Button>
          <Button variant="outline" asChild>
            <Link href={listHref}>Cancel</Link>
          </Button>
        </div>
      </div>
    </div>
  );
}
