import React, { useState, useEffect } from "react";
import { motion, AnimatePresence } from "framer-motion";
import {
  XMarkIcon,
  MagnifyingGlassIcon,
  Squares2X2Icon,
  TableCellsIcon,
  EyeIcon,
  ListBulletIcon,
} from "@heroicons/react/24/outline";
import { createPortal } from "react-dom";
import Typography from "../Typography/Typography";
import { getNestedValue } from "../../utils/getNestedValue";
import { useDarkMode } from "../../hooks/useDarkMode";

type ConditionProps = {
  for: number;
  condition: string;
  apply: string;
  otherwise: string;
};
type CustomFunctionProps = {
  for: number;
  apply: (value: any, item: any) => any;
};
interface ShowMoreInfoProps {
  title: string;
  disabled?: boolean;
  children?: React.ReactNode;
  className?: string;
  data?: any;
  accessKeys?: string[][];
  columns?: string[];
  counter?: string[];
  conditions?: ConditionProps[];
  customFunction?: CustomFunctionProps[];
  groupBy?: string[];
  hideCounter?: boolean;
}

const ShowMoreInfo: React.FC<ShowMoreInfoProps> = ({
  title,
  children,
  className = "",
  data,
  accessKeys,
  columns,
  conditions,
  customFunction,
  counter,
  disabled = false,
  groupBy,
  hideCounter = false,
}) => {
  const [isOpen, setIsOpen] = useState(false);
  const [isMobile, setIsMobile] = useState(false);
  const [processedItems, setProcessedItems] = useState<any[]>([]);
  const [groupedItems, setGroupedItems] = useState<any[]>([]);
  const [searchTerm, setSearchTerm] = useState("");
  const [isDark] = useDarkMode();
  const [viewMode, setViewMode] = useState<"grid" | "table">(
    data?.length === 1 ? "table" : "grid"
  );

  useEffect(() => {
    if (data && accessKeys && columns) {
      const mapped = data.map((item: any, i: number) => {
        const nestedValues: any[] = [];
        for (let index = 0; index < columns.length; index++) {
          const customFn = customFunction?.find(
            (opt: CustomFunctionProps) => opt.for === index
          );
          let renderedField = getNestedValue(item, accessKeys[index], {
            disableLocaleString: !!customFn,
          });
          const foundedCondition = conditions?.find(
            (opt: ConditionProps) => opt.for === index
          );
          if (foundedCondition) {
            if (renderedField === foundedCondition?.condition) {
              renderedField = foundedCondition?.apply;
            } else {
              renderedField = foundedCondition?.otherwise;
            }
          }
          if (customFn) {
            renderedField = customFn.apply(renderedField, item);
          }
          nestedValues.push(renderedField);
        }
        return {
          row: hideCounter ? nestedValues : [i + 1, ...nestedValues],
          raw: item,
          index: i,
        };
      });
      setProcessedItems(mapped);
    } else {
      setProcessedItems([]);
    }
  }, [data, accessKeys, columns, conditions, customFunction]);

  useEffect(() => {
    if (!groupBy || !groupBy.length) {
      const groups = [
        {
          key: "__all",
          label: "",
          items: processedItems,
        },
      ];
      setGroupedItems(groups);
      return;
    }
    const map = new Map<string, { label: string; items: any[] }>();
    processedItems.forEach((p) => {
      const values = groupBy.map((g) => {
        const path = typeof g === "string" ? g.split(".") : g;
        const val = getNestedValue(p.raw, path);
        return val ?? "";
      });
      const key = values.join("|||");
      const label = values.join(" / ");
      if (!map.has(key)) {
        map.set(key, { label, items: [p] });
      } else {
        map.get(key)!.items.push(p);
      }
    });
    const result = Array.from(map.entries()).map(([k, v]) => ({
      key: k,
      label: v.label,
      items: v.items,
    }));
    setGroupedItems(result);
  }, [processedItems, groupBy]);

  useEffect(() => {
    if (searchTerm.trim() === "") {
      setGroupedItems((prevGroups) =>
        prevGroups.map((g) => ({ ...g, items: g.items }))
      );
      return;
    }
    const term = searchTerm.toLowerCase();
    const filteredGroups = groupedItems.map((g) => {
      const items = g.items.filter((p: any) =>
        p.row.some(
          (v: any) =>
            v !== null &&
            v !== undefined &&
            v.toString().toLowerCase().includes(term)
        )
      );
      return { ...g, items };
    });
    setGroupedItems(filteredGroups);
  }, [searchTerm]);

  useEffect(() => {
    const handleResize = () => {
      setIsMobile(window.innerWidth < 768);
      if (window.innerWidth < 768) {
        setViewMode("table");
      }
    };
    handleResize();
    window.addEventListener("resize", handleResize);
    return () => window.removeEventListener("resize", handleResize);
  }, []);

  const toggleModal = () => setIsOpen(!isOpen);
  const toggleViewMode = () =>
    setViewMode(viewMode === "grid" ? "table" : "grid");

  const desktopVariants = {
    hidden: {
      opacity: 0,
      scale: 0.95,
      y: 20,
    },
    visible: {
      opacity: 1,
      scale: 1,
      y: 0,
      transition: {
        duration: 0.2,
        ease: "easeOut",
      },
    },
    exit: {
      opacity: 0,
      scale: 0.95,
      y: 20,
      transition: {
        duration: 0.15,
        ease: "easeIn",
      },
    },
  };

  const mobileVariants = {
    hidden: {
      opacity: 0,
      y: "100%",
    },
    visible: {
      opacity: 1,
      y: 0,
      transition: {
        duration: 0.3,
        ease: "easeOut",
      },
    },
    exit: {
      opacity: 0,
      y: "100%",
      transition: {
        duration: 0.25,
        ease: "easeIn",
      },
    },
  };

  const overlayVariants = {
    hidden: { opacity: 0 },
    visible: { opacity: 1 },
  };

  const totalCount = groupedItems.reduce(
    (acc, g) => acc + (g.items?.length || 0),
    0
  );

  return (
    <>
      <button
        disabled={disabled}
        onClick={() => {
          if (children || totalCount) {
            toggleModal();
          }
        }}
        className={`relative overflow-hidden group ${className} ${
          children || totalCount
            ? "cursor-pointer"
            : "cursor-not-allowed opacity-50"
        }`}
      >
        <motion.span
          className={`flex items-center justify-center gap-1 px-3 py-1.5 text-sm rounded-lg text-nowrap ${
            columns
              ? `${
                  disabled
                    ? "bg-primary-500/40 opacity-40 cursor-not-allowed"
                    : "bg-primary-500/40"
                }  text-primary-700 dark:text-primary-400 dark:bg-primary-500/20`
              : `${
                  disabled
                    ? "bg-primary-500/30 opacity-40 cursor-not-allowed"
                    : "bg-primary-500/30"
                } text-primary-700 dark:text-primary-400 dark:bg-primary-100/20`
          }`}
          initial={false}
          whileTap={{ scale: 0.95 }}
        >
          <motion.span
            className="flex items-center text-nowrap"
            initial={false}
            animate={{
              opacity: [1, 0.7, 1],
            }}
            transition={{
              repeat: Infinity,
              duration: 3,
              ease: "easeInOut",
            }}
          >
            {accessKeys ? (
              <EyeIcon className="w-4 h-4 ml-1" />
            ) : (
              <ListBulletIcon className="w-4 h-4 ml-1" />
            )}
            نمایش {!!counter && `(${counter})`}
          </motion.span>
          {!!totalCount && (
            <span className="inline-flex items-center justify-center px-2 py-0.5 text-xs font-medium rounded-full bg-primary-500/20 text-primary-700 dark:text-primary-300">
              {totalCount}
            </span>
          )}

          <motion.span
            className="absolute inset-0 bg-primary-500/10 opacity-0 group-hover:opacity-100"
            initial={false}
            transition={{ duration: 0.3 }}
            style={{
              borderRadius: "50%",
              scale: 0,
            }}
            whileHover={{
              scale: 2,
              opacity: 0,
              transition: { duration: 0.6 },
            }}
          />
        </motion.span>
      </button>

      {createPortal(
        <AnimatePresence>
          {isOpen && (
            <div className="fixed inset-0 z-[9999] flex items-end md:items-center justify-center p-0 md:p-4">
              <motion.div
                variants={overlayVariants}
                initial="hidden"
                animate="visible"
                exit="hidden"
                className="absolute inset-0 bg-black/50 dark:bg-black/70"
                onClick={toggleModal}
              />

              <motion.div
                variants={isMobile ? mobileVariants : desktopVariants}
                initial="hidden"
                animate="visible"
                exit="exit"
                className={`relative w-full ${
                  isMobile
                    ? "max-h-[90vh] rounded-t-2xl"
                    : "max-w-2xl max-h-[90vh] rounded-lg"
                } bg-white dark:bg-gray-800 shadow-xl overflow-hidden`}
              >
                <div className="flex justify-between items-center p-2">
                  <div className="w-8"></div>

                  <Typography
                    variant="body1"
                    className="absolute left-1/2 transform -translate-x-1/2"
                  >
                    {title}
                  </Typography>
                  <button
                    className="p-1 text-gray-500 dark:text-gray-200 hover:text-gray-700 dark:hover:text-gray-300 z-10 cursor-pointer"
                    onClick={toggleModal}
                  >
                    <XMarkIcon className="h-6 w-6" />
                  </button>
                </div>

                <section
                  className={`flex w-full justify-start overflow-y-auto ${
                    isDark && "dark-scrollbar"
                  }`}
                >
                  {data && columns && (
                    <div className="w-full max-w-7xl">
                      {totalCount > 0 && (
                        <div className="p-2">
                          <div className="flex items-center gap-2">
                            <div className="relative flex-1">
                              <div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
                                {searchTerm ? (
                                  <button
                                    className="absolute inset-y-0 left-0 pl-3 flex items-center"
                                    onClick={() => setSearchTerm("")}
                                  >
                                    <XMarkIcon className="h-5 w-5 text-gray-400 hover:text-gray-600" />
                                  </button>
                                ) : (
                                  <MagnifyingGlassIcon className="h-5 w-5 text-gray-400" />
                                )}
                              </div>
                              <input
                                type="text"
                                placeholder="جستجو..."
                                className="block w-full pl-10 pr-3 py-1 border border-gray-300 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent"
                                value={searchTerm}
                                onChange={(e) => setSearchTerm(e.target.value)}
                              />
                            </div>
                            <button
                              onClick={toggleViewMode}
                              className="p-2 rounded-lg bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors"
                              title={
                                viewMode === "grid"
                                  ? "نمایش جدولی"
                                  : "نمایش کارتی"
                              }
                            >
                              {viewMode === "grid" ? (
                                <TableCellsIcon className="h-5 w-5" />
                              ) : (
                                <Squares2X2Icon className="h-5 w-5" />
                              )}
                            </button>
                          </div>
                        </div>
                      )}

                      {viewMode === "grid" ? (
                        <div className="space-y-3 max-h-[500px] overflow-y-auto p-2">
                          {groupedItems.map((group, gIdx) =>
                            !group.items || group.items.length === 0 ? null : (
                              <div key={`group-${gIdx}`}>
                                {group.label !== "" && (
                                  <div className="px-2 py-1">
                                    <p className="text-sm font-bold text-blue-900/50 dark:text-white">
                                      {group.label}
                                    </p>
                                  </div>
                                )}
                                <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-4 gap-2 rounded-xl p-2">
                                  {group.items.map(
                                    (item: any, index: number) => (
                                      <div
                                        key={`item-${group.key}-${index}`}
                                        className={`${
                                          index % 2 === 0
                                            ? "bg-primary-50/50 dark:bg-dark-900"
                                            : "bg-primary-50 dark:bg-dark-700"
                                        }  rounded-2xl shadow-md border border-gray-200 gap-2 p-2 transition-transform hover:scale-[1.02]`}
                                      >
                                        <div className="space-y-1 divide-y-2 divide-gray-200 dark:divide-gray-300">
                                          {item?.row?.map(
                                            (
                                              opt: string,
                                              innerIndex: number
                                            ) => (
                                              <div
                                                key={innerIndex}
                                                className="space-y-1 flex justify-between items-center"
                                              >
                                                <p className="text-xs font-medium text-gray-500 dark:text-gray-200">
                                                  {[
                                                    ...(hideCounter
                                                      ? columns
                                                      : ["ردیف", ...columns])[
                                                      innerIndex
                                                    ],
                                                  ]}
                                                </p>
                                                <p className="text-sm font-semibold text-gray-800 dark:text-white break-words">
                                                  {opt}
                                                </p>
                                              </div>
                                            )
                                          )}
                                        </div>
                                      </div>
                                    )
                                  )}
                                </div>
                              </div>
                            )
                          )}
                        </div>
                      ) : (
                        <div className="max-h-[500px] overflow-y-auto p-2">
                          <div className="overflow-x-auto rounded-lg">
                            <table className="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
                              <thead className="bg-primary-50 dark:bg-dark-900">
                                <tr>
                                  {(hideCounter
                                    ? columns
                                    : ["ردیف", ...columns]
                                  ).map((column, index) => (
                                    <th
                                      key={index}
                                      scope="col"
                                      className="px-3 py-2 text-right text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider"
                                    >
                                      {column}
                                    </th>
                                  ))}
                                </tr>
                              </thead>
                              <tbody className="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
                                {groupedItems.map((group, gIdx) =>
                                  !group.items ||
                                  group.items.length === 0 ? null : (
                                    <React.Fragment key={`group-table-${gIdx}`}>
                                      {group.label !== "" && (
                                        <tr className="bg-primary-200/80 dark:bg-dark-900/30">
                                          <td
                                            colSpan={
                                              (hideCounter
                                                ? columns
                                                : ["ردیف", ...columns]
                                              ).length
                                            }
                                            className="px-3 py-2 text-sm text-dark-600/80 text-center dark:text-gray-200 font-bold"
                                          >
                                            {group.label}
                                          </td>
                                        </tr>
                                      )}
                                      {group.items.map(
                                        (item: any, index: number) => (
                                          <tr
                                            key={`table-row-${group.key}-${index}`}
                                            className={`${
                                              index % 2 === 0
                                                ? "bg-white dark:bg-dark-800"
                                                : "bg-primary-50 dark:bg-dark-900"
                                            } hover:bg-primary-100 dark:hover:bg-dark-700 dark:hover:text-dark-100`}
                                          >
                                            {item?.row?.map(
                                              (
                                                opt: string,
                                                innerIndex: number
                                              ) => (
                                                <td
                                                  key={`table-cell-${group.key}-${index}-${innerIndex}`}
                                                  className="px-3 py-2 whitespace-nowrap text-sm text-gray-800 dark:text-gray-200"
                                                >
                                                  {opt}
                                                </td>
                                              )
                                            )}
                                          </tr>
                                        )
                                      )}
                                    </React.Fragment>
                                  )
                                )}
                              </tbody>
                            </table>
                          </div>
                        </div>
                      )}
                    </div>
                  )}
                </section>
                <section className="overflow-auto max-h-[500px] modern-scrollbar">
                  {children && (
                    <div className="mb-4 p-2 flex justify-center w-full items-center">
                      {children}
                    </div>
                  )}
                </section>
              </motion.div>
            </div>
          )}
        </AnimatePresence>,
        document.body
      )}
    </>
  );
};

export default ShowMoreInfo;
