import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { X, Play, Square, Trash2, RefreshCw, ArrowDown, ArrowUp, Search } from 'lucide-react';
import { api, type MQTTLogEntry } from '../api/client';
import { Button } from './Button';
import { useState, useEffect, useRef, useMemo } from 'react';

interface MQTTDebugModalProps {
  printerId: number;
  printerName: string;
  onClose: () => void;
}

export function MQTTDebugModal({ printerId, printerName, onClose }: MQTTDebugModalProps) {
  const queryClient = useQueryClient();
  const [autoScroll, setAutoScroll] = useState(true);
  const [expandedLogs, setExpandedLogs] = useState<Set<number>>(new Set());
  const [searchQuery, setSearchQuery] = useState('');
  const [directionFilter, setDirectionFilter] = useState<'all' | 'in' | 'out'>('all');
  const logContainerRef = useRef<HTMLDivElement>(null);

  const { data, isLoading, refetch } = useQuery({
    queryKey: ['mqtt-logs', printerId],
    queryFn: () => api.getMQTTLogs(printerId),
    refetchInterval: 1000, // Poll every second when logging is enabled
  });

  const enableMutation = useMutation({
    mutationFn: () => api.enableMQTTLogging(printerId),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['mqtt-logs', printerId] });
    },
  });

  const disableMutation = useMutation({
    mutationFn: () => api.disableMQTTLogging(printerId),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['mqtt-logs', printerId] });
    },
  });

  const clearMutation = useMutation({
    mutationFn: () => api.clearMQTTLogs(printerId),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['mqtt-logs', printerId] });
    },
  });

  // Close on Escape key
  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.key === 'Escape') onClose();
    };
    window.addEventListener('keydown', handleKeyDown);
    return () => window.removeEventListener('keydown', handleKeyDown);
  }, [onClose]);

  // Auto-scroll to bottom when new logs arrive
  useEffect(() => {
    if (autoScroll && logContainerRef.current) {
      logContainerRef.current.scrollTop = logContainerRef.current.scrollHeight;
    }
  }, [data?.logs, autoScroll]);

  const toggleExpand = (index: number) => {
    setExpandedLogs((prev) => {
      const newSet = new Set(prev);
      if (newSet.has(index)) {
        newSet.delete(index);
      } else {
        newSet.add(index);
      }
      return newSet;
    });
  };

  const formatTimestamp = (timestamp: string) => {
    const date = new Date(timestamp);
    return date.toLocaleTimeString('en-US', { hour12: false, fractionalSecondDigits: 3 });
  };

  const formatPayload = (payload: unknown, expanded: boolean): string => {
    if (payload === undefined || payload === null) {
      return '<empty>';
    }
    // If payload is already a string, parse it first to format nicely
    const obj = typeof payload === 'string' ? JSON.parse(payload) : payload;
    const json = JSON.stringify(obj, null, expanded ? 2 : 0);
    if (!expanded && json.length > 100) {
      return json.substring(0, 100) + '...';
    }
    return json;
  };

  const loggingEnabled = data?.logging_enabled ?? false;
  const logs = data?.logs ?? [];

  // Filter logs based on search query and direction filter
  const filteredLogs = useMemo(() => {
    return logs.filter((log) => {
      // Direction filter
      if (directionFilter !== 'all' && log.direction !== directionFilter) {
        return false;
      }
      // Search filter
      if (searchQuery.trim()) {
        const query = searchQuery.toLowerCase();
        const topicMatch = log.topic.toLowerCase().includes(query);
        const payloadStr = JSON.stringify(log.payload).toLowerCase();
        const payloadMatch = payloadStr.includes(query);
        return topicMatch || payloadMatch;
      }
      return true;
    });
  }, [logs, searchQuery, directionFilter]);

  return (
    <div className="fixed inset-0 bg-black/70 flex items-center justify-center z-50 p-4">
      <div className="bg-bambu-dark-secondary rounded-lg max-w-4xl w-full max-h-[85vh] flex flex-col">
        {/* Header */}
        <div className="flex items-center justify-between p-4 border-b border-bambu-dark-tertiary">
          <div>
            <h2 className="text-lg font-semibold text-white">MQTT Debug Log</h2>
            <p className="text-sm text-bambu-gray">{printerName}</p>
          </div>
          <button
            onClick={onClose}
            className="text-bambu-gray hover:text-white transition-colors"
          >
            <X className="w-5 h-5" />
          </button>
        </div>

        {/* Controls */}
        <div className="flex flex-col gap-2 p-4 border-b border-bambu-dark-tertiary">
          <div className="flex items-center gap-2">
            {loggingEnabled ? (
              <Button
                size="sm"
                variant="secondary"
                onClick={() => disableMutation.mutate()}
                disabled={disableMutation.isPending}
              >
                <Square className="w-4 h-4" />
                Stop
              </Button>
            ) : (
              <Button
                size="sm"
                onClick={() => enableMutation.mutate()}
                disabled={enableMutation.isPending}
              >
                <Play className="w-4 h-4" />
                Start Logging
              </Button>
            )}
            <Button
              size="sm"
              variant="secondary"
              onClick={() => clearMutation.mutate()}
              disabled={clearMutation.isPending || logs.length === 0}
            >
              <Trash2 className="w-4 h-4" />
              Clear
            </Button>
            <Button
              size="sm"
              variant="secondary"
              onClick={() => refetch()}
              disabled={isLoading}
            >
              <RefreshCw className={`w-4 h-4 ${isLoading ? 'animate-spin' : ''}`} />
            </Button>
            <div className="flex-1" />
            <label className="flex items-center gap-2 text-sm text-bambu-gray cursor-pointer">
              <input
                type="checkbox"
                checked={autoScroll}
                onChange={(e) => setAutoScroll(e.target.checked)}
                className="rounded border-bambu-dark-tertiary"
              />
              Auto-scroll
            </label>
            <span className="text-sm text-bambu-gray">
              {filteredLogs.length}/{logs.length}
            </span>
          </div>

          {/* Search and Filter Row */}
          <div className="flex items-center gap-2">
            <div className="relative flex-1">
              <Search className="absolute left-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-bambu-gray" />
              <input
                type="text"
                placeholder="Search topic or payload..."
                value={searchQuery}
                onChange={(e) => setSearchQuery(e.target.value)}
                className="w-full pl-8 pr-3 py-1.5 text-sm bg-bambu-dark border border-bambu-dark-tertiary rounded text-white placeholder-bambu-gray focus:border-bambu-green focus:outline-none"
              />
              {searchQuery && (
                <button
                  onClick={() => setSearchQuery('')}
                  className="absolute right-2 top-1/2 -translate-y-1/2 text-bambu-gray hover:text-white"
                >
                  <X className="w-4 h-4" />
                </button>
              )}
            </div>
            <div className="flex items-center gap-1 bg-bambu-dark rounded border border-bambu-dark-tertiary">
              <button
                onClick={() => setDirectionFilter('all')}
                className={`px-2 py-1.5 text-xs rounded-l transition-colors ${
                  directionFilter === 'all'
                    ? 'bg-bambu-green text-white'
                    : 'text-bambu-gray hover:text-white'
                }`}
              >
                All
              </button>
              <button
                onClick={() => setDirectionFilter('in')}
                className={`px-2 py-1.5 text-xs transition-colors flex items-center gap-1 ${
                  directionFilter === 'in'
                    ? 'bg-blue-500 text-white'
                    : 'text-bambu-gray hover:text-white'
                }`}
              >
                <ArrowDown className="w-3 h-3" />
                In
              </button>
              <button
                onClick={() => setDirectionFilter('out')}
                className={`px-2 py-1.5 text-xs rounded-r transition-colors flex items-center gap-1 ${
                  directionFilter === 'out'
                    ? 'bg-green-500 text-white'
                    : 'text-bambu-gray hover:text-white'
                }`}
              >
                <ArrowUp className="w-3 h-3" />
                Out
              </button>
            </div>
          </div>
        </div>

        {/* Log Content */}
        <div
          ref={logContainerRef}
          className="flex-1 overflow-auto p-4 font-mono text-xs bg-black min-h-[400px]"
        >
          {logs.length === 0 ? (
            <div className="flex flex-col items-center justify-center h-full text-bambu-gray">
              <p className="mb-2">No messages logged yet</p>
              {!loggingEnabled && (
                <p className="text-sm">Click "Start Logging" to begin capturing MQTT messages</p>
              )}
            </div>
          ) : filteredLogs.length === 0 ? (
            <div className="flex flex-col items-center justify-center h-full text-bambu-gray">
              <p className="mb-2">No messages match your filter</p>
              <p className="text-sm">Try adjusting your search or filter criteria</p>
            </div>
          ) : (
            <div className="space-y-1">
              {filteredLogs.map((log: MQTTLogEntry, index: number) => {
                const isExpanded = expandedLogs.has(index);
                const isIncoming = log.direction === 'in';

                return (
                  <div
                    key={index}
                    className={`p-2 rounded cursor-pointer hover:bg-bambu-dark-secondary transition-colors ${
                      isExpanded ? 'bg-bambu-dark-secondary' : ''
                    }`}
                    onClick={() => toggleExpand(index)}
                  >
                    <div className="flex items-start gap-2">
                      <span className="text-bambu-gray shrink-0">
                        {formatTimestamp(log.timestamp)}
                      </span>
                      <span
                        className={`shrink-0 ${
                          isIncoming ? 'text-blue-400' : 'text-green-400'
                        }`}
                        title={isIncoming ? 'Incoming' : 'Outgoing'}
                      >
                        {isIncoming ? (
                          <ArrowDown className="w-3 h-3" />
                        ) : (
                          <ArrowUp className="w-3 h-3" />
                        )}
                      </span>
                      <span className="text-purple-400 shrink-0">{log.topic}</span>
                    </div>
                    {isExpanded ? (
                      <pre className="mt-2 p-3 bg-gray-900 border border-gray-700 rounded text-green-400 overflow-x-auto whitespace-pre-wrap break-all max-h-96 overflow-y-auto text-xs">
                        {formatPayload(log.payload, true)}
                      </pre>
                    ) : (
                      <pre className="mt-1 text-white/80 truncate">
                        {formatPayload(log.payload, false)}
                      </pre>
                    )}
                  </div>
                );
              })}
            </div>
          )}
        </div>

        {/* Footer */}
        <div className="flex items-center justify-between p-4 border-t border-bambu-dark-tertiary">
          <div className="text-sm text-bambu-gray">
            {loggingEnabled ? (
              <span className="flex items-center gap-2">
                <span className="w-2 h-2 bg-green-500 rounded-full animate-pulse" />
                Logging active - messages will auto-refresh
              </span>
            ) : (
              <span>Logging stopped</span>
            )}
          </div>
          <Button variant="secondary" onClick={onClose}>
            Close
          </Button>
        </div>
      </div>
    </div>
  );
}
