import React, { useEffect, useMemo, useState } from "react";
import {
  Button,
  Card,
  Checkbox,
  Input,
  Select,
  Tag,
  Tooltip,
} from "antd";
import { SearchOutlined, StarFilled, StarOutlined } from "@ant-design/icons";
import { Layers } from "lucide-react";
import { CategoryI, OperatorI } from "@/pages/OperatorMarket/operator.model";
import { updateOperatorByIdUsingPut } from "@/pages/OperatorMarket/operator.api";

type GroupedCategoryOption = {
  label: string;
  title: string;
  options: Array<Omit<CategoryI, "type">>;
};

interface OperatorListProps {
  operators: OperatorI[];
  favorites: Set<string>;
  toggleFavorite: (id: string) => void;
  toggleOperator: (operator: OperatorI) => void;
  selectedOperators: OperatorI[];
  onDragOperator: (
    e: React.DragEvent,
    item: OperatorI,
    source: "library"
  ) => void;
}

const handleStar = async (
  operator: OperatorI,
  toggleFavorite: (id: string) => void
) => {
  const data = {
    id: operator.id,
    isStar: !operator.isStar,
  };
  await updateOperatorByIdUsingPut(operator.id, data);
  toggleFavorite(operator.id);
};

const OperatorList: React.FC<OperatorListProps> = ({
  operators,
  favorites,
  toggleFavorite,
  toggleOperator,
  selectedOperators,
  onDragOperator,
}) => (
  <div className="grid grid-cols-1 gap-2">
    {operators.map((operator) => {
      const isSelected = selectedOperators.some((op) => op.id === operator.id);
      return (
        <Card
          size="small"
          key={operator.id}
          draggable
          hoverable
          onDragStart={(event) => onDragOperator(event, operator, "library")}
          onClick={() => toggleOperator(operator)}
        >
          <div className="flex items-center justify-between">
            <div className="flex flex-1 min-w-0 items-center gap-2">
              <Checkbox checked={isSelected} />
              <span className="flex-1 min-w-0 font-medium text-sm overflow-hidden text-ellipsis whitespace-nowrap">
                {operator.name}
              </span>
            </div>
            <span
              className="cursor-pointer"
              onClick={(event) => {
                event.stopPropagation();
                handleStar(operator, toggleFavorite);
              }}
            >
              {favorites.has(operator.id) ? (
                <StarFilled style={{ color: "#FFD700" }} />
              ) : (
                <StarOutlined />
              )}
            </span>
          </div>
        </Card>
      );
    })}
  </div>
);

interface OperatorLibraryProps {
  selectedOperators: OperatorI[];
  operatorList: OperatorI[];
  categoryOptions: CategoryI[];
  setSelectedOperators: (operators: OperatorI[]) => void;
  toggleOperator: (operator: OperatorI) => void;
  handleDragStart: (
    e: React.DragEvent,
    item: OperatorI,
    source: "library"
  ) => void;
}

const OperatorLibrary: React.FC<OperatorLibraryProps> = ({
  selectedOperators,
  operatorList,
  categoryOptions,
  setSelectedOperators,
  toggleOperator,
  handleDragStart,
}) => {
  const [searchTerm, setSearchTerm] = useState("");
  const [showFavorites, setShowFavorites] = useState(false);
  const [favorites, setFavorites] = useState<Set<string>>(new Set());
  const [selectedCategory, setSelectedCategory] = useState<string[]>([]);
  const [operatorListFiltered, setOperatorListFiltered] = useState<OperatorI[]>(
    []
  );

  useMemo(() => {
    const groups: Record<string, { type: string; operators: OperatorI[] }> = {};
    let operatorFilteredList: OperatorI[];

    categoryOptions.forEach((cat) => {
      groups[cat.id] = {
        type: cat.type,
        operators: operatorList.filter((op) => op.categories?.includes(cat.id)),
      };
    });

    if (selectedCategory.length) {
      const groupedFiltered: Record<string, OperatorI[]> = {};
      selectedCategory.forEach((cat: string) => {
        const parent = groups[cat]?.type;
        if (!parent) {
          return;
        }
        if (!groupedFiltered[parent]) {
          groupedFiltered[parent] = groups[cat].operators;
        } else {
          groupedFiltered[parent] = Array.from(
            new Map(
              [...groupedFiltered[parent], ...groups[cat].operators].map((item) => [
                item.id,
                item,
              ])
            ).values()
          );
        }
      });

      operatorFilteredList = Object.values(groupedFiltered).reduce<OperatorI[]>(
        (acc, currentList) => {
          if (acc.length === 0) {
            return currentList;
          }
          const currentIds = new Set(currentList.map((item) => item.id));
          return acc.filter((item) => currentIds.has(item.id));
        },
        []
      );
    } else {
      operatorFilteredList = [...operatorList];
    }

    if (searchTerm) {
      operatorFilteredList = operatorFilteredList.filter((operator) =>
        operator.name.toLowerCase().includes(searchTerm.toLowerCase())
      );
    }

    if (showFavorites) {
      operatorFilteredList = operatorFilteredList.filter((operator) =>
        favorites.has(operator.id)
      );
    }

    setOperatorListFiltered([...operatorFilteredList]);
    return groups;
  }, [
    categoryOptions,
    selectedCategory,
    operatorList,
    searchTerm,
    showFavorites,
    favorites,
  ]);

  const toggleFavorite = (operatorId: string) => {
    const newFavorites = new Set(favorites);
    if (newFavorites.has(operatorId)) {
      newFavorites.delete(operatorId);
    } else {
      newFavorites.add(operatorId);
    }
    setFavorites(newFavorites);
  };

  useEffect(() => {
    const newFavorites = new Set<string>();
    operatorList.forEach((item) => {
      if (item.isStar) {
        newFavorites.add(item.id);
      }
    });
    setFavorites(newFavorites);
  }, [operatorList]);

  const handleSelectAll = (operators: OperatorI[]) => {
    const newSelected = [...selectedOperators];
    operators.forEach((operator) => {
      if (!newSelected.some((op) => op.id === operator.id)) {
        newSelected.push(operator);
      }
    });
    setSelectedOperators(newSelected);
  };

  const handleSelectCategory = (source: CategoryI[]): GroupedCategoryOption[] => {
    const groups: Record<string, GroupedCategoryOption> = {};
    const tree: GroupedCategoryOption[] = [];

    source.forEach((item) => {
      const groupName = item.type || "未分组";
      if (!groups[groupName]) {
        const newGroup = {
          label: groupName,
          title: groupName,
          options: [],
        };
        groups[groupName] = newGroup;
        tree.push(newGroup);
      }
      const childItem: Omit<CategoryI, "type"> = {
        id: item.id,
        name: item.name,
        count: item.count,
        parentId: item.parentId,
        value: item.value,
        createdAt: item.createdAt,
      };
      groups[groupName].options.push(childItem);
    });

    return tree;
  };

  return (
    <div className="w-1/4 h-full min-w-3xs flex flex-col">
      <div className="pb-4 border-b border-gray-200">
        <span className="flex items-center font-semibold text-base">
          <Layers className="w-4 h-4 mr-2" />
          标注算子库({operatorList.length})
        </span>
      </div>

      <div className="flex flex-col h-full pt-4 pr-4 overflow-hidden">
        <div className="flex flex-wrap gap-2 border-b border-gray-100 pb-2">
          <Input
            prefix={<SearchOutlined />}
            placeholder="搜索算子名称..."
            value={searchTerm}
            allowClear
            onChange={(event) => setSearchTerm(event.target.value)}
          />

          <Select
            value={selectedCategory}
            options={handleSelectCategory(categoryOptions)}
            onChange={setSelectedCategory}
            mode="multiple"
            allowClear
            className="flex-1"
            placeholder="选择分类"
          />

          <Tooltip title="只看收藏">
            <span
              className="cursor-pointer"
              onClick={() => setShowFavorites(!showFavorites)}
            >
              {showFavorites ? (
                <StarFilled style={{ color: "#FFD700" }} />
              ) : (
                <StarOutlined />
              )}
            </span>
          </Tooltip>

          <div className="flex items-center justify-right w-full">
            <Button
              type="link"
              size="small"
              onClick={(event) => {
                event.stopPropagation();
                handleSelectAll(operatorListFiltered);
              }}
            >
              全选
              <Tag>{operatorListFiltered.length}</Tag>
            </Button>
          </div>
        </div>

        <div className="flex-1 overflow-auto">
          <OperatorList
            selectedOperators={selectedOperators}
            operators={operatorListFiltered}
            favorites={favorites}
            toggleOperator={toggleOperator}
            onDragOperator={handleDragStart}
            toggleFavorite={toggleFavorite}
          />

          {operatorListFiltered.length === 0 && (
            <div className="text-center py-8 text-gray-400">
              <SearchOutlined className="text-3xl mb-2 opacity-50" />
              <div>未找到匹配的算子</div>
            </div>
          )}
        </div>
      </div>
    </div>
  );
};

export default OperatorLibrary;
