import { useCallback, useContext, useEffect, useMemo, useState } from "react";
import { apiFetch } from '@/utils/api';
import { Check, ChevronsUpDown, Loader2 } from "lucide-react";
import { toast } from "sonner";

import {
  Dialog,
  DialogContent,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";
import {
  Command,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
} from "@/components/ui/command";
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/components/ui/popover";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import config from "@/config";
import { createProductCategory, type CreateProductCategoryResponse } from "@/services/apiv2";
import { AuthContext } from "@/contexts/AuthContext";

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

export type CreatedCategoryInfo = {
  id?: string;
  name: string;
  parentId: string;
  type: "line" | "subline";
  response: CreateProductCategoryResponse;
};

interface CreateProductCategoryDialogProps {
  trigger: React.ReactNode;
  companies: Option[];
  defaultCompanyId?: string | null;
  defaultLineId?: string | null;
  environment?: "dev" | "prod";
  onCreated?: (info: CreatedCategoryInfo) => void | Promise<void>;
}

const normalizeOptions = (items: Array<Option | Record<string, unknown>>): Option[] =>
  items
    .map((item) => {
      if ("label" in item && "value" in item) {
        const casted = item as Option;
        return {
          label: String(casted.label),
          value: String(casted.value),
        };
      }

      const record = item as Record<string, unknown>;
      const label = record.label ?? record.name ?? record.display_name;
      const value = record.value ?? record.id ?? record.cat_id;

      if (!label || !value) {
        return null;
      }

      return { label: String(label), value: String(value) };
    })
    .filter((item): item is Option => Boolean(item));

export function CreateProductCategoryDialog({
  trigger,
  companies,
  defaultCompanyId,
  defaultLineId,
  environment = "prod",
  onCreated,
}: CreateProductCategoryDialogProps) {
  const { user } = useContext(AuthContext);
  const hasDebugPermission = Boolean(user?.is_admin || user?.permissions?.includes("admin:debug"));

  const [isOpen, setIsOpen] = useState(false);
  const [activeTab, setActiveTab] = useState<"line" | "subline">(defaultLineId ? "subline" : "line");
  const [companyId, setCompanyId] = useState<string>(defaultCompanyId ?? "");
  const [lineId, setLineId] = useState<string>(defaultLineId ?? "");
  const [categoryName, setCategoryName] = useState("");
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [isLoadingLines, setIsLoadingLines] = useState(false);
  const [lines, setLines] = useState<Option[]>([]);
  const [linesCache, setLinesCache] = useState<Record<string, Option[]>>({});
  const [targetEnvironment, setTargetEnvironment] = useState<"dev" | "prod">(environment);

  // Popover open states
  const [companyOpen, setCompanyOpen] = useState(false);
  const [lineOpen, setLineOpen] = useState(false);

  const companyOptions = useMemo(() => normalizeOptions(companies), [companies]);
  
  // Get display label for selected company
  const selectedCompanyLabel = useMemo(() => {
    const company = companyOptions.find((c) => c.value === companyId);
    return company?.label || "";
  }, [companyOptions, companyId]);
  
  // Get display label for selected line
  const selectedLineLabel = useMemo(() => {
    const line = lines.find((l) => l.value === lineId);
    return line?.label || "";
  }, [lines, lineId]);

  useEffect(() => {
    if (!isOpen) {
      setCompanyId(defaultCompanyId ?? "");
      setLineId(defaultLineId ?? "");
      setCategoryName("");
      setActiveTab(defaultLineId ? "subline" : "line");
    }
  }, [isOpen, defaultCompanyId, defaultLineId]);

  const fetchLines = useCallback(
    async (targetCompanyId: string) => {
      const cached = linesCache[targetCompanyId];
      if (cached) {
        setLines(cached);
        return cached;
      }

      setIsLoadingLines(true);

      try {
        const response = await apiFetch(`${config.apiUrl}/import/product-lines/${targetCompanyId}`);
        if (!response.ok) {
          throw new Error("Failed to load product lines");
        }

        const payload = await response.json();
        const normalized = normalizeOptions(Array.isArray(payload) ? payload : []);
        setLinesCache((prev) => ({ ...prev, [targetCompanyId]: normalized }));
        setLines(normalized);
        return normalized;
      } catch (error) {
        console.error("Failed to fetch product lines:", error);
        toast.error("Could not load product lines");
        setLines([]);
        return [];
      } finally {
        setIsLoadingLines(false);
      }
    },
    [linesCache],
  );

  useEffect(() => {
    if (!companyId) {
      setLines([]);
      setLineId("");
      return;
    }

    fetchLines(companyId).catch(() => {
      /* errors surfaced via toast */
    });
  }, [companyId, fetchLines]);

  const handleSubmit = useCallback(
    async (event?: React.FormEvent<HTMLFormElement>) => {
      event?.preventDefault();

      if (!companyId) {
        toast.error("Select a company before creating a category");
        return;
      }

      const trimmedName = categoryName.trim();

      if (!trimmedName) {
        toast.error("Enter a name for the new category");
        return;
      }

      if (activeTab === "subline" && !lineId) {
        toast.error("Select a parent line to create a subline");
        return;
      }

      const parentId = activeTab === "subline" ? lineId : companyId;
      const creationType = activeTab;

      setIsSubmitting(true);

      try {
        const result = await createProductCategory({
          masterCatId: parentId,
          name: trimmedName,
          environment: targetEnvironment,
        });

        if (!result.success) {
          const message =
            result.message ||
            (typeof result.error === "string" ? result.error : null) ||
            `Failed to create ${creationType === "line" ? "product line" : "subline"}.`;
          throw new Error(message ?? "Request failed");
        }

        const potentialData = result.category ?? result.data;
        let newId: string | undefined;

        if (potentialData && typeof potentialData === "object") {
          const record = potentialData as Record<string, unknown>;
          const candidateId = record.cat_id ?? record.id ?? record.value;
          if (candidateId !== undefined && candidateId !== null) {
            newId = String(candidateId);
          }
        }

        if (activeTab === "line") {
          const nextOption: Option = { label: trimmedName, value: newId ?? trimmedName };
          setLinesCache((prev) => {
            const existing = prev[companyId] ?? [];
            return {
              ...prev,
              [companyId]: [...existing, nextOption],
            };
          });
          setLines((prev) => [...prev, nextOption]);
        }

        toast.success(
          creationType === "line"
            ? "Product line created successfully."
            : "Subline created successfully.",
        );

        await onCreated?.({
          id: newId,
          name: trimmedName,
          parentId,
          type: creationType,
          response: result,
        });

        setIsOpen(false);
      } catch (error) {
        console.error("Failed to create product category:", error);
        const message =
          error instanceof Error
            ? error.message
            : `Failed to create ${activeTab === "line" ? "product line" : "subline"}.`;
        toast.error(message);
      } finally {
        setIsSubmitting(false);
      }
    },
    [activeTab, categoryName, companyId, targetEnvironment, lineId, onCreated],
  );

  return (
    <Dialog open={isOpen} onOpenChange={setIsOpen}>
      <DialogTrigger asChild>{trigger}</DialogTrigger>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Create New Line or Subline</DialogTitle>
        </DialogHeader>

        <Tabs value={activeTab} onValueChange={(value) => setActiveTab(value as "line" | "subline")}>
          <TabsList className="grid w-full grid-cols-2">
            <TabsTrigger value="line">Create Line</TabsTrigger>
            <TabsTrigger value="subline">Create Subline</TabsTrigger>
          </TabsList>

          <form onSubmit={handleSubmit} className="space-y-4 pt-4">
            {/* Company Select - shown in both tabs */}
            <div className="space-y-2">
              <Label>Company</Label>
              <Popover open={companyOpen} onOpenChange={setCompanyOpen}>
                <PopoverTrigger asChild>
                  <Button
                    variant="outline"
                    role="combobox"
                    aria-expanded={companyOpen}
                    className="w-full justify-between font-normal"
                  >
                    {selectedCompanyLabel || "Select a company"}
                    <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
                  </Button>
                </PopoverTrigger>
                <PopoverContent className="w-[--radix-popover-trigger-width] p-0" align="start">
                  <Command>
                    <CommandInput placeholder="Search companies..." />
                    <CommandList>
                      <CommandEmpty>No company found.</CommandEmpty>
                      <CommandGroup>
                        {companyOptions.map((company) => (
                          <CommandItem
                            key={company.value}
                            value={company.label}
                            onSelect={() => {
                              setCompanyId(company.value);
                              setLineId("");
                              setCompanyOpen(false);
                            }}
                          >
                            {company.label}
                            {company.value === companyId && (
                              <Check className="ml-auto h-4 w-4" />
                            )}
                          </CommandItem>
                        ))}
                      </CommandGroup>
                    </CommandList>
                  </Command>
                </PopoverContent>
              </Popover>
            </div>

            <TabsContent value="line" className="space-y-4 m-0">
              <div className="space-y-2">
                <Label htmlFor="create-line-name">Line Name</Label>
                <Input
                  id="create-line-name"
                  value={categoryName}
                  onChange={(event) => setCategoryName(event.target.value)}
                  placeholder="Enter the new line name"
                />
              </div>
            </TabsContent>

            <TabsContent value="subline" className="space-y-4 m-0">
              {/* Parent Line Select - only shown in subline tab */}
              <div className="space-y-2">
                <Label>Parent Line</Label>
                <Popover open={lineOpen} onOpenChange={setLineOpen}>
                  <PopoverTrigger asChild>
                    <Button
                      variant="outline"
                      role="combobox"
                      aria-expanded={lineOpen}
                      className="w-full justify-between font-normal"
                      disabled={!companyId || isLoadingLines}
                    >
                      {!companyId
                        ? "Select a company first"
                        : isLoadingLines
                          ? "Loading product lines..."
                          : selectedLineLabel || "Select a parent line"}
                      <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
                    </Button>
                  </PopoverTrigger>
                  <PopoverContent className="w-[--radix-popover-trigger-width] p-0" align="start">
                    <Command>
                      <CommandInput placeholder="Search lines..." />
                      <CommandList>
                        <CommandEmpty>No line found.</CommandEmpty>
                        <CommandGroup>
                          {lines.map((line) => (
                            <CommandItem
                              key={line.value}
                              value={line.label}
                              onSelect={() => {
                                setLineId(line.value);
                                setLineOpen(false);
                              }}
                            >
                              {line.label}
                              {line.value === lineId && (
                                <Check className="ml-auto h-4 w-4" />
                              )}
                            </CommandItem>
                          ))}
                        </CommandGroup>
                      </CommandList>
                    </Command>
                  </PopoverContent>
                </Popover>
                {companyId && !isLoadingLines && !lines.length && (
                  <p className="text-xs text-muted-foreground">
                    No existing lines found for this company. Create a line first.
                  </p>
                )}
              </div>

              <div className="space-y-2">
                <Label htmlFor="create-subline-name">Subline Name</Label>
                <Input
                  id="create-subline-name"
                  value={categoryName}
                  onChange={(event) => setCategoryName(event.target.value)}
                  placeholder="Enter the new subline name"
                />
              </div>
            </TabsContent>

            {hasDebugPermission && (
              <div className="pt-2 pb-2 border-t">
                <div className="flex items-center gap-2">
                  <Switch
                    id="category-api-environment"
                    checked={targetEnvironment === "dev"}
                    onCheckedChange={(checked) => setTargetEnvironment(checked ? "dev" : "prod")}
                  />
                  <Label htmlFor="category-api-environment" className="text-sm font-medium cursor-pointer">
                    Use test API
                  </Label>
                </div>
              </div>
            )}

            <DialogFooter className="gap-2">
              <Button type="button" variant="outline" onClick={() => setIsOpen(false)}>
                Cancel
              </Button>
              <Button
                type="submit"
                disabled={isSubmitting || !companyId || (activeTab === "subline" && !lineId)}
              >
                {isSubmitting ? (
                  <>
                    <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                    Creating...
                  </>
                ) : (
                  `Create ${activeTab === "line" ? "Line" : "Subline"}`
                )}
              </Button>
            </DialogFooter>
          </form>
        </Tabs>
      </DialogContent>
    </Dialog>
  );
}

export default CreateProductCategoryDialog;
