import { useState, useEffect, useCallback, useMemo, useRef } from "react";
import axios from "axios";
import { toast } from "sonner";
import { Loader2 } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
import {
  Pagination,
  PaginationContent,
  PaginationItem,
  PaginationLink,
  PaginationNext,
  PaginationPrevious,
  PaginationEllipsis,
} from "@/components/ui/pagination";
import { ProductSearch } from "@/components/product-editor/ProductSearch";
import { ProductEditForm, LAYOUT_ICONS } from "@/components/product-editor/ProductEditForm";
import type { LayoutMode } from "@/components/product-editor/ProductEditForm";
import type { SearchProduct, FieldOptions, FieldOption, LineOption, LandingExtra } from "@/components/product-editor/types";

const PER_PAGE = 20;
const PROD_IMG_HOST = "https://sbing.com";

/** Strip all HTML except <b>, </b>, and <br> tags */
function sanitizeHtml(html: string): string {
  return html.replace(/<\/?(?!b>|br\s*\/?>)[^>]*>/gi, "");
}

/** Strip all HTML tags for use in plain text contexts */
function stripHtml(html: string): string {
  return html.replace(/<[^>]*>/g, "");
}

export default function ProductEditor() {
  const [allProducts, setAllProducts] = useState<SearchProduct[]>([]);
  const [fieldOptions, setFieldOptions] = useState<FieldOptions | null>(null);
  const [isLoadingOptions, setIsLoadingOptions] = useState(true);
  const [isLoadingProducts, setIsLoadingProducts] = useState(false);
  const [layoutMode, setLayoutMode] = useState<LayoutMode>("full");
  const [page, _setPage] = useState(1);
  const topRef = useRef<HTMLDivElement>(null);
  const setPage = useCallback((v: number | ((p: number) => number)) => {
    _setPage(v);
    setTimeout(() => topRef.current?.scrollIntoView({ behavior: "smooth" }), 0);
  }, []);
  const [activeTab, setActiveTab] = useState("new");
  const [loadedTab, setLoadedTab] = useState<string | null>(null);

  // Line picker state
  const [lineCompany, setLineCompany] = useState<string>("");
  const [lineLine, setLineLine] = useState<string>("");
  const [lineSubline, setLineSubline] = useState<string>("");
  const [lineOptions, setLineOptions] = useState<LineOption[]>([]);
  const [sublineOptions, setSublineOptions] = useState<LineOption[]>([]);
  const [isLoadingLines, setIsLoadingLines] = useState(false);
  const [isLoadingSublines, setIsLoadingSublines] = useState(false);

  // Landing extras state
  const [landingExtras, setLandingExtras] = useState<Record<string, LandingExtra[]>>({});
  const [isLoadingExtras, setIsLoadingExtras] = useState(false);
  const [activeLandingItem, setActiveLandingItem] = useState<string | null>(null);

  // Abort controller for cancelling in-flight product requests
  const abortRef = useRef<AbortController | null>(null);

  const totalPages = Math.ceil(allProducts.length / PER_PAGE);
  const products = useMemo(
    () => allProducts.slice((page - 1) * PER_PAGE, page * PER_PAGE),
    [allProducts, page]
  );

  useEffect(() => {
    axios
      .get("/api/import/field-options")
      .then((res) => setFieldOptions(res.data))
      .catch((err) => {
        console.error("Failed to load field options:", err);
        toast.error("Failed to load field options");
      })
      .finally(() => setIsLoadingOptions(false));
    // Auto-load the default tab
    handleTabChange("new");
  }, []);

  // Load lines when company changes
  useEffect(() => {
    setLineLine("");
    setLineSubline("");
    setLineOptions([]);
    setSublineOptions([]);
    if (!lineCompany) return;
    setIsLoadingLines(true);
    axios
      .get(`/api/import/product-lines/${lineCompany}`)
      .then((res) => setLineOptions(res.data))
      .catch(() => setLineOptions([]))
      .finally(() => setIsLoadingLines(false));
  }, [lineCompany]);

  // Load sublines when line changes
  useEffect(() => {
    setLineSubline("");
    setSublineOptions([]);
    if (!lineLine) return;
    setIsLoadingSublines(true);
    axios
      .get(`/api/import/sublines/${lineLine}`)
      .then((res) => setSublineOptions(res.data))
      .catch(() => setSublineOptions([]))
      .finally(() => setIsLoadingSublines(false));
  }, [lineLine]);

  const handleSearchSelect = useCallback((product: SearchProduct) => {
    setAllProducts((prev) => {
      if (prev.some((p) => p.pid === product.pid)) return prev;
      return [product, ...prev];
    });
    setPage(1);
  }, []);

  const handleRemoveProduct = useCallback((pid: number) => {
    setAllProducts((prev) => prev.filter((p) => p.pid !== pid));
  }, []);

  const loadFeedProducts = useCallback(async (endpoint: string, label: string) => {
    abortRef.current?.abort();
    const controller = new AbortController();
    abortRef.current = controller;
    setAllProducts([]);
    setIsLoadingProducts(true);
    try {
      const res = await axios.get(`/api/import/${endpoint}`, { signal: controller.signal });
      setAllProducts(res.data);
      setPage(1);
      toast.success(`Loaded ${res.data.length} ${label} products`);
    } catch (e) {
      if (!axios.isCancel(e)) toast.error(`Failed to load ${label} products`);
    } finally {
      setIsLoadingProducts(false);
    }
  }, []);

  const loadLandingExtras = useCallback(async (catId: number, tabKey: string) => {
    if (landingExtras[tabKey]) return;
    setIsLoadingExtras(true);
    try {
      const res = await axios.get("/api/import/landing-extras", {
        params: { catId, sid: 0 },
      });
      setLandingExtras((prev) => ({ ...prev, [tabKey]: res.data }));
    } catch {
      console.error("Failed to load landing extras");
    } finally {
      setIsLoadingExtras(false);
    }
  }, [landingExtras]);

  const handleLandingClick = useCallback(async (extra: LandingExtra) => {
    abortRef.current?.abort();
    const controller = new AbortController();
    abortRef.current = controller;
    setActiveLandingItem(extra.path);
    setAllProducts([]);
    setIsLoadingProducts(true);
    try {
      const res = await axios.get("/api/import/path-products", {
        params: { path: extra.path },
        signal: controller.signal,
      });
      setAllProducts(res.data);
      setPage(1);
      toast.success(`Loaded ${res.data.length} products for ${stripHtml(extra.name)}`);
    } catch (e) {
      if (!axios.isCancel(e)) toast.error("Failed to load products for " + stripHtml(extra.name));
    } finally {
      setIsLoadingProducts(false);
      setActiveLandingItem(null);
    }
  }, []);

  // Auto-load when switching tabs
  const handleTabChange = useCallback((tab: string) => {
    setActiveTab(tab);
    if (tab === "new" && loadedTab !== "new") {
      setLoadedTab("new");
      loadFeedProducts("new-products", "new");
      loadLandingExtras(-2, "new");
    } else if (tab === "preorder" && loadedTab !== "preorder") {
      setLoadedTab("preorder");
      loadFeedProducts("preorder-products", "pre-order");
      loadLandingExtras(-16, "preorder");
    } else if (tab === "hidden" && loadedTab !== "hidden") {
      setLoadedTab("hidden");
      loadFeedProducts("hidden-new-products", "hidden");
    }
  }, [loadedTab, loadFeedProducts, loadLandingExtras]);

  const loadLineProducts = useCallback(async () => {
    if (!lineCompany || !lineLine) return;
    abortRef.current?.abort();
    const controller = new AbortController();
    abortRef.current = controller;
    setAllProducts([]);
    setIsLoadingProducts(true);
    try {
      const params: Record<string, string> = { company: lineCompany, line: lineLine };
      if (lineSubline) params.subline = lineSubline;
      const res = await axios.get("/api/import/line-products", { params, signal: controller.signal });
      setAllProducts(res.data);
      setPage(1);
      toast.success(`Loaded ${res.data.length} products`);
    } catch (e) {
      if (!axios.isCancel(e)) toast.error("Failed to load line products");
    } finally {
      setIsLoadingProducts(false);
    }
  }, [lineCompany, lineLine, lineSubline]);

  const renderLandingExtras = (tabKey: string) => {
    const extras = landingExtras[tabKey];
    if (!extras || extras.length === 0) return null;

    return (
      <div className="mb-4">
        <div className="flex gap-3 overflow-x-auto pb-2 items-start">
          {extras.map((extra) => (
            <button
              key={extra.extra_id}
              onClick={() => handleLandingClick(extra)}
              disabled={activeLandingItem === extra.path}
              className="flex-shrink-0 group relative w-28 text-left"
            >
              <div className="aspect-square w-full overflow-hidden rounded-lg border bg-card hover:bg-accent transition-colors relative">
                {extra.image && (
                  <img
                    src={extra.image.startsWith("/") ? PROD_IMG_HOST + extra.image : extra.image}
                    alt={stripHtml(extra.name)}
                    className="w-full h-full object-cover group-hover:scale-105 transition-transform"
                    loading="lazy"
                  />
                )}
                {activeLandingItem === extra.path && (
                  <div className="absolute inset-0 flex items-center justify-center bg-background/60">
                    <Loader2 className="h-4 w-4 animate-spin" />
                  </div>
                )}
              </div>
              <div className="pt-1 text-center">
                {(() => {
                  const parts = extra.name.split(/<br\s*\/?>/i).map(stripHtml);
                  return (
                    <div className="text-xs leading-snug">
                      {parts[0] && <span className="font-semibold">{parts[0]}</span>}
                      {parts[1] && <><br /><span className="font-normal">{parts[1]}</span></>}
                    </div>
                  );
                })()}
                {extra.top_text && (
                  <div
                    className="text-[10px] text-muted-foreground mt-0.5"
                    dangerouslySetInnerHTML={{ __html: sanitizeHtml(extra.top_text) }}
                  />
                )}
              </div>
            </button>
          ))}
        </div>
      </div>
    );
  };

  const renderPagination = () => {
    if (totalPages <= 1) return null;

    const getPageNumbers = () => {
      const pages: (number | "ellipsis")[] = [];
      if (totalPages <= 7) {
        for (let i = 1; i <= totalPages; i++) pages.push(i);
      } else {
        pages.push(1);
        if (page > 3) pages.push("ellipsis");
        for (let i = Math.max(2, page - 1); i <= Math.min(totalPages - 1, page + 1); i++) {
          pages.push(i);
        }
        if (page < totalPages - 2) pages.push("ellipsis");
        pages.push(totalPages);
      }
      return pages;
    };

    return (
      <Pagination>
        <PaginationContent>
          <PaginationItem>
            <PaginationPrevious
              onClick={() => setPage((p) => Math.max(1, p - 1))}
              className={page === 1 ? "pointer-events-none opacity-50" : "cursor-pointer"}
            />
          </PaginationItem>
          {getPageNumbers().map((p, i) =>
            p === "ellipsis" ? (
              <PaginationItem key={`e${i}`}>
                <PaginationEllipsis />
              </PaginationItem>
            ) : (
              <PaginationItem key={p}>
                <PaginationLink
                  isActive={p === page}
                  onClick={() => setPage(p)}
                  className="cursor-pointer"
                >
                  {p}
                </PaginationLink>
              </PaginationItem>
            )
          )}
          <PaginationItem>
            <PaginationNext
              onClick={() => setPage((p) => Math.min(totalPages, p + 1))}
              className={page === totalPages ? "pointer-events-none opacity-50" : "cursor-pointer"}
            />
          </PaginationItem>
        </PaginationContent>
      </Pagination>
    );
  };

  if (isLoadingOptions) {
    return (
      <div className="flex items-center justify-center h-64">
        <Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
      </div>
    );
  }

  return (
    <div className="container mx-auto py-6 max-w-4xl space-y-6">
      <div className="flex items-center justify-between">
        <div>
          <h1 className="text-2xl font-bold">Product Editor</h1>
        </div>
        <div className="flex items-center gap-3">
          <span className="text-sm text-muted-foreground">Layout: </span>
          <ToggleGroup
            type="single"
            value={layoutMode}
            onValueChange={(v) => { if (v) setLayoutMode(v as LayoutMode); }}
          >
            {LAYOUT_ICONS.map(({ mode, label, icon: Icon }) => (
              <Tooltip key={mode}>
                <TooltipTrigger asChild>
                  <ToggleGroupItem value={mode} size="sm" variant="outline">
                    <Icon className="h-4 w-4" />
                    <span className="text-xs">{label}</span>
                  </ToggleGroupItem>
                </TooltipTrigger>
                <TooltipContent side="bottom">{label}</TooltipContent>
              </Tooltip>
            ))}
          </ToggleGroup>
        </div>
      </div>

      <Tabs value={activeTab} onValueChange={handleTabChange}>
        <TabsList>
          <TabsTrigger value="new">New</TabsTrigger>
          <TabsTrigger value="preorder">Pre-Order</TabsTrigger>
          <TabsTrigger value="hidden">Hidden (New)</TabsTrigger>
          <TabsTrigger value="by-line">By Line</TabsTrigger>
          <TabsTrigger value="search">Search</TabsTrigger>
        </TabsList>

        <TabsContent value="search" className="mt-4">
          <ProductSearch onSelect={handleSearchSelect} />
        </TabsContent>

        <TabsContent value="new" className="mt-4">
          {isLoadingExtras && !landingExtras["new"] && (
            <div className="flex items-center gap-2 text-sm text-muted-foreground mb-3">
              <Loader2 className="h-4 w-4 animate-spin" />
              Loading featured lines...
            </div>
          )}
          {renderLandingExtras("new")}
          {isLoadingProducts && (
            <div className="flex items-center gap-2 text-sm text-muted-foreground">
              <Loader2 className="h-4 w-4 animate-spin" />
              Loading new products...
            </div>
          )}
        </TabsContent>

        <TabsContent value="preorder" className="mt-4">
          {isLoadingExtras && !landingExtras["preorder"] && (
            <div className="flex items-center gap-2 text-sm text-muted-foreground mb-3">
              <Loader2 className="h-4 w-4 animate-spin" />
              Loading featured lines...
            </div>
          )}
          {renderLandingExtras("preorder")}
          {isLoadingProducts && (
            <div className="flex items-center gap-2 text-sm text-muted-foreground">
              <Loader2 className="h-4 w-4 animate-spin" />
              Loading pre-order products...
            </div>
          )}
        </TabsContent>

        <TabsContent value="hidden" className="mt-4">
          {isLoadingProducts && (
            <div className="flex items-center gap-2 text-sm text-muted-foreground">
              <Loader2 className="h-4 w-4 animate-spin" />
              Loading hidden recently-created products...
            </div>
          )}
        </TabsContent>

        <TabsContent value="by-line" className="mt-4">
          <div className="flex items-center gap-3">
            <Select value={lineCompany} onValueChange={setLineCompany}>
              <SelectTrigger className="w-52">
                <SelectValue placeholder="Select company..." />
              </SelectTrigger>
              <SelectContent>
                {fieldOptions?.companies.map((c: FieldOption) => (
                  <SelectItem key={c.value} value={c.value}>{c.label}</SelectItem>
                ))}
              </SelectContent>
            </Select>
            <Select value={lineLine} onValueChange={setLineLine} disabled={!lineCompany || isLoadingLines}>
              <SelectTrigger className="w-52">
                <SelectValue placeholder={isLoadingLines ? "Loading..." : "Select line..."} />
              </SelectTrigger>
              <SelectContent>
                {lineOptions.map((l) => (
                  <SelectItem key={l.value} value={l.value}>{l.label}</SelectItem>
                ))}
              </SelectContent>
            </Select>
            {sublineOptions.length > 0 && (
              <Select value={lineSubline} onValueChange={setLineSubline} disabled={isLoadingSublines}>
                <SelectTrigger className="w-52">
                  <SelectValue placeholder={isLoadingSublines ? "Loading..." : "All sublines"} />
                </SelectTrigger>
                <SelectContent>
                  {sublineOptions.map((s) => (
                    <SelectItem key={s.value} value={s.value}>{s.label}</SelectItem>
                  ))}
                </SelectContent>
              </Select>
            )}
            <Button onClick={loadLineProducts} disabled={!lineLine || isLoadingProducts}>
              {isLoadingProducts && <Loader2 className="h-4 w-4 animate-spin mr-2" />}
              Load
            </Button>
          </div>
        </TabsContent>
      </Tabs>

      <div ref={topRef} />
      {renderPagination()}

      {products.length > 0 && fieldOptions && (
        <div className="space-y-4">
          {products.map((product) => (
            <ProductEditForm
              key={product.pid}
              product={product}
              fieldOptions={fieldOptions}
              layoutMode={layoutMode}
              onClose={() => handleRemoveProduct(product.pid)}
            />
          ))}
        </div>
      )}

      {renderPagination()}
    </div>
  );
}
