import React, { useEffect, useRef, useState, useCallback, useMemo } from 'react';
import * as d3 from 'd3';
import { 
  Neo4jNode, 
  D3Node, 
} from '../../graphTypes/graphTypes';


import { CONSTANTS, NODE_COLOR_PALETTE, VIBRANT_FALLBACK_COLORS } from '../graphCanva/constant';



class ColorManager {
  static getLabelBasedColor(node: Neo4jNode): string {
    const primaryLabel = node.labels?.[0] || 'default';
    const nodeType = node.properties?.type || 
                    node.properties?.category || 
                    node.properties?.name || 
                    primaryLabel;

    // Try exact match
    const exactMatch = this.findExactMatch(primaryLabel);
    if (exactMatch) return exactMatch;

    // Try partial match
    const partialMatch = this.findPartialMatch(primaryLabel);
    if (partialMatch) return partialMatch;

    // Try type match
    if (nodeType !== primaryLabel) {
      const typeMatch = this.findPartialMatch(nodeType.toString());
      if (typeMatch) return typeMatch;
    }

    // Generate consistent color from hash
    return this.generateHashedColor(primaryLabel);
  }

  static getEnhancedNodeColor(node: D3Node): string {
    const baseColor = this.getLabelBasedColor(node);
    
    // Apply brightness adjustments based on properties
    if (node.properties?.isImportant || node.properties?.priority === 'high') {
      return d3.rgb(baseColor).brighter(0.4).toString();
    }
    
    if (node.properties?.isDeprecated || node.properties?.status === 'inactive') {
      return d3.rgb(baseColor).darker(0.3).toString();
    }
    
    if (node.properties?.impact === 'Critical') {
      return d3.rgb(baseColor).brighter(0.2).toString();
    }
    
    return baseColor;
  }

  private static findExactMatch(label: string): string | null {
    const normalizedLabel = label.toLowerCase().trim();
    const exactKey = Object.keys(NODE_COLOR_PALETTE).find(key => 
      key.toLowerCase() === normalizedLabel
    );
    return exactKey ? NODE_COLOR_PALETTE[exactKey as keyof typeof NODE_COLOR_PALETTE] : null;
  }

  private static findPartialMatch(label: string): string | null {
    const normalizedLabel = label.toLowerCase().trim();
    const partialKey = Object.keys(NODE_COLOR_PALETTE).find(key => 
      normalizedLabel.includes(key.toLowerCase()) || key.toLowerCase().includes(normalizedLabel)
    );
    return partialKey ? NODE_COLOR_PALETTE[partialKey as keyof typeof NODE_COLOR_PALETTE] : null;
  }

  private static generateHashedColor(label: string): string {
    let hash = 0;
    for (let i = 0; i < label.length; i++) {
      hash = ((hash << 5) - hash) + label.charCodeAt(i);
      hash = hash & hash;
    }
    const colorIndex = Math.abs(hash) % VIBRANT_FALLBACK_COLORS.length;
    return VIBRANT_FALLBACK_COLORS[colorIndex];
  }

  static createGradient(
    svg: d3.Selection<SVGSVGElement, unknown, null, undefined>, 
    color: string, 
    nodeId: string
  ): string {
    const defs = svg.select('defs');
    const gradientId = `gradient-${nodeId}`;
    
    // Remove existing gradient
    defs.select(`#${gradientId}`).remove();
    
    const gradient = defs.append('radialGradient')
      .attr('id', gradientId)
      .attr('cx', '30%')
      .attr('cy', '30%')
      .attr('r', '70%');
        
    gradient.append('stop')
      .attr('offset', '0%')
      .attr('stop-color', d3.rgb(color).brighter(1.2).toString());
        
    gradient.append('stop')
      .attr('offset', '70%')
      .attr('stop-color', color);
        
    gradient.append('stop')
      .attr('offset', '100%')
      .attr('stop-color', d3.rgb(color).darker(0.3).toString());
        
    return `url(#${gradientId})`;
  }
}

export default ColorManager;