/**
 * Custom hook for search functionality in the modeler
 * Manages search visibility, terms, highlighting, and focus.
 *
 * When a search result is selected the corresponding element is selected on
 * the canvas (node or edge) and the viewport pans/zooms to bring it into
 * view.  For edges (conditions) the viewport centers on the edge's source
 * node since edges don't have a fixed position of their own.
 */

import { useState, useCallback } from 'react';
import { useStore, Node, Edge } from '../store/store';
import { TIMING } from '../constants/dimensions';

export function useSearch() {
  const setViewportTarget = useStore(state => state.setViewportTarget);
  const selectNode = useStore(state => state.selectNode);
  const selectEdge = useStore(state => state.selectEdge);
  const nodes = useStore(state => state.nodes);

  // Search state
  const [isSearchVisible, setIsSearchVisible] = useState(false);
  const [searchTerm, setSearchTerm] = useState('');
  const [highlightedSearchResult, setHighlightedSearchResult] = useState<any>(null);

  // Handle search term changes
  const onSearchChange = useCallback((term: string) => {
    setSearchTerm(term);
  }, []);

  /**
   * Center the viewport on the given node (by id).
   */
  const centerOnNode = useCallback((nodeId: string) => {
    setViewportTarget({
      type: 'center',
      nodeId,
      options: { zoom: 1.2, duration: TIMING.VIEWPORT_PAN_DURATION },
    });
  }, [setViewportTarget]);

  /**
   * Select a search result on the canvas and pan/zoom to it.
   *
   * - Nodes are selected directly and the viewport centers on them.
   * - Edges (conditions) are selected and the viewport centers on the
   *   edge's source node.
   */
  const selectAndCenter = useCallback((result: { id: string; type: 'node' | 'edge'; data: Node | Edge }) => {
    if (result.type === 'node') {
      selectNode(result.data as Node);
      centerOnNode(result.id);
    } else {
      const edge = result.data as Edge;
      selectEdge(edge);
      // Center on the source node of the edge
      const sourceNode = nodes.find(n => n.id === edge.source);
      if (sourceNode) {
        centerOnNode(sourceNode.id);
      }
    }
  }, [selectNode, selectEdge, nodes, centerOnNode]);

  // Handle search result highlighting (hover / auto-select single result)
  const onSearchHighlight = useCallback((result: any) => {
    setHighlightedSearchResult(result);
    if (result?.data) {
      selectAndCenter(result);
    }
  }, [selectAndCenter]);

  // Handle search focus (when clicking on search results)
  const onSearchFocus = useCallback((_data: any) => {
    // Selection + centering is already handled by onSearchHighlight via
    // handleResultSelect in SearchBar.  This callback is kept for
    // backward compatibility but no longer needs to duplicate the logic.
  }, []);

  // Handle general highlighting (unified with search highlighting)
  const onHighlight = useCallback((result: any) => {
    setHighlightedSearchResult(result);
  }, []);

  // Handle general focus (unified with search focus)
  const onFocus = useCallback((data: any) => {
    if (data.type === 'node') {
      centerOnNode(data.id);
    } else if (data.source) {
      // Edge — center on its source node
      const sourceNode = nodes.find((n: Node) => n.id === data.source);
      if (sourceNode) {
        centerOnNode(sourceNode.id);
      }
    }
  }, [nodes, centerOnNode]);

  // Toggle search visibility
  const toggleSearch = useCallback(() => {
    setIsSearchVisible(prev => !prev);
  }, []);

  // Clear search and hide
  const clearSearch = useCallback(() => {
    setIsSearchVisible(false);
    setSearchTerm('');
    setHighlightedSearchResult(null);
  }, []);

  return {
    // State
    isSearchVisible,
    searchTerm,
    highlightedSearchResult,
    
    // Actions
    onSearchChange,
    onSearchHighlight,
    onSearchFocus,
    onHighlight,
    onFocus,
    toggleSearch,
    clearSearch,
    setIsSearchVisible
  };
}