import { useEffect, useMemo, useState } from "react";
import {
  Check,
  ExternalLink,
  ListChecks,
  Loader2,
  Pencil,
  Plus,
  RefreshCw,
  Search,
  Trash2,
  X,
} from "lucide-react";
import { toast } from "sonner";

import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { useAppLists } from "@/lib/appLists";
import {
  mutateManagedList,
  type ManagedListCategory,
} from "@/lib/listAdmin";
import { normalizeOptionKey } from "@/lib/optionUtils";
import { cn } from "@/lib/utils";

const SHEET_URL =
  "https://docs.google.com/spreadsheets/d/19oBoslErcTSk8ibA6Nr38lcOV8Q09JwGahS7JD1o4Ts/edit?gid=1709890592#gid=1709890592";

type Props = {
  open: boolean;
  onOpenChange: (open: boolean) => void;
};

type EditableRow = {
  value: string;
  manager?: string;
};

const CATEGORY_META: Record<
  ManagedListCategory,
  { label: string; singular: string; placeholder: string; description: string }
> = {
  client: {
    label: "Clientes",
    singular: "cliente",
    placeholder: "Ej: PepsiCo",
    description: "Opciones disponibles en el campo Cliente de los proyectos.",
  },
  brand: {
    label: "Marcas",
    singular: "marca",
    placeholder: "Ej: Nescafé",
    description: "Opciones disponibles en la selección de una o varias marcas.",
  },
  country: {
    label: "País / BU",
    singular: "País / BU",
    placeholder: "Ej: Guatemala",
    description: "Cada País / BU puede tener un Country Manager asociado.",
  },
  status: {
    label: "Estatus",
    singular: "estatus",
    placeholder: "Ej: Stand by",
    description: "Estatus disponibles para cerrar o clasificar proyectos.",
  },
};

function sortRows(rows: EditableRow[]) {
  return [...rows].sort((a, b) => a.value.localeCompare(b.value, "es", { sensitivity: "base" }));
}

const PAGE_SIZE = 25;

type PaginationItem = number | "ellipsis-start" | "ellipsis-end";

function buildPaginationItems(currentPage: number, totalPages: number): PaginationItem[] {
  if (totalPages <= 7) {
    return Array.from({ length: totalPages }, (_, index) => index + 1);
  }

  if (currentPage <= 4) {
    return [1, 2, 3, 4, 5, "ellipsis-end", totalPages];
  }

  if (currentPage >= totalPages - 3) {
    return [
      1,
      "ellipsis-start",
      totalPages - 4,
      totalPages - 3,
      totalPages - 2,
      totalPages - 1,
      totalPages,
    ];
  }

  return [
    1,
    "ellipsis-start",
    currentPage - 1,
    currentPage,
    currentPage + 1,
    "ellipsis-end",
    totalPages,
  ];
}

export function ListManagerDialog({ open, onOpenChange }: Props) {
  const [category, setCategory] = useState<ManagedListCategory>("client");
  const [query, setQuery] = useState("");
  const [page, setPage] = useState(1);
  const [value, setValue] = useState("");
  const [manager, setManager] = useState("");
  const [editingOriginal, setEditingOriginal] = useState<string | null>(null);
  const [saving, setSaving] = useState(false);
  const [deletingValue, setDeletingValue] = useState<string | null>(null);
  const [syncing, setSyncing] = useState(false);
  const { lists, loading, error, refresh } = useAppLists();

  const rows = useMemo<EditableRow[]>(() => {
    if (category === "client") return sortRows(lists.clientes.map((item) => ({ value: item })));
    if (category === "brand") return sortRows(lists.marcas.map((item) => ({ value: item })));
    if (category === "status") return sortRows(lists.status.map((item) => ({ value: item })));

    return sortRows(
      lists.bus.map((item) => ({
        value: item,
        manager:
          lists.buCm[item] ||
          Object.entries(lists.buCm).find(
            ([key]) => normalizeOptionKey(key) === normalizeOptionKey(item),
          )?.[1] ||
          "",
      })),
    );
  }, [category, lists]);

  const filteredRows = useMemo(() => {
    const cleanQuery = normalizeOptionKey(query);
    if (!cleanQuery) return rows;

    return rows.filter((row) =>
      normalizeOptionKey(`${row.value} ${row.manager || ""}`).includes(cleanQuery),
    );
  }, [query, rows]);

  const totalPages = Math.max(1, Math.ceil(filteredRows.length / PAGE_SIZE));
  const currentPage = Math.min(page, totalPages);
  const pageStart = (currentPage - 1) * PAGE_SIZE;
  const pageRows = filteredRows.slice(pageStart, pageStart + PAGE_SIZE);
  const paginationItems = buildPaginationItems(currentPage, totalPages);

  const resetDraft = () => {
    setValue("");
    setManager("");
    setEditingOriginal(null);
  };

  useEffect(() => {
    if (!open) return;
    void refresh();
  }, [open, refresh]);

  useEffect(() => {
    resetDraft();
    setQuery("");
    setPage(1);
  }, [category]);

  useEffect(() => {
    setPage(1);
  }, [query]);

  useEffect(() => {
    if (page > totalPages) setPage(totalPages);
  }, [page, totalPages]);

  const beginEdit = (row: EditableRow) => {
    setEditingOriginal(row.value);
    setValue(row.value);
    setManager(row.manager || "");
  };

  const save = async () => {
    const cleanValue = value.trim();
    const cleanManager = manager.trim();

    if (!cleanValue) {
      toast.error(`Escribe el ${CATEGORY_META[category].singular}.`);
      return;
    }

    setSaving(true);
    try {
      await mutateManagedList({
        action: editingOriginal ? "update" : "create",
        category,
        value: cleanValue,
        previousValue: editingOriginal || undefined,
        manager: category === "country" ? cleanManager : undefined,
      });
      await refresh();
      toast.success(editingOriginal ? "Lista actualizada." : "Opción agregada.", {
        description: "Google Sheet y Supabase quedaron sincronizados.",
      });
      resetDraft();
    } catch (saveError) {
      console.error("Error guardando lista:", saveError);
      toast.error("No se pudo guardar la lista.", {
        description:
          saveError instanceof Error ? saveError.message : "Revisa n8n e intenta nuevamente.",
      });
    } finally {
      setSaving(false);
    }
  };

  const remove = async (row: EditableRow) => {
    if (
      !window.confirm(
        `¿Eliminar "${row.value}" de ${CATEGORY_META[category].label}?\n\nEl cambio también se hará en el Google Sheet. Los proyectos históricos no se borrarán.`,
      )
    ) {
      return;
    }

    setDeletingValue(row.value);
    try {
      await mutateManagedList({
        action: "delete",
        category,
        value: row.value,
        previousValue: row.value,
      });
      await refresh();
      if (editingOriginal && normalizeOptionKey(editingOriginal) === normalizeOptionKey(row.value)) {
        resetDraft();
      }
      toast.success("Opción eliminada.", {
        description: "Google Sheet y Supabase quedaron sincronizados.",
      });
    } catch (deleteError) {
      console.error("Error eliminando lista:", deleteError);
      toast.error("No se pudo eliminar la opción.", {
        description:
          deleteError instanceof Error ? deleteError.message : "Revisa n8n e intenta nuevamente.",
      });
    } finally {
      setDeletingValue(null);
    }
  };

  const syncFromSheet = async () => {
    setSyncing(true);
    try {
      await mutateManagedList({ action: "refresh" });
      await refresh();
      toast.success("Listas actualizadas desde el Sheet.");
    } catch (syncError) {
      console.error("Error sincronizando listas:", syncError);
      toast.error("No se pudieron sincronizar las listas.", {
        description:
          syncError instanceof Error ? syncError.message : "Revisa n8n e intenta nuevamente.",
      });
    } finally {
      setSyncing(false);
    }
  };

  const meta = CATEGORY_META[category];

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="h-[88vh] max-h-[860px] w-[96vw] max-w-[1050px] overflow-hidden p-0">
        <div className="flex h-full min-h-0 flex-col">
          <div className="border-b border-border px-6 py-5 pr-14">
            <DialogHeader>
              <div className="flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between">
                <div>
                  <DialogTitle className="flex items-center gap-2 text-xl">
                    <ListChecks className="h-5 w-5 text-primary" />
                    Administración de listas
                  </DialogTitle>
                  <DialogDescription className="mt-1 max-w-2xl">
                    Los cambios que realices aquí se guardarán automáticamente en la hoja{` `}
                    <strong>Listas</strong> y se reflejarán de inmediato en las opciones disponibles
                    de la aplicación.
                  </DialogDescription>
                </div>
                <div className="flex flex-wrap gap-2">
                  <Button
                    type="button"
                    variant="outline"
                    size="sm"
                    className="gap-1.5"
                    onClick={() => window.open(SHEET_URL, "_blank", "noopener,noreferrer")}
                  >
                    <ExternalLink className="h-3.5 w-3.5" /> Abrir Sheet
                  </Button>
                  <Button
                    type="button"
                    variant="outline"
                    size="sm"
                    className="gap-1.5"
                    onClick={() => void syncFromSheet()}
                    disabled={syncing}
                  >
                    <RefreshCw className={cn("h-3.5 w-3.5", syncing && "animate-spin")} />
                    Sincronizar desde Sheet
                  </Button>
                </div>
              </div>
            </DialogHeader>
          </div>

          <div className="border-b border-border px-6 py-4">
            <Tabs value={category} onValueChange={(next) => setCategory(next as ManagedListCategory)}>
              <TabsList className="grid w-full grid-cols-2 sm:grid-cols-4">
                {(Object.keys(CATEGORY_META) as ManagedListCategory[]).map((key) => (
                  <TabsTrigger key={key} value={key}>
                    {CATEGORY_META[key].label}
                  </TabsTrigger>
                ))}
              </TabsList>
            </Tabs>
          </div>

          <div className="grid min-h-0 flex-1 grid-cols-1 lg:grid-cols-[360px_minmax(0,1fr)]">
            <section className="border-b border-border bg-muted/15 p-5 lg:border-b-0 lg:border-r">
              <div className="rounded-2xl border border-border bg-card p-4 shadow-sm">
                <div className="flex items-center justify-between gap-2">
                  <div>
                    <h3 className="text-sm font-semibold">
                      {editingOriginal ? `Editar ${meta.singular}` : `Agregar ${meta.singular}`}
                    </h3>
                    <p className="mt-1 text-xs text-muted-foreground">{meta.description}</p>
                  </div>
                  {editingOriginal && (
                    <Button type="button" variant="ghost" size="icon" onClick={resetDraft}>
                      <X className="h-4 w-4" />
                    </Button>
                  )}
                </div>

                <div className="mt-4 space-y-3">
                  <div className="space-y-1.5">
                    <Label>{meta.singular.charAt(0).toUpperCase() + meta.singular.slice(1)}</Label>
                    <Input
                      value={value}
                      onChange={(event) => setValue(event.target.value)}
                      placeholder={meta.placeholder}
                      disabled={saving}
                    />
                  </div>

                  {category === "country" && (
                    <div className="space-y-1.5">
                      <Label>Country Manager</Label>
                      <Input
                        value={manager}
                        onChange={(event) => setManager(event.target.value)}
                        placeholder="Ej: Poul"
                        disabled={saving}
                      />
                    </div>
                  )}

                  <Button
                    type="button"
                    className="w-full gap-1.5"
                    onClick={() => void save()}
                    disabled={saving || !value.trim()}
                  >
                    {saving ? (
                      <Loader2 className="h-4 w-4 animate-spin" />
                    ) : editingOriginal ? (
                      <Check className="h-4 w-4" />
                    ) : (
                      <Plus className="h-4 w-4" />
                    )}
                    {editingOriginal ? "Guardar cambios" : "Agregar"}
                  </Button>
                </div>
              </div>

            </section>

            <section className="flex min-h-0 flex-col p-5">
              <div className="relative mb-3">
                <Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
                <Input
                  value={query}
                  onChange={(event) => setQuery(event.target.value)}
                  placeholder={`Buscar en ${meta.label}…`}
                  className="pl-9"
                />
              </div>

              {error && (
                <div className="mb-3 rounded-xl border border-amber-200 bg-amber-50 px-3 py-2 text-xs text-amber-900">
                  No se pudieron cargar las listas desde Supabase: {error}
                </div>
              )}

              <div className="mb-2 flex items-center justify-between text-xs text-muted-foreground">
                <span>{filteredRows.length} opción(es)</span>
                {loading && <span>Cargando…</span>}
              </div>

              <div className="min-h-0 flex-1 overflow-y-auto rounded-2xl border border-border bg-card">
                {loading && rows.length === 0 ? (
                  <div className="flex h-40 items-center justify-center gap-2 text-sm text-muted-foreground">
                    <Loader2 className="h-4 w-4 animate-spin" /> Cargando listas…
                  </div>
                ) : filteredRows.length === 0 ? (
                  <div className="flex h-40 items-center justify-center text-sm text-muted-foreground">
                    No hay opciones que coincidan.
                  </div>
                ) : (
                  <div className="divide-y divide-border">
                    {pageRows.map((row) => (
                      <div
                        key={normalizeOptionKey(`${category}:${row.value}`)}
                        className="flex items-center justify-between gap-3 px-4 py-3"
                      >
                        <div className="min-w-0">
                          <p className="truncate text-sm font-medium">{row.value}</p>
                          {category === "country" && (
                            <p className="mt-0.5 truncate text-xs text-muted-foreground">
                              CM: {row.manager || "Sin asignar"}
                            </p>
                          )}
                        </div>
                        <div className="flex shrink-0 items-center gap-1">
                          <Button
                            type="button"
                            variant="ghost"
                            size="sm"
                            className="h-8 gap-1 px-2"
                            onClick={() => beginEdit(row)}
                            disabled={Boolean(deletingValue) || saving}
                          >
                            <Pencil className="h-3.5 w-3.5" /> Editar
                          </Button>
                          <Button
                            type="button"
                            variant="ghost"
                            size="sm"
                            className="h-8 gap-1 px-2 text-muted-foreground hover:text-destructive"
                            onClick={() => void remove(row)}
                            disabled={Boolean(deletingValue) || saving}
                          >
                            {deletingValue === row.value ? (
                              <Loader2 className="h-3.5 w-3.5 animate-spin" />
                            ) : (
                              <Trash2 className="h-3.5 w-3.5" />
                            )}
                            Eliminar
                          </Button>
                        </div>
                      </div>
                    ))}
                  </div>
                )}
              </div>

              {filteredRows.length > 0 && (
                <div className="mt-3 flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
                  <span className="text-xs text-muted-foreground">
                    Mostrando {pageStart + 1}–{Math.min(pageStart + PAGE_SIZE, filteredRows.length)} de{` `}
                    {filteredRows.length}
                  </span>
                  {totalPages > 1 && (
                    <div className="flex flex-wrap items-center gap-1">
                      <Button
                        type="button"
                        variant="outline"
                        size="sm"
                        className="h-8 px-2.5"
                        onClick={() => setPage((current) => Math.max(1, current - 1))}
                        disabled={currentPage === 1}
                      >
                        Anterior
                      </Button>
                      {paginationItems.map((item) =>
                        typeof item === "number" ? (
                          <Button
                            key={item}
                            type="button"
                            variant={item === currentPage ? "default" : "outline"}
                            size="sm"
                            className="h-8 min-w-8 px-2"
                            onClick={() => setPage(item)}
                            aria-current={item === currentPage ? "page" : undefined}
                          >
                            {item}
                          </Button>
                        ) : (
                          <span
                            key={item}
                            className="flex h-8 min-w-6 items-center justify-center text-xs text-muted-foreground"
                            aria-hidden="true"
                          >
                            …
                          </span>
                        ),
                      )}
                      <Button
                        type="button"
                        variant="outline"
                        size="sm"
                        className="h-8 px-2.5"
                        onClick={() => setPage((current) => Math.min(totalPages, current + 1))}
                        disabled={currentPage === totalPages}
                      >
                        Siguiente
                      </Button>
                    </div>
                  )}
                </div>
              )}
            </section>
          </div>
        </div>
      </DialogContent>
    </Dialog>
  );
}
