/**
 * TreeNavigation
 * 
 * A flexible, recursive tree navigation component that supports:
 * - Dynamic sublevels of any depth
 * - Expandable/collapsible nodes
 * - Auto-expand based on active path
 * - Customizable icons and badges
 * - Section headers
 * - NavLink integration with React Router
 */

import React, { useState, useEffect, ReactNode } from 'react';
import { NavLink, useLocation } from 'react-router-dom';
import { FaChevronDown, FaChevronRight } from 'react-icons/fa';
import styles from './TreeNavigation.module.css';

// =============================================================================
// TYPES
// =============================================================================

export interface TreeNodeItem {
  /** Unique identifier for this node */
  id: string;
  /** Display label */
  label: string;
  /** Icon to display (React component or element) */
  icon?: ReactNode;
  /** Badge content (e.g., count, role) */
  badge?: string | number;
  /** Optional badge style variant */
  badgeVariant?: 'default' | 'primary' | 'success' | 'warning';
  /** Path for navigation (if this is a link) */
  path?: string;
  /** Child nodes */
  children?: TreeNodeItem[];
  /** Whether this node is expanded by default */
  defaultExpanded?: boolean;
  /** Whether this node can be expanded/collapsed (default: true if has children) */
  expandable?: boolean;
  /** Custom onClick handler (overrides navigation) */
  onClick?: () => void;
  /** Whether this node is disabled */
  disabled?: boolean;
  /** Additional CSS class */
  className?: string;
  /** Indent level (auto-calculated) */
  level?: number;
  /** Data attribute for testing/identification */
  dataId?: string;
}

export interface TreeSectionItem {
  /** Section type */
  type: 'section';
  /** Section title */
  title: string;
  /** Child nodes in this section */
  children: TreeNodeItem[];
  /** Whether this section is initially visible */
  visible?: boolean;
}

export interface TreeSeparatorItem {
  /** Separator type */
  type: 'separator';
}

export type TreeItem = TreeNodeItem | TreeSectionItem | TreeSeparatorItem;

export interface TreeNavigationProps {
  /** Array of tree items to render */
  items: TreeItem[];
  /** Whether to auto-expand nodes when their path is active */
  autoExpandActive?: boolean;
  /** Callback when a node is clicked */
  onNodeClick?: (node: TreeNodeItem) => void;
  /** Maximum depth to render (0 = unlimited) */
  maxDepth?: number;
  /** Additional CSS class for the container */
  className?: string;
}

// =============================================================================
// HELPER FUNCTIONS
// =============================================================================

/**
 * Check if a node or any of its descendants has the active path
 */
function hasActivePath(node: TreeNodeItem, currentPath: string): boolean {
  if (node.path && currentPath.startsWith(node.path)) {
    return true;
  }
  if (node.children) {
    return node.children.some(child => hasActivePath(child, currentPath));
  }
  return false;
}

/**
 * Type guard to check if item is a TreeNodeItem
 */
function isTreeNode(item: TreeItem): item is TreeNodeItem {
  return !('type' in item);
}

/**
 * Type guard to check if item is a TreeSectionItem
 */
function isTreeSection(item: TreeItem): item is TreeSectionItem {
  return 'type' in item && item.type === 'section';
}

/**
 * Type guard to check if item is a TreeSeparatorItem
 */
function isTreeSeparator(item: TreeItem): item is TreeSeparatorItem {
  return 'type' in item && item.type === 'separator';
}

// =============================================================================
// TREE NODE COMPONENT
// =============================================================================

interface TreeNodeProps {
  node: TreeNodeItem;
  level: number;
  autoExpandActive: boolean;
  currentPath: string;
  onNodeClick?: (node: TreeNodeItem) => void;
  maxDepth: number;
}

const TreeNode: React.FC<TreeNodeProps> = ({
  node,
  level,
  autoExpandActive,
  currentPath,
  onNodeClick,
  maxDepth,
}) => {
  const hasChildren = node.children && node.children.length > 0;
  const isExpandable = node.expandable !== false && hasChildren;
  const shouldAutoExpand = autoExpandActive && hasActivePath(node, currentPath);
  
  const [isExpanded, setIsExpanded] = useState(
    node.defaultExpanded ?? shouldAutoExpand ?? false
  );

  // Auto-expand when path becomes active
  useEffect(() => {
    if (autoExpandActive && hasActivePath(node, currentPath) && !isExpanded) {
      setIsExpanded(true);
    }
  }, [currentPath, autoExpandActive, node]);

  // Check if this exact node is active
  const isActive = node.path ? currentPath === node.path || currentPath.startsWith(node.path + '/') : false;

  // Handle click
  const handleClick = (e: React.MouseEvent) => {
    if (node.disabled) {
      e.preventDefault();
      return;
    }

    if (node.onClick) {
      e.preventDefault();
      node.onClick();
      return;
    }

    if (isExpandable && !node.path) {
      // If only expandable (no path), toggle expand
      setIsExpanded(!isExpanded);
    } else if (isExpandable && node.path) {
      // If both expandable and has path, expand on click but allow navigation
      if (!isExpanded) {
        setIsExpanded(true);
      }
    }

    if (onNodeClick) {
      onNodeClick(node);
    }
  };

  // Handle chevron click separately
  const handleChevronClick = (e: React.MouseEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setIsExpanded(!isExpanded);
  };

  // Get level-specific styles
  const getLevelClass = () => {
    switch (level) {
      case 0: return styles.levelRoot;
      case 1: return styles.levelOne;
      case 2: return styles.levelTwo;
      case 3: return styles.levelThree;
      default: return styles.levelDeep;
    }
  };

  // Render the node content
  const nodeContent = (
    <>
      {isExpandable && (
        <span className={styles.chevron} onClick={handleChevronClick}>
          {isExpanded ? <FaChevronDown /> : <FaChevronRight />}
        </span>
      )}
      {!isExpandable && hasChildren === false && (
        <span className={styles.chevronSpacer} />
      )}
      {node.icon && <span className={styles.nodeIcon}>{node.icon}</span>}
      <span className={styles.nodeLabel} title={node.label}>{node.label}</span>
      {node.badge !== undefined && (
        <span 
          className={`${styles.nodeBadge} ${node.badgeVariant ? styles[`badge${node.badgeVariant.charAt(0).toUpperCase() + node.badgeVariant.slice(1)}`] : ''}`}
        >
          {node.badge}
        </span>
      )}
    </>
  );

  // Determine if we should render as NavLink or button
  const nodeClasses = `${styles.treeNode} ${getLevelClass()} ${isActive ? styles.active : ''} ${node.disabled ? styles.disabled : ''} ${node.className || ''}`;

  const nodeElement = node.path ? (
    <NavLink
      to={node.path}
      className={nodeClasses}
      onClick={handleClick}
      data-id={node.dataId}
    >
      {nodeContent}
    </NavLink>
  ) : (
    <button
      type="button"
      className={nodeClasses}
      onClick={handleClick}
      disabled={node.disabled}
      data-id={node.dataId}
    >
      {nodeContent}
    </button>
  );

  // Check max depth
  const canRenderChildren = maxDepth === 0 || level < maxDepth;

  return (
    <div className={styles.treeNodeContainer}>
      {nodeElement}
      {isExpanded && hasChildren && canRenderChildren && (
        <div className={styles.treeNodeChildren}>
          {node.children!.map((child, index) => (
            <TreeNode
              key={child.id || `${node.id}-child-${index}`}
              node={child}
              level={level + 1}
              autoExpandActive={autoExpandActive}
              currentPath={currentPath}
              onNodeClick={onNodeClick}
              maxDepth={maxDepth}
            />
          ))}
        </div>
      )}
    </div>
  );
};

// =============================================================================
// TREE SECTION COMPONENT
// =============================================================================

interface TreeSectionProps {
  section: TreeSectionItem;
  autoExpandActive: boolean;
  currentPath: string;
  onNodeClick?: (node: TreeNodeItem) => void;
  maxDepth: number;
}

const TreeSection: React.FC<TreeSectionProps> = ({
  section,
  autoExpandActive,
  currentPath,
  onNodeClick,
  maxDepth,
}) => {
  if (section.visible === false) {
    return null;
  }

  return (
    <div className={styles.treeSection}>
      <div className={styles.sectionHeader}>
        <span className={styles.sectionTitle}>{section.title}</span>
      </div>
      <div className={styles.sectionContent}>
        {section.children.map((node, index) => (
          <TreeNode
            key={node.id || `section-${section.title}-${index}`}
            node={node}
            level={0}
            autoExpandActive={autoExpandActive}
            currentPath={currentPath}
            onNodeClick={onNodeClick}
            maxDepth={maxDepth}
          />
        ))}
      </div>
    </div>
  );
};

// =============================================================================
// MAIN COMPONENT
// =============================================================================

export const TreeNavigation: React.FC<TreeNavigationProps> = ({
  items,
  autoExpandActive = true,
  onNodeClick,
  maxDepth = 0,
  className = '',
}) => {
  const location = useLocation();
  const currentPath = location.pathname;

  return (
    <nav className={`${styles.treeNavigation} ${className}`}>
      {items.map((item, index) => {
        if (isTreeSeparator(item)) {
          return <div key={`separator-${index}`} className={styles.separator} />;
        }

        if (isTreeSection(item)) {
          return (
            <TreeSection
              key={`section-${item.title}-${index}`}
              section={item}
              autoExpandActive={autoExpandActive}
              currentPath={currentPath}
              onNodeClick={onNodeClick}
              maxDepth={maxDepth}
            />
          );
        }

        if (isTreeNode(item)) {
          return (
            <TreeNode
              key={item.id || `node-${index}`}
              node={item}
              level={0}
              autoExpandActive={autoExpandActive}
              currentPath={currentPath}
              onNodeClick={onNodeClick}
              maxDepth={maxDepth}
            />
          );
        }

        return null;
      })}
    </nav>
  );
};

export default TreeNavigation;
