/**
 * useAIUIControl — WebSocket client hook for AI-driven UI control.
 *
 * Task 4.3: Frontend useAIUIControl Hook
 * Task 4.4: Command: Navigate
 * Task 4.5: Command: Filter setzen
 * Task 4.6: Command: Contact öffnen
 * Task 4.7: Command: Modal öffnen/schließen
 * Task 4.8: Command: Tab wechseln
 * Task 4.9: Command: Settings ändern
 * Task 4.10: UI-Action-Feedback an KI
 *
 * Connects to /api/v1/ai-ui-control/ws, receives commands from AI agents,
 * executes them using React Router navigation, URL search params, and Zustand
 * stores, then sends feedback back through the WebSocket.
 */

import { useEffect, useRef, useCallback } from 'react';
import { useNavigate, useSearchParams, useLocation } from 'react-router-dom';
import { useAIUIControlStore, type UICommand, type UICommandFeedback } from '@/store/aiUIControlStore';

export function useAIUIControl() {
  const wsRef = useRef<WebSocket | null>(null);
  const reconnectTimeout = useRef<number | undefined>(undefined);
  const navigate = useNavigate();
  const [searchParams, setSearchParams] = useSearchParams();
  const location = useLocation();

  const setConnected = useAIUIControlStore((s) => s.setConnected);
  const setActiveCommand = useAIUIControlStore((s) => s.setActiveCommand);
  const addCommandToHistory = useAIUIControlStore((s) => s.addCommandToHistory);
  const setLastFeedback = useAIUIControlStore((s) => s.setLastFeedback);
  const setActiveModal = useAIUIControlStore((s) => s.setActiveModal);
  const setActiveTab = useAIUIControlStore((s) => s.setActiveTab);
  const setPendingFilter = useAIUIControlStore((s) => s.setPendingFilter);
  const setPendingSettings = useAIUIControlStore((s) => s.setPendingSettings);
  const clearPending = useAIUIControlStore((s) => s.clearPending);

  /** Send feedback back to backend via WebSocket */
  const sendFeedback = useCallback(
    (feedback: Partial<UICommandFeedback> & { command_id: string; status: string }) => {
      const ws = wsRef.current;
      if (ws?.readyState === WebSocket.OPEN) {
        ws.send(
          JSON.stringify({
            type: 'feedback',
            ...feedback,
          }),
        );
      }
      setLastFeedback(feedback as UICommandFeedback);
    },
    [setLastFeedback],
  );

  /** Execute a navigate command (Task 4.4) */
  const executeNavigate = useCallback(
    (cmd: UICommand) => {
      if (!cmd.path) {
        sendFeedback({
          command_id: cmd.command_id,
          status: 'failed',
          action: 'navigate',
          error: 'No path provided',
        });
        return;
      }
      try {
        navigate(cmd.path);
        sendFeedback({
          command_id: cmd.command_id,
          status: 'success',
          action: 'navigate',
          current_path: cmd.path,
        });
      } catch (err) {
        sendFeedback({
          command_id: cmd.command_id,
          status: 'failed',
          action: 'navigate',
          error: String(err),
        });
      }
    },
    [navigate, sendFeedback],
  );

  /** Execute a filter command (Task 4.5) */
  const executeFilter = useCallback(
    (cmd: UICommand) => {
      if (!cmd.entity || !cmd.filter) {
        sendFeedback({
          command_id: cmd.command_id,
          status: 'failed',
          action: 'filter',
          error: 'Missing entity or filter',
        });
        return;
      }
      try {
        // Navigate to the entity list page first
        const entityPath = `/${cmd.entity}`;
        if (!location.pathname.startsWith(entityPath)) {
          navigate(entityPath);
        }
        // Set filter as URL search params
        const newParams = new URLSearchParams();
        for (const [key, value] of Object.entries(cmd.filter)) {
          newParams.set(key, String(value));
        }
        setSearchParams(newParams);
        // Also set in store for components that read from store
        setPendingFilter({ entity: cmd.entity, filter: cmd.filter });
        sendFeedback({
          command_id: cmd.command_id,
          status: 'success',
          action: 'filter',
          current_path: `${entityPath}?${newParams.toString()}`,
          data: { entity: cmd.entity, filter: cmd.filter },
        });
      } catch (err) {
        sendFeedback({
          command_id: cmd.command_id,
          status: 'failed',
          action: 'filter',
          error: String(err),
        });
      }
    },
    [navigate, location.pathname, setSearchParams, setPendingFilter, sendFeedback],
  );

  /** Execute an open_contact command (Task 4.6) */
  const executeOpenContact = useCallback(
    (cmd: UICommand) => {
      if (!cmd.contact_id) {
        sendFeedback({
          command_id: cmd.command_id,
          status: 'failed',
          action: 'open_contact',
          error: 'No contact_id provided',
        });
        return;
      }
      try {
        const path = `/contacts/${cmd.contact_id}`;
        navigate(path);
        sendFeedback({
          command_id: cmd.command_id,
          status: 'success',
          action: 'open_contact',
          current_path: path,
        });
      } catch (err) {
        sendFeedback({
          command_id: cmd.command_id,
          status: 'failed',
          action: 'open_contact',
          error: String(err),
        });
      }
    },
    [navigate, sendFeedback],
  );

  /** Execute a modal command (Task 4.7) */
  const executeModal = useCallback(
    (cmd: UICommand) => {
      if (!cmd.modal) {
        sendFeedback({
          command_id: cmd.command_id,
          status: 'failed',
          action: 'modal',
          error: 'No modal type provided',
        });
        return;
      }
      try {
        if (cmd.modal === 'close') {
          setActiveModal(null);
        } else {
          setActiveModal(cmd.modal);
        }
        sendFeedback({
          command_id: cmd.command_id,
          status: 'success',
          action: 'modal',
          data: { modal: cmd.modal, contact_id: cmd.contact_id },
        });
      } catch (err) {
        sendFeedback({
          command_id: cmd.command_id,
          status: 'failed',
          action: 'modal',
          error: String(err),
        });
      }
    },
    [setActiveModal, sendFeedback],
  );

  /** Execute a tab command (Task 4.8) */
  const executeTab = useCallback(
    (cmd: UICommand) => {
      if (!cmd.tab) {
        sendFeedback({
          command_id: cmd.command_id,
          status: 'failed',
          action: 'tab',
          error: 'No tab provided',
        });
        return;
      }
      try {
        // If contact_id is provided, navigate to contact detail first
        if (cmd.contact_id) {
          const path = `/contacts/${cmd.contact_id}`;
          if (!location.pathname.includes(path)) {
            navigate(path);
          }
        }
        setActiveTab(cmd.tab);
        sendFeedback({
          command_id: cmd.command_id,
          status: 'success',
          action: 'tab',
          current_tab: cmd.tab,
          current_path: location.pathname,
        });
      } catch (err) {
        sendFeedback({
          command_id: cmd.command_id,
          status: 'failed',
          action: 'tab',
          error: String(err),
        });
      }
    },
    [navigate, location.pathname, setActiveTab, sendFeedback],
  );

  /** Execute a settings command (Task 4.9) */
  const executeSettings = useCallback(
    (cmd: UICommand) => {
      if (!cmd.section) {
        sendFeedback({
          command_id: cmd.command_id,
          status: 'failed',
          action: 'settings',
          error: 'No settings section provided',
        });
        return;
      }
      try {
        // Navigate to settings page
        const settingsPath = `/settings/${cmd.section}`;
        navigate(settingsPath);
        // If key/value provided, set pending settings change
        if (cmd.key) {
          setPendingSettings({
            section: cmd.section,
            key: cmd.key,
            value: cmd.value,
          });
        }
        sendFeedback({
          command_id: cmd.command_id,
          status: 'success',
          action: 'settings',
          current_path: settingsPath,
          data: { section: cmd.section, key: cmd.key, value: cmd.value },
        });
      } catch (err) {
        sendFeedback({
          command_id: cmd.command_id,
          status: 'failed',
          action: 'settings',
          error: String(err),
        });
      }
    },
    [navigate, setPendingSettings, sendFeedback],
  );

  /** Dispatch a command to the appropriate executor */
  const executeCommand = useCallback(
    (cmd: UICommand) => {
      setActiveCommand(cmd);
      addCommandToHistory(cmd);

      // Clear active state after a delay for visual indication
      const clearTimer = window.setTimeout(() => {
        clearPending();
      }, 5000);

      switch (cmd.action) {
        case 'navigate':
          executeNavigate(cmd);
          break;
        case 'filter':
          executeFilter(cmd);
          break;
        case 'open_contact':
          executeOpenContact(cmd);
          break;
        case 'modal':
          executeModal(cmd);
          break;
        case 'tab':
          executeTab(cmd);
          break;
        case 'settings':
          executeSettings(cmd);
          break;
        default:
          sendFeedback({
            command_id: cmd.command_id,
            status: 'failed',
            error: `Unknown command action: ${cmd.action}`,
          });
      }

      // Clear the timer reference
      return () => clearTimeout(clearTimer);
    },
    [
      setActiveCommand,
      addCommandToHistory,
      clearPending,
      executeNavigate,
      executeFilter,
      executeOpenContact,
      executeModal,
      executeTab,
      executeSettings,
      sendFeedback,
    ],
  );

  useEffect(() => {
    let reconnectAttempts = 0;
    const maxReconnectDelay = 30000;

    function connect() {
      const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
      const ws = new WebSocket(`${protocol}//${window.location.host}/api/v1/ai-ui-control/ws`);
      wsRef.current = ws;

      ws.onopen = () => {
        reconnectAttempts = 0;
        setConnected(true);
        console.log('AI UI Control WebSocket connected');
      };

      ws.onmessage = (event) => {
        try {
          const data = JSON.parse(event.data);
          // Commands from AI agents arrive as command objects
          if (data.command_id && data.action) {
            executeCommand(data as UICommand);
          }
        } catch (err) {
          console.error('AI UI Control WebSocket message parse error:', err);
        }
      };

      ws.onclose = () => {
        setConnected(false);
        console.log('AI UI Control WebSocket disconnected');
        const delay = Math.min(1000 * Math.pow(2, reconnectAttempts), maxReconnectDelay);
        reconnectAttempts++;
        reconnectTimeout.current = window.setTimeout(connect, delay);
      };

      ws.onerror = (error) => {
        console.error('AI UI Control WebSocket error:', error);
      };
    }

    connect();

    // Ping interval to keep connection alive
    const pingInterval = setInterval(() => {
      if (wsRef.current?.readyState === WebSocket.OPEN) {
        wsRef.current.send(JSON.stringify({ type: 'ping' }));
      }
    }, 30000);

    return () => {
      clearInterval(pingInterval);
      if (reconnectTimeout.current) clearTimeout(reconnectTimeout.current);
      wsRef.current?.close();
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return wsRef;
}
