// src/utils/clientUtils.ts

export function createToolSlug(toolName: string): string {
  if (!toolName || typeof toolName !== 'string') {
    console.warn('[CLIENT-UTILS] Invalid toolName provided to createToolSlug:', toolName);
    return '';
  }
  
  return toolName.toLowerCase()
    .replace(/[^a-z0-9\s-]/g, '')
    .replace(/\s+/g, '-')
    .replace(/-+/g, '-')
    .replace(/^-|-$/g, '');
}

export function findToolByIdentifier(tools: any[], identifier: string): any | undefined {
  if (!identifier || !Array.isArray(tools)) return undefined;
  
  return tools.find((tool: any) => 
    tool.name === identifier || 
    createToolSlug(tool.name) === identifier.toLowerCase()
  );
}

export function isToolHosted(tool: any): boolean {
  return tool.projectUrl !== undefined && 
         tool.projectUrl !== null && 
         tool.projectUrl !== "" && 
         tool.projectUrl.trim() !== "";
}

export function sanitizeText(text: string): string {
  if (typeof text !== 'string') return '';
  
  return text
    .replace(/^#{1,6}\s+/gm, '')
    .replace(/^\s*[-*+]\s+/gm, '')
    .replace(/^\s*\d+\.\s+/gm, '')
    .replace(/\*\*(.+?)\*\*/g, '$1')
    .replace(/\*(.+?)\*/g, '$1')
    .replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
    .replace(/```[\s\S]*?```/g, '[CODE BLOCK]')
    .replace(/`([^`]+)`/g, '$1')
    .replace(/<[^>]+>/g, '')
    .replace(/\n\s*\n\s*\n/g, '\n\n')
    .trim();
}

export function escapeHtml(text: string): string {
  if (typeof text !== 'string') return String(text);
  const div = document.createElement('div');
  div.textContent = text;
  return div.innerHTML;
}

export function truncateText(text: string, maxLength: number): string {
  if (!text || text.length <= maxLength) return text;
  return text.slice(0, maxLength) + '...';
}

export function summarizeData(data: any): string {
  if (data === null || data === undefined) return 'null';
  if (typeof data === 'string') {
    return data.length > 100 ? data.slice(0, 100) + '...' : data;
  }
  if (typeof data === 'number' || typeof data === 'boolean') {
    return data.toString();
  }
  if (Array.isArray(data)) {
    if (data.length === 0) return '[]';
    if (data.length <= 3) return JSON.stringify(data);
    return `[${data.slice(0, 3).map(i => typeof i === 'string' ? i : JSON.stringify(i)).join(', ')}, ...+${data.length - 3}]`;
  }
  if (typeof data === 'object') {
    const keys = Object.keys(data);
    if (keys.length === 0) return '{}';
    if (keys.length <= 3) {
      return '{' + keys.map(k => `${k}: ${typeof data[k] === 'string' ? data[k].slice(0, 20) + (data[k].length > 20 ? '...' : '') : JSON.stringify(data[k])}`).join(', ') + '}';
    }
    return `{${keys.slice(0, 3).join(', ')}, ...+${keys.length - 3} keys}`;
  }
  return String(data);
}

export function formatDuration(ms: number): string {
  if (ms < 1000) return '< 1s';
  if (ms < 60000) return `${Math.ceil(ms / 1000)}s`;
  const minutes = Math.floor(ms / 60000);
  const seconds = Math.ceil((ms % 60000) / 1000);
  return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;
}

export function showElement(element: HTMLElement | null): void {
  if (element) {
    element.style.display = 'block';
    element.classList.remove('hidden');
  }
}

export function hideElement(element: HTMLElement | null): void {
  if (element) {
    element.style.display = 'none';
    element.classList.add('hidden');
  }
}

interface AutocompleteOptions {
  minLength?: number;
  maxResults?: number;
  placeholder?: string;
  allowMultiple?: boolean;
  separator?: string;
  filterFunction?: (query: string) => any[];
  renderFunction?: (item: any) => string;
  hiddenInput?: HTMLInputElement;
}

export class AutocompleteManager {
  public input: HTMLInputElement;
  public dataSource: any[];
  public options: AutocompleteOptions;
  public isOpen: boolean = false;
  public selectedIndex: number = -1;
  public filteredData: any[] = [];
  public selectedItems: Set<string> = new Set();
  public dropdown!: HTMLElement;
  public selectedContainer!: HTMLElement;

  constructor(inputElement: HTMLInputElement, dataSource: any[], options: AutocompleteOptions = {}) {
    this.input = inputElement;
    this.dataSource = dataSource;
    this.options = {
      minLength: 1,
      maxResults: 10,
      placeholder: 'Type to search...',
      allowMultiple: false,
      separator: ', ',
      filterFunction: this.defaultFilter.bind(this),
      renderFunction: this.defaultRender.bind(this),
      ...options
    };
    
    this.init();
  }
  
  init(): void {
    this.createDropdown();
    this.bindEvents();
    
    if (this.options.allowMultiple) {
      this.initMultipleMode();
    }
  }
  
  createDropdown(): void {
    this.dropdown = document.createElement('div');
    this.dropdown.className = 'autocomplete-dropdown';
    this.dropdown.style.cssText = `
      position: absolute;
      top: 100%;
      left: 0;
      right: 0;
      background: var(--color-bg);
      border: 1px solid var(--color-border);
      border-radius: 0.375rem;
      box-shadow: var(--shadow-lg);
      max-height: 200px;
      overflow-y: auto;
      z-index: 1000;
      display: none;
    `;
    
    const parentElement = this.input.parentNode as HTMLElement;
    parentElement.style.position = 'relative';
    parentElement.insertBefore(this.dropdown, this.input.nextSibling);
  }
  
  bindEvents(): void {
    this.input.addEventListener('input', (e) => {
      this.handleInput((e.target as HTMLInputElement).value);
    });
    
    this.input.addEventListener('keydown', (e) => {
      this.handleKeydown(e);
    });
    
    this.input.addEventListener('focus', () => {
      if (this.input.value.length >= (this.options.minLength || 1)) {
        this.showDropdown();
      }
    });
    
    this.input.addEventListener('blur', () => {
      setTimeout(() => {
        const activeElement = document.activeElement;
        if (!activeElement || !this.dropdown.contains(activeElement)) {
          this.hideDropdown();
        }
      }, 150);
    });
    
    document.addEventListener('click', (e) => {
      const target = e.target as Node;
      if (!this.input.contains(target) && !this.dropdown.contains(target)) {
        this.hideDropdown();
      }
    });
  }
  
  initMultipleMode(): void {
    this.selectedContainer = document.createElement('div');
    this.selectedContainer.className = 'autocomplete-selected';
    this.selectedContainer.style.cssText = `
      display: flex;
      flex-wrap: wrap;
      gap: 0.5rem;
      margin-bottom: 0.5rem;
      min-height: 1.5rem;
    `;
    
    const parentElement = this.input.parentNode as HTMLElement;
    parentElement.insertBefore(this.selectedContainer, this.input);
    this.updateSelectedDisplay();
  }
  
  handleInput(value: string): void {
    if (value.length >= (this.options.minLength || 1)) {
      this.filteredData = this.options.filterFunction!(value);
      this.selectedIndex = -1;
      this.renderDropdown();
      this.showDropdown();
    } else {
      this.hideDropdown();
    }
  }
  
  handleKeydown(e: KeyboardEvent): void {
    if (!this.isOpen) return;
    
    switch (e.key) {
      case 'ArrowDown':
        e.preventDefault();
        this.selectedIndex = Math.min(this.selectedIndex + 1, this.filteredData.length - 1);
        this.updateHighlight();
        break;
        
      case 'ArrowUp':
        e.preventDefault();
        this.selectedIndex = Math.max(this.selectedIndex - 1, -1);
        this.updateHighlight();
        break;
        
      case 'Enter':
        e.preventDefault();
        if (this.selectedIndex >= 0) {
          this.selectItem(this.filteredData[this.selectedIndex]);
        }
        break;
        
      case 'Escape':
        this.hideDropdown();
        break;
    }
  }
  
  defaultFilter(query: string): any[] {
    const searchTerm = query.toLowerCase();
    return this.dataSource
      .filter(item => {
        const text = typeof item === 'string' ? item : item.name || item.label || item.toString();
        return text.toLowerCase().includes(searchTerm) && 
               (!this.options.allowMultiple || !this.selectedItems.has(text));
      })
      .slice(0, this.options.maxResults || 10);
  }
  
  defaultRender(item: any): string {
    const text = typeof item === 'string' ? item : item.name || item.label || item.toString();
    return `<div class="autocomplete-item">${escapeHtml(text)}</div>`;
  }
  
  renderDropdown(): void {
    if (this.filteredData.length === 0) {
      this.dropdown.innerHTML = '<div class="autocomplete-no-results">No results found</div>';
      return;
    }
    
    this.dropdown.innerHTML = this.filteredData
      .map((item, index) => {
        const content = this.options.renderFunction!(item);
        return `<div class="autocomplete-option" data-index="${index}" style="
          padding: 0.5rem;
          cursor: pointer;
          border-bottom: 1px solid var(--color-border-light);
          transition: background-color 0.15s ease;
        ">${content}</div>`;
      })
      .join('');
    
    this.dropdown.querySelectorAll('.autocomplete-option').forEach((option, index) => {
      option.addEventListener('click', () => {
        this.selectItem(this.filteredData[index]);
      });
      
      option.addEventListener('mouseenter', () => {
        this.selectedIndex = index;
        this.updateHighlight();
      });
    });
  }
  
  updateHighlight(): void {
    this.dropdown.querySelectorAll('.autocomplete-option').forEach((option, index) => {
      (option as HTMLElement).style.backgroundColor = index === this.selectedIndex 
        ? 'var(--color-bg-secondary)' 
        : 'transparent';
    });
  }
  
  selectItem(item: any): void {
    const text = typeof item === 'string' ? item : item.name || item.label || item.toString();
    
    if (this.options.allowMultiple) {
      this.selectedItems.add(text);
      this.updateSelectedDisplay();
      this.updateInputValue();
      this.input.value = '';
    } else {
      this.input.value = text;
      this.hideDropdown();
    }
    
    this.input.dispatchEvent(new CustomEvent('autocomplete:select', {
      detail: { item, text, selectedItems: Array.from(this.selectedItems) }
    }));
  }
  
  removeItem(text: string): void {
    if (this.options.allowMultiple) {
      this.selectedItems.delete(text);
      this.updateSelectedDisplay();
      this.updateInputValue();
    }
  }
  
  updateSelectedDisplay(): void {
    if (!this.options.allowMultiple || !this.selectedContainer) return;
    
    this.selectedContainer.innerHTML = Array.from(this.selectedItems)
      .map(item => `
        <span class="autocomplete-tag" style="
          background-color: var(--color-primary);
          color: white;
          padding: 0.25rem 0.5rem;
          border-radius: 0.25rem;
          font-size: 0.875rem;
          display: flex;
          align-items: center;
          gap: 0.25rem;
        ">
          ${escapeHtml(item)}
          <button type="button" class="autocomplete-remove" data-item="${escapeHtml(item)}" style="
            background: none;
            border: none;
            color: white;
            font-weight: bold;
            cursor: pointer;
            padding: 0;
            width: 1rem;
            height: 1rem;
            display: flex;
            align-items: center;
            justify-content: center;
          ">×</button>
        </span>
      `)
      .join('');
    
    this.selectedContainer.querySelectorAll('.autocomplete-remove').forEach(btn => {
      btn.addEventListener('click', (e) => {
        e.preventDefault();
        this.removeItem((btn as HTMLElement).getAttribute('data-item')!);
      });
    });
  }
  
  updateInputValue(): void {
    if (this.options.allowMultiple && this.options.hiddenInput) {
      this.options.hiddenInput.value = Array.from(this.selectedItems).join(this.options.separator || ', ');
    }
  }
  
  showDropdown(): void {
    this.dropdown.style.display = 'block';
    this.isOpen = true;
  }
  
  hideDropdown(): void {
    this.dropdown.style.display = 'none';
    this.isOpen = false;
    this.selectedIndex = -1;
  }
  
  setDataSource(newDataSource: any[]): void {
    this.dataSource = newDataSource;
  }
  
  getSelectedItems(): string[] {
    return Array.from(this.selectedItems);
  }
  
  setSelectedItems(items: string[]): void {
    this.selectedItems = new Set(items);
    if (this.options.allowMultiple) {
      this.updateSelectedDisplay();
      this.updateInputValue();
    }
  }
  
  destroy(): void {
    if (this.dropdown && this.dropdown.parentNode) {
      this.dropdown.parentNode.removeChild(this.dropdown);
    }
    if (this.selectedContainer && this.selectedContainer.parentNode) {
      this.selectedContainer.parentNode.removeChild(this.selectedContainer);
    }
  }
}