import React, { Key, useEffect, useRef } from "react";

//import { FolderOutlined } from '@ant-design/icons';
import Tree from "rc-tree";
import "rc-tree/assets/index.css"
import "./CtTree.css"
import { useUiLoadingStore } from "@/lib/_AG";



export interface CtTreeNode {
  key: string;
  title: string;
  children?: CtTreeNode[];
  isLeaf?: boolean;
}


export function treeToList(tree: CtTreeNode[]): CtTreeNode[] {
  const result: CtTreeNode[] = [];

  for (const node of tree) {
    result.push(node);

    if (node.children && node.children.length > 0) {
      const childrenFlatNodes = treeToList(node.children);
      result.push(...childrenFlatNodes);
    }
  }

  return result;
}

export function expandAndSelectTreeNode(
  treeData: any[],
  selectedKey: Key,
  setSelectedKeys: React.Dispatch<React.SetStateAction<Key[]>>,
  expandedKeys: Key[], 
  setExpandedKeys: React.Dispatch<React.SetStateAction<Key[]>>
) {
  if (selectedKey != "") {
    const uniqueKeys: Key[] = Array.from(new Set([...expandedKeys, ...findParentKeys(treeData, selectedKey)]));

    setExpandedKeys(uniqueKeys) 
    setSelectedKeys([selectedKey])
  }
}

export function getAllNodeKeys(treeData: any[]): Key[] {
  const keys: string[] = [];

  const traverse = (nodes: any[]) => {
    nodes.forEach(node => {
      keys.push(node.key);

      if (node.children && node.children.length > 0) {
        traverse(node.children);
      }
    });
  };

  traverse(treeData);
  return keys;
};

export function findNodeByKey(tree: any[], key: Key): any | null {
  for (const node of tree) {
    if (node.key === key) {
      return node;
    }

    if (node.children) {
      const result = findNodeByKey(node.children, key);
      if (result !== null) {
        return result;
      }
    }
  }

  return null;
}

export function findParentKeys(tree: any[], key: Key, path: string[] = []): string[] {
  for (const node of tree) {
    const newPath = [...path, node.key];

    if (node.key === key) {
      return newPath.slice(0, -1);
    }

    if (node.children) {
      const result = findParentKeys(node.children, key, newPath);
      if (result.length) return result;
    }
  }

  return [];
}

export function findRootNodeByKey(tree: any[], key: Key): any | null {
  for (const node of tree) {
    if (node.key === key) {
      return node;
    }

    if (node.children && node.children.length > 0) {
      const targetNode = findNodeByKey(node.children, key);
      if (targetNode) {
        return node;
      }
    }
  }

  return null;
}

export function addNodeByKey(tree: any[], key: Key, newNode: any): any[] {
  let found = false;

  function traverse(nodes: any[]): any[] {
    return nodes.map((node) => {
      if (node.key === key) {
        found = true;
        const updatedChildren = [
          ...(node.children || []),
          ...(Array.isArray(newNode) ? newNode : [newNode]),
        ];
        return { ...node, children: updatedChildren, isLeaf: false };
      }

      if (Array.isArray(node.children)) {
        const updatedChildren = traverse(node.children);
        if (updatedChildren !== node.children) {
          return { ...node, children: updatedChildren };
        }
      }

      return node;
    });
  }

  const updatedTree = traverse(tree);

  if (!found) {
    return [...tree, ...(Array.isArray(newNode) ? newNode : [newNode])];
  }

  return updatedTree;
}

export function changeNodeByKey(tree: any[], key: Key, newNode: any): any[] {
  return tree.map((node) => {
      if (node.biz_group_id === key) {
          return {
              ...node,
              ...newNode
          };
      }

      if (node.children) {
          const newChildren = changeNodeByKey(node.children, key, newNode);
          if (newChildren !== node.children) {
              return {
                  ...node,
                  children: newChildren
              };
          }
      }

      return node;
  });
};

/*
export function deleteNodeByKey(tree: any[], key: Key): any[] {
  return tree.map((node) => {
      if (node.key === key) {
        return null;
      }

      if (node.children) {
        const updatedChildren = deleteNodeByKey(node.children, key);
        return { ...node, children: updatedChildren };
      }

      return node;
    }).filter(Boolean);
}
*/
export function deleteNodeByKey(tree: any[], key: Key): any[] {
  return tree
    .map((node) => {
      if (node.key === key) {
        return null;
      }

      if (node.children) {
        const updatedChildren = deleteNodeByKey(node.children, key);
        const isNowLeaf = updatedChildren.length === 0;

        return {
          ...node,
          children: updatedChildren,
          isLeaf: isNowLeaf,
        };
      }

      return node;
    })
    .filter(Boolean);
}

export default function CtTree({ treeData, selectedKeys, setSelectedKeys, onClickNode, expandedKeys, setExpandedKeys, onClickExpanded, isLoading }: {
  treeData: any;
  selectedKeys: Key[];
  setSelectedKeys: React.Dispatch<React.SetStateAction<Key[]>>;
  onClickNode?: (key: Key) => void;
  expandedKeys: Key[];
  setExpandedKeys: React.Dispatch<React.SetStateAction<Key[]>>;
  onClickExpanded?: (key: Key) => void;
  isLoading?: boolean;
}) {
  const treeLoading = useUiLoadingStore((s) => s.isTreeLoading);
  const loading = isLoading ?? treeLoading;

  const handleExpand = (keys: Key[]) => {
    //console.log("expand keys = " + keys);

    const expanded = keys.filter(x => !expandedKeys.includes(x));
    if (expanded.length > 0) {
      //console.log("handleExpand, expanded = " + expanded);
      onClickExpanded?.(expanded[0]);
    }

    setExpandedKeys(keys);
  }

  const handleSelect = (keys: Key[]) => {
    //console.log("handleTreeSelect: " + keys);
    if (keys.length == 0)
      return;

    setSelectedKeys(keys);

    onClickNode?.(keys[0]);
  }

  useEffect(() => {
    const handleGlobalClick = (event: any) => {
      if (event.target.matches('.rc-tree-treenode')) {
        console.log("event.target = ", event.target)

        setSelectedKeys([]);
      }
    };

    document.addEventListener('mousedown', handleGlobalClick);
    return () => document.removeEventListener('mousedown', handleGlobalClick);
  }, []);
  

  const switcherIcon = (nodeProps: any) => {
    console.log("nodeProps = ", nodeProps);
    //const hasChildren = nodeProps?.data?.children && nodeProps.data.children.length > 0;
    //if (hasChildren == undefined || hasChildren == null) return null;
    if (nodeProps.isLeaf) return null;
    return nodeProps.expanded ? <span className="ct-tree-switcher ct-tree-switcher-open" /> : <span className="ct-tree-switcher ct-tree-switcher-close" />
  };

  return (
    <div className="relative min-h-[80px]">
      <div className={loading ? "pointer-events-none opacity-60" : ""}>
        <Tree
          treeData={treeData}
          switcherIcon={switcherIcon}
          defaultExpandAll={true}
          selectedKeys={selectedKeys}
          checkable={false}
          expandedKeys={expandedKeys}
          onExpand={handleExpand}
          onSelect={handleSelect}
        />
      </div>
      {loading && (
        <div className="absolute inset-0 flex items-center justify-center bg-white/50 dark:bg-gray-900/40">
          <div className="flex items-center gap-2 text-sm text-gray-600 dark:text-gray-300">
            <span className="h-4 w-4 animate-spin rounded-full border-2 border-gray-300 border-t-brand-500"></span>
            불러오는 중...
          </div>
        </div>
      )}
    </div>
  );
}
