import ReactTable from "@/components/ReactTable/ReactTable";
import { Button } from "@/components/ui/button";
import { AnimatePresence, LayoutGroup, motion } from "framer-motion";
import React, { useEffect, useMemo, useState } from "react";
type Column<T> = {
  header: string;
  widthClass?: string;
  render: (item: T) => React.ReactNode;
};
type MetricCardProps<T> = {
  title: string;
  layoutId: string;
  fetchData: () => Promise<T[]>;
  deps?: any[];
  enabled?: boolean;
  columns?: Column<T>[];
  getRowId?: (item: T, index: number) => React.Key;
  getTotalValue?: (items: T[]) => number;
  showValueOnCard?: boolean;
  formatValue?: (n: number) => string;
  footer?: (ctx: {
    items: T[];
    totalCount: number;
    totalValue?: number;
  }) => React.ReactNode;
  className?: string;
};

function defaultCurrencyBR(n: number) {
  return Number(n || 0).toLocaleString("pt-BR", {
    style: "currency",
    currency: "BRL",
  });
}
// Texto puro de um ReactNode: usado como valor da coluna no ReactTable para
// que pesquisa, ordenação e exportação funcionem mesmo quando a célula é JSX.
function textoDoNode(node: React.ReactNode): string {
  if (node === null || node === undefined || typeof node === "boolean")
    return "";
  if (typeof node === "string" || typeof node === "number") return String(node);
  if (Array.isArray(node)) return node.map(textoDoNode).join(" ");
  if (React.isValidElement(node))
    return textoDoNode((node.props as any)?.children);
  return "";
}
export function MetricCard<T>({
  title,
  layoutId,
  fetchData,
  deps = [],
  enabled = true,
  columns = [],
  getRowId = (_item, i) => i,
  getTotalValue,
  showValueOnCard = false,
  formatValue = defaultCurrencyBR,
  footer,
  className = "",
}: MetricCardProps<T>) {
  const [items, setItems] = useState<T[]>([]);
  const [open, setOpen] = useState(false);
  const [loading, setLoading] = useState(false);
  const [errorMsg, setErrorMsg] = useState<string | null>(null);

  const totalCount = items.length;
  const totalValue = useMemo(
    () => (getTotalValue ? getTotalValue(items) : undefined),
    [items, getTotalValue],
  );

  // Detalhe do quadro em ReactTable (pesquisa, ordenação, paginação e export)
  const colunasTabela = useMemo(
    () =>
      columns.map((col, i) => ({
        header: col.header,
        accessorKey: `coluna_${i}`,
        cell: (info: any) => col.render(info.row.original.__item),
      })),
    [columns],
  );

  const dadosTabela = useMemo(
    () =>
      items.map((item, index) => {
        const linha: any = { __item: item, __id: getRowId(item, index) };
        columns.forEach((col, i) => {
          linha[`coluna_${i}`] = textoDoNode(col.render(item));
        });
        return linha;
      }),
    [items, columns, getRowId],
  );

  const handleOpen = () => setOpen(true);
  const handleClose = () => setOpen(false);

  useEffect(() => {
    let active = true;
    const run = async () => {
      if (!enabled) return;
      setLoading(true);
      setErrorMsg(null);
      try {
        const data = await fetchData();
        if (!active) return;
        setItems(Array.isArray(data) ? data : []);
      } catch (e: any) {
        if (!active) return;
        setErrorMsg("Erro ao carregar os dados.");
        console.error(e);
      } finally {
        if (active) setLoading(false);
      }
    };
    run();
    return () => {
      active = false;
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [enabled, ...deps]);

  useEffect(() => {
    if (!open) return;
    const prevOverflow = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    const onKeyDown = (e: KeyboardEvent) => {
      if (e.key === "Escape") handleClose();
    };
    window.addEventListener("keydown", onKeyDown);
    return () => {
      document.body.style.overflow = prevOverflow;
      window.removeEventListener("keydown", onKeyDown);
    };
  }, [open]);

  return (
    <LayoutGroup id={`${layoutId}-group`}>
      <div className={`relative ml-3 w-full ${className}`}>
        <motion.div
          layoutId={layoutId}
          className="pointer-events-none absolute inset-0 rounded-2xl dark:bg-boxdark"
          style={{ borderRadius: 16 }}
        />
        <div
          onClick={handleOpen}
          className="relative z-[1] cursor-pointer rounded px-3 py-5 w-full dark:text-white"
        >
          <div className="flex flex-col items-center justify-center">
            <div className="flex items-center justify-between w-full">
              <div className="flex items-center">
                <p className="font-medium mr-5 text-black text-sm">{title}</p>
              </div>
            </div>

            {loading ? (
              <div className="loader mt-3">
                <p className="font-semibold">Aguarde...</p>
              </div>
            ) : errorMsg ? (
              <p className="mt-2 text-sm text-red-500">{errorMsg}</p>
            ) : (
              <div className="flex items-center gap-2">
                <p className="mt-2 text-3xl font-bold">{totalCount}</p>
                {showValueOnCard && typeof totalValue === "number" ? (
                  <p className="mt-2 px-3 py-1 text-[#4ba083] rounded-md text-sm font-bold">
                    {formatValue(totalValue)}
                  </p>
                ) : null}
              </div>
            )}
          </div>
        </div>
      </div>

      <AnimatePresence>
        {open && (
          <motion.div
            className="fixed inset-0  bg-black/40 backdrop-blur-[1px] flex items-center justify-center z-50"
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            onClick={handleClose}
          >
            <motion.div
              layoutId={layoutId}
              className="bg-white dark:bg-boxdark dark:text-white rounded-2xl shadow-xl w-[80%] max-sm:w-[95%] max-h-[80vh] overflow-hidden flex flex-col"
              style={{ borderRadius: 16 }}
              onClick={(e) => e.stopPropagation()}
              transition={{
                layout: { type: "spring", stiffness: 300, damping: 30 },
              }}
            >
              {/* Header */}
              <div className="p-8 pb-4 max-sm:p-4 max-sm:pb-2 shrink-0 flex items-start justify-between gap-2">
                <h2 className="text-2xl md:text-3xl max-sm:text-lg font-semibold tracking-tight">
                  {title}
                </h2>
                <Button variant="outline" onClick={handleClose}>
                  Fechar
                </Button>
              </div>

              {/* KPIs */}
              <div className="px-8 pb-4 max-sm:px-4 max-sm:pb-2 shrink-0">
                <p className="text-5xl md:text-6xl max-sm:text-3xl font-semibold leading-none">
                  {totalCount}
                </p>
                {showValueOnCard && typeof totalValue === "number" && (
                  <p className="text-[#4ba083] text-2xl md:text-3xl max-sm:text-lg font-semibold">
                    {formatValue(totalValue)}
                  </p>
                )}
              </div>

              {/* Tabela do detalhe (ReactTable) */}
              {!!columns.length && (
                <div className="px-8 flex-1 min-h-0 overflow-auto">
                  <ReactTable
                    pageName={title}
                    columns={colunasTabela}
                    data={dadosTabela}
                    listFunction={async () => dadosTabela}
                  />
                </div>
              )}

              {/* Footer opcional */}
              {footer && (
                <div className="px-8 pt-6 pb-8 max-sm:px-4 max-sm:pt-4 max-sm:pb-4 shrink-0 border-t border-slate-200 dark:border-slate-700">
                  {footer({ items, totalCount, totalValue })}
                </div>
              )}
            </motion.div>
            {/* <motion.div
              layoutId={layoutId}
              className="bg-white dark:bg-boxdark h-max  dark:text-white rounded-2xl shadow-xl w-[90%] max-w-4xl"
              style={{ borderRadius: 16 }}
              onClick={(e) => e.stopPropagation()}
              transition={{
                layout: { type: "spring", stiffness: 300, damping: 30 },
              }}
            >
              <div className="p-8">
                <div className="flex items-start justify-between mb-6">
                  <h2 className="text-2xl md:text-3xl font-semibold tracking-tight">
                    {title}
                  </h2>
                  <Button variant="outline" onClick={handleClose}>
                    Fechar
                  </Button>
                </div>

                <div className="grid grid-cols-1 gap-8">
                  <div>
                    <div className="space-y-2">
                      <p className="text-5xl md:text-6xl font-semibold leading-none">
                        {totalCount}
                      </p>
                      {showValueOnCard && typeof totalValue === "number" && (
                        <p className="text-[#4ba083] text-2xl md:text-3xl font-semibold">
                          {formatValue(totalValue)}
                        </p>
                      )}
                    </div>

                    {!!columns.length && (
                      <div className="mt-6">
                        <div className="flex items-center text-sm text-slate-500 font-medium">
                          {(columns ?? []).map((col, i) => (
                            <div key={i} className={col.widthClass ?? "flex-1"}>
                              {col.header}
                            </div>
                          ))}
                        </div>
                        <div className="h-px bg-slate-200 dark:bg-slate-700 my-3" />

                        {items.length === 0 ? (
                          <div className="text-sm text-slate-500">
                            Nenhum registro.
                          </div>
                        ) : (
                          <AutoSizer>
                            {({ height, width }) => (
                              <List
                                height={height}
                                width={width}
                                itemCount={items.length}
                                itemSize={50}
                                itemData={{ items, columns, getRowId }}
                                itemKey={(index) =>
                                  String(getRowId(items[index], index))
                                }
                              >
                                {({ index, style, data }) => (
                                  <Row
                                    index={index}
                                    style={style}
                                    items={data.items}
                                    columns={data.columns}
                                    getRowId={data.getRowId}
                                  />
                                )}
                              </List>
                            )}
                          </AutoSizer>

                          // <AutoSizer>
                          //   {({ height, width }) => (
                          //     <List
                          //       height={height}
                          //       width={width}
                          //       itemCount={items.length}
                          //       itemSize={50}
                          //       itemData={{ items, columns, getRowId }}
                          //     >
                          //       {({ index, style, data }) => {

                          //         return (
                          //           <Row
                          //             index={index}
                          //             style={style}
                          //             items={data.items}
                          //             columns={data.columns}
                          //             getRowId={data.getRowId}
                          //           />
                          //         );
                          //       }}
                          //     </List>
                          //   )}
                          // </AutoSizer>
                        )}
                      </div>
                    )}
                  </div>
                </div>

                {footer && (
                  <div className="mt-8 pt-6 border-t border-slate-200 dark:border-slate-700">
                    {footer({ items, totalCount, totalValue })}
                  </div>
                )}
              </div>
            </motion.div> */}
          </motion.div>
        )}
      </AnimatePresence>
    </LayoutGroup>
  );
}
