"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import Link from "next/link";
import { useParams, useRouter, useSearchParams } from "next/navigation";
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 DataService from "@/config/axios";
import { useRequireSuperAdmin } from "@/hooks/use-require-super-admin";
import { getApiErrorMessage } from "@/lib/api-error";
import { uploadAdminServiceImage } from "@/lib/upload-admin-service-image";
import { toast } from "sonner";
import { BlogRichTextEditor } from "@/features/super-admin/blogs/blog-rich-text-editor";
import { cn } from "@/lib/utils";
import type { ServiceCategoryType } from "./services-admin";

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();
}

function parseCategoryType(raw: string | null): ServiceCategoryType | null {
  if (raw === "service" || raw === "solution") return raw;
  return null;
}

type Category = { _id: string; name: string; slug: string; categoryType?: ServiceCategoryType };

type ItemRow = {
  _id: string;
  title: string;
  slug: string;
  excerpt?: string;
  content: string;
  status: "draft" | "published";
  category?: { _id: string; name: string; slug: string; categoryType?: ServiceCategoryType } | null;
  icon?: string;
  banner?: string;
  metaTitle?: string;
  metaDescription?: string;
  metaKeywords?: string[];
  tags?: string[];
};

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

type FieldErrors = {
  title?: string;
  category?: string;
  content?: string;
};

function validateForm(
  form: { title: string; content: string; category: string },
  categoryCount: number,
): FieldErrors {
  const errors: FieldErrors = {};
  if (!form.title.trim()) {
    errors.title = "Title is required.";
  }
  if (categoryCount === 0) {
    errors.category = "Create at least one category first.";
  } else if (!form.category) {
    errors.category = "Please select a category.";
  }
  if (!htmlToPlain(form.content)) {
    errors.content = "Content is required.";
  }
  return errors;
}

export default function AdminServiceEditorPage({ itemId }: Props) {
  const ready = useRequireSuperAdmin();
  const router = useRouter();
  const params = useParams();
  const searchParams = useSearchParams();
  const app = params.app as string;

  const categoryType = parseCategoryType(searchParams.get("type")) ?? "service";
  const listHref = `/${app}/admin/services`;

  const isEdit = Boolean(itemId);
  const [loading, setLoading] = useState(true);
  const [categories, setCategories] = useState<Category[]>([]);
  const [editSlug, setEditSlug] = useState<string | null>(null);
  const [iconUploading, setIconUploading] = useState(false);
  const [bannerUploading, setBannerUploading] = useState(false);
  const [saving, setSaving] = useState(false);
  const [fieldErrors, setFieldErrors] = useState<FieldErrors>({});
  const [form, setForm] = useState({
    title: "",
    slug: "",
    metaTitle: "",
    metaDescription: "",
    metaKeywords: "",
    tagsInput: "",
    content: "",
    category: "",
    status: "published" as "draft" | "published",
    icon: "",
    banner: "",
  });

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

  const loadItem = useCallback(async (id: string) => {
    const res = await DataService.get(`/admin/service-items/${id}`);
    return res.data?.data as ItemRow | undefined;
  }, []);

  useEffect(() => {
    if (!ready) return;
    let cancelled = false;
    (async () => {
      setLoading(true);
      try {
        const cats = await loadCategories();
        if (cancelled) return;
        if (itemId) {
          const row = await loadItem(itemId);
          if (cancelled) return;
          if (!row) {
            toast.error("Item not found");
            router.replace(listHref);
            return;
          }
          if (row.category?.categoryType && row.category.categoryType !== categoryType) {
            toast.error("This item belongs to a different section");
            router.replace(listHref);
            return;
          }
          setEditSlug(row.slug);
          setForm({
            title: row.title,
            slug: row.slug || "",
            metaTitle: row.metaTitle || "",
            metaDescription: row.metaDescription ?? row.excerpt ?? "",
            metaKeywords: Array.isArray(row.metaKeywords) ? row.metaKeywords.join(", ") : "",
            tagsInput: (row.tags || []).join(", "),
            content: row.content,
            category: row.category?._id || "",
            status: row.status || "published",
            icon: row.icon || "",
            banner: row.banner || "",
          });
        } else {
          setEditSlug(null);
          setForm({
            title: "",
            slug: "",
            metaTitle: "",
            metaDescription: "",
            metaKeywords: "",
            tagsInput: "",
            content: "",
            category: cats[0]?._id || "",
            status: "published",
            icon: "",
            banner: "",
          });
        }
      } catch (e: unknown) {
        if (!cancelled) toast.error(getApiErrorMessage(e, "Failed to load"));
      } finally {
        if (!cancelled) setLoading(false);
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [ready, itemId, loadItem, loadCategories, listHref, router, categoryType]);

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

  const typeTitle = categoryType === "service" ? "Service" : "Solution";

  const save = async () => {
    const errors = validateForm(form, categories.length);
    if (Object.keys(errors).length > 0) {
      setFieldErrors(errors);
      const first = errors.title
        ? "field-title"
        : errors.category
          ? "field-category"
          : errors.content
            ? "field-content"
            : null;
      if (first) {
        requestAnimationFrame(() =>
          document.getElementById(first)?.scrollIntoView({ behavior: "smooth", block: "center" }),
        );
      }
      return;
    }
    setFieldErrors({});

    try {
      setSaving(true);
      const metaDesc = form.metaDescription.trim();
      const tags = form.tagsInput
        .split(",")
        .map((t) => t.trim())
        .filter(Boolean);
      const payload = {
        title: form.title.trim(),
        slug: form.slug.trim() || undefined,
        excerpt: metaDesc,
        metaTitle: form.metaTitle.trim(),
        metaDescription: metaDesc,
        metaKeywords: form.metaKeywords
          .split(",")
          .map((k) => k.trim())
          .filter(Boolean),
        tags,
        content: form.content.trim(),
        category: form.category,
        status: form.status,
        icon: form.icon.trim(),
        banner: form.banner.trim(),
      };
      if (isEdit && itemId) {
        await DataService.patch(`/admin/service-items/${itemId}`, payload);
        toast.success(`${typeTitle} updated`);
      } else {
        await DataService.post("/admin/service-items", payload);
        toast.success(`${typeTitle} created`);
      }
      router.push(listHref);
    } catch (e: unknown) {
      toast.error(getApiErrorMessage(e, "Could not save"));
    } finally {
      setSaving(false);
    }
  };

  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">
      <MainTitle title={isEdit ? `Edit ${typeTitle.toLowerCase()}` : `Add ${typeTitle.toLowerCase()}`} goBack>
        <Button variant="outline" asChild>
          <Link href={listHref}>Back to list</Link>
        </Button>
      </MainTitle>

      <div className="rounded-lg border bg-white p-6 shadow-sm">
        <div className="mx-auto grid max-w-3xl gap-4">
          <div id="field-title" className="grid gap-2">
            <Label htmlFor="svc-title">
              Title <span className="text-destructive">*</span>
            </Label>
            <Input
              id="svc-title"
              aria-invalid={Boolean(fieldErrors.title)}
              className={cn(fieldErrors.title && "border-destructive focus-visible:ring-destructive")}
              value={form.title}
              onChange={(e) => {
                setForm((p) => ({ ...p, title: e.target.value }));
                setFieldErrors((p) => ({ ...p, title: undefined }));
              }}
            />
            {fieldErrors.title ? (
              <p className="text-sm text-destructive" role="alert">
                {fieldErrors.title}
              </p>
            ) : null}
          </div>

          <div id="field-category" className="grid gap-2">
            <Label htmlFor="svc-category">
              Category <span className="text-destructive">*</span>
            </Label>
            <select
              id="svc-category"
              aria-invalid={Boolean(fieldErrors.category)}
              className={cn(
                "h-10 w-full rounded-md border border-input bg-background px-3 text-sm",
                fieldErrors.category && "border-destructive",
              )}
              value={form.category}
              onChange={(e) => {
                setForm((p) => ({ ...p, category: e.target.value }));
                setFieldErrors((p) => ({ ...p, category: undefined }));
              }}
            >
              <option value="">Select category</option>
              {categories.map((c) => (
                <option key={c._id} value={c._id}>
                  {c.name}
                </option>
              ))}
            </select>
            {fieldErrors.category ? (
              <p className="text-sm text-destructive" role="alert">
                {fieldErrors.category}
              </p>
            ) : null}
          </div>

          <div className="grid gap-2">
            <Label>Tags</Label>
            <Input
              placeholder="e.g. consulting, support"
              value={form.tagsInput}
              onChange={(e) => setForm((p) => ({ ...p, tagsInput: e.target.value }))}
            />
            <p className="text-xs text-muted-foreground">Comma-separated</p>
          </div>

          <div className="grid gap-2">
            <Label>Meta title</Label>
            <Input
              value={form.metaTitle}
              onChange={(e) => setForm((p) => ({ ...p, metaTitle: e.target.value }))}
              placeholder="SEO title"
            />
          </div>

          <div className="grid gap-2">
            <Label>Slug</Label>
            <Input
              placeholder="Leave empty to auto-generate from meta title or title"
              value={form.slug}
              onChange={(e) => setForm((p) => ({ ...p, slug: e.target.value }))}
            />
            <div className="rounded-md border bg-muted/30 px-3 py-2 text-sm">
              <span className="text-muted-foreground">Preview</span>
              <div className="mt-0.5 font-mono text-black">{slugPreview || "—"}</div>
              {isEdit && editSlug ? (
                <p className="mt-1 text-xs text-muted-foreground">Stored slug: {editSlug}</p>
              ) : null}
            </div>
          </div>

          <div className="grid gap-2">
            <Label>Meta description</Label>
            <Textarea
              value={form.metaDescription}
              onChange={(e) => setForm((p) => ({ ...p, metaDescription: e.target.value }))}
              placeholder="SEO description"
              rows={3}
            />
          </div>

          <div className="grid gap-2">
            <Label>Meta keywords</Label>
            <Input
              placeholder="keyword1, keyword2"
              value={form.metaKeywords}
              onChange={(e) => setForm((p) => ({ ...p, metaKeywords: e.target.value }))}
            />
          </div>

          <div className="grid gap-2">
            <Label>Icon</Label>
            <div className="flex flex-col gap-3 sm:flex-row sm:items-start">
              {form.icon.trim() ? (
                /* eslint-disable-next-line @next/next/no-img-element -- admin preview of uploaded URL */
                <img
                  src={form.icon}
                  alt=""
                  className="size-20 shrink-0 rounded-md border border-slate-200 bg-slate-50 object-cover"
                />
              ) : (
                <div className="flex size-20 shrink-0 items-center justify-center rounded-md border border-dashed border-slate-200 bg-slate-50 text-center text-xs text-muted-foreground">
                  No icon
                </div>
              )}
              <div className="flex min-w-0 flex-1 flex-col gap-2">
                <div className="flex flex-wrap items-center gap-2">
                  <Input
                    readOnly
                    className="min-w-[12rem] flex-1"
                    value={form.icon ? form.icon.split("/").pop() || form.icon : "No icon selected"}
                  />
                  <label className="inline-flex h-10 cursor-pointer items-center rounded-md border px-3 text-sm">
                    {iconUploading ? "Uploading..." : form.icon ? "Change" : "Upload"}
                    <input
                      type="file"
                      accept="image/*"
                      className="hidden"
                      disabled={iconUploading}
                      onChange={async (e) => {
                        const file = e.target.files?.[0];
                        e.target.value = "";
                        if (!file) return;
                        setIconUploading(true);
                        try {
                          const url = await uploadAdminServiceImage(file);
                          setForm((p) => ({ ...p, icon: url }));
                          toast.success("Icon uploaded");
                        } catch (err: unknown) {
                          toast.error(err instanceof Error ? err.message : "Upload failed");
                        } finally {
                          setIconUploading(false);
                        }
                      }}
                    />
                  </label>
                  {form.icon ? (
                    <Button type="button" variant="outline" onClick={() => setForm((p) => ({ ...p, icon: "" }))}>
                      Delete
                    </Button>
                  ) : null}
                </div>
              </div>
            </div>
          </div>

          <div className="grid gap-2">
            <Label>Banner</Label>
            <div className="flex flex-col gap-3 sm:flex-row sm:items-start">
              {form.banner.trim() ? (
                /* eslint-disable-next-line @next/next/no-img-element -- admin preview of uploaded URL */
                <img
                  src={form.banner}
                  alt=""
                  className="h-24 w-40 max-w-full shrink-0 rounded-md border border-slate-200 bg-slate-50 object-cover"
                />
              ) : (
                <div className="flex h-24 w-40 max-w-full shrink-0 items-center justify-center rounded-md border border-dashed border-slate-200 bg-slate-50 text-center text-xs text-muted-foreground">
                  No banner
                </div>
              )}
              <div className="flex min-w-0 flex-1 flex-col gap-2">
                <div className="flex flex-wrap items-center gap-2">
                  <Input
                    readOnly
                    className="min-w-[12rem] flex-1"
                    value={form.banner ? form.banner.split("/").pop() || form.banner : "No banner selected"}
                  />
                  <label className="inline-flex h-10 cursor-pointer items-center rounded-md border px-3 text-sm">
                    {bannerUploading ? "Uploading..." : form.banner ? "Change" : "Upload"}
                    <input
                      type="file"
                      accept="image/*"
                      className="hidden"
                      disabled={bannerUploading}
                      onChange={async (e) => {
                        const file = e.target.files?.[0];
                        e.target.value = "";
                        if (!file) return;
                        setBannerUploading(true);
                        try {
                          const url = await uploadAdminServiceImage(file);
                          setForm((p) => ({ ...p, banner: url }));
                          toast.success("Banner uploaded");
                        } catch (err: unknown) {
                          toast.error(err instanceof Error ? err.message : "Upload failed");
                        } finally {
                          setBannerUploading(false);
                        }
                      }}
                    />
                  </label>
                  {form.banner ? (
                    <Button type="button" variant="outline" onClick={() => setForm((p) => ({ ...p, banner: "" }))}>
                      Delete
                    </Button>
                  ) : null}
                </div>
              </div>
            </div>
          </div>

          <div id="field-content" className="grid gap-2">
            <Label>
              Content <span className="text-destructive">*</span>
            </Label>
            <div
              className={cn(
                "rounded-md",
                fieldErrors.content && "ring-2 ring-destructive ring-offset-2 ring-offset-background",
              )}
            >
              <BlogRichTextEditor
                value={form.content}
                onChange={(html) => {
                  setForm((p) => ({ ...p, content: html }));
                  setFieldErrors((p) => ({ ...p, content: undefined }));
                }}
              />
            </div>
            {fieldErrors.content ? (
              <p className="text-sm text-destructive" role="alert">
                {fieldErrors.content}
              </p>
            ) : null}
          </div>

          <div className="grid gap-2">
            <Label>Status</Label>
            <select
              className="h-10 w-full rounded-md border border-input bg-background px-3 text-sm"
              value={form.status}
              onChange={(e) =>
                setForm((p) => ({
                  ...p,
                  status: e.target.value === "draft" ? "draft" : "published",
                }))
              }
            >
              <option value="published">Published</option>
              <option value="draft">Draft</option>
            </select>
          </div>

          <div className="flex flex-wrap justify-end gap-2 border-t pt-6">
            <Button variant="outline" asChild>
              <Link href={listHref}>Cancel</Link>
            </Button>
            <Button onClick={save} disabled={iconUploading || bannerUploading || saving}>
              {saving ? "Saving…" : "Save"}
            </Button>
          </div>
        </div>
      </div>
    </div>
  );
}
