import { useState, useEffect, useRef, useCallback } from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import type { User, DroneRegistration, SubProcessStat } from '../lib/api';
import { droneApi } from '../lib/api';
import { socketClient } from '../lib/socket';
import SubProcessTable from '../components/SubProcessTable';
import DroneMonitor from '../components/DroneMonitor';
import LogRenderer from '../components/LogRenderer';
import type { LogRendererEntry } from '../components/LogRenderer';

interface DroneManagerProps {
  user: User | null;
}

interface ToastState {
  message: string;
  type: 'success' | 'error';
}

let logIdCounter = 0;

export default function DroneManager({ user }: DroneManagerProps) {
  const navigate = useNavigate();
  const location = useLocation();
  const [allDrones, setAllDrones] = useState<DroneRegistration[]>([]);
  const [selectedDrone, setSelectedDrone] = useState<DroneRegistration | null>(null);
  const [loading, setLoading] = useState(true);
  const [terminating, setTerminating] = useState<string | null>(null);
  const [toast, setToast] = useState<ToastState | null>(null);

  // SubProcess state
  const [processStats, setProcessStats] = useState<SubProcessStat[]>([]);
  const [selectedPid, setSelectedPid] = useState<number | null>(null);

  // Live log state
  const [logEntries, setLogEntries] = useState<LogRendererEntry[]>([]);
  const [autoScroll, setAutoScroll] = useState(true);
  const logContainerRef = useRef<HTMLDivElement>(null);

  // Track cleanup
  const pollIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
  const subscribedDroneRef = useRef<string | null>(null);
  const droneChangeGeneration = useRef(0);

  useEffect(() => {
    if (!user) {
      navigate('/sign-in');
      return;
    }
    loadDrones();
  }, [user]);

  // Socket lifecycle — subscribe, poll, listen when selectedDrone changes
  useEffect(() => {
    const gen = ++droneChangeGeneration.current;

    // Cleanup previous subscription
    if (subscribedDroneRef.current) {
      socketClient.unsubscribeDrone(subscribedDroneRef.current);
      subscribedDroneRef.current = null;
    }
    if (pollIntervalRef.current) {
      clearInterval(pollIntervalRef.current);
      pollIntervalRef.current = null;
    }

    if (!selectedDrone || selectedDrone.status === 'offline') {
      setProcessStats([]);
      setLogEntries([]);
      return;
    }

    const regId = selectedDrone._id;
    subscribedDroneRef.current = regId;
    setProcessStats([]);
    setLogEntries([]);

    // Subscribe to live drone events
    socketClient.subscribeDrone(regId);

    // Listen for log events
    const handleLog = (data: { timestamp: string; level: string; component: string; message: string; metadata?: unknown }) => {
      if (droneChangeGeneration.current !== gen) return;
      logIdCounter++;
      setLogEntries((prev) => {
        const entry: LogRendererEntry = {
          id: `log-${logIdCounter}`,
          timestamp: new Date(data.timestamp),
          level: data.level,
          component: data.component,
          message: data.message,
          metadata: data.metadata,
        };
        const next = [...prev, entry];
        if (next.length > 200) {
          return next.slice(next.length - 200);
        }
        return next;
      });
    };

    socketClient.on('drone:log', handleLog);

    // Poll process stats every 1s
    const poll = async () => {
      if (droneChangeGeneration.current !== gen) return;
      const result = await socketClient.requestProcessStats(regId);
      if (result.success && result.processes && droneChangeGeneration.current === gen) {
        setProcessStats(result.processes as SubProcessStat[]);
      }
    };

    poll();
    pollIntervalRef.current = setInterval(poll, 1000);

    return () => {
      // Mark this effect cycle as stale so async callbacks are no-ops
      droneChangeGeneration.current++;
      clearInterval(pollIntervalRef.current!);
      pollIntervalRef.current = null;
      socketClient.off('drone:log', handleLog);
      socketClient.unsubscribeDrone(regId);
      subscribedDroneRef.current = null;
    };
  }, [selectedDrone]);

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

  const handleScroll = () => {
    if (logContainerRef.current) {
      const { scrollTop, scrollHeight, clientHeight } = logContainerRef.current;
      const isNearBottom = scrollHeight - scrollTop - clientHeight < 100;
      setAutoScroll(isNearBottom);
    }
  };

  const loadDrones = async () => {
    try {
      const data = await droneApi.getForManager();
      setAllDrones(data);

      // Auto-select from route state if provided
      const state = location.state as { droneId?: string } | null;
      if (state?.droneId) {
        const match = data.find((d) => d._id === state.droneId);
        if (match) {
          setSelectedDrone(match);
        }
        // Clear route state to avoid re-selecting on re-render
        window.history.replaceState({}, '');
      }
    } catch (err) {
      console.error('Failed to load drones', err);
      showToast('Failed to load drones', 'error');
    } finally {
      setLoading(false);
    }
  };

  const showToast = (message: string, type: 'success' | 'error') => {
    setToast({ message, type });
    setTimeout(() => setToast(null), 5000);
  };

  const handleSelectDrone = (drone: DroneRegistration) => {
    setSelectedDrone(drone);
    setSelectedPid(null);
  };

  const handleTerminate = async () => {
    if (!selectedDrone) return;

    if (selectedDrone.status === 'busy') {
      const confirmed = confirm('Are you sure you want to terminate the drone? Any work or operations currently in progress may be lost.');
      if (!confirmed) return;
    }

    setTerminating(selectedDrone._id);
    try {
      const result = await droneApi.terminate(selectedDrone._id);

      if (result.message) {
        showToast(result.message, result.success ? 'success' : 'error');
      } else {
        showToast('Drone terminated successfully', 'success');
      }

      await loadDrones();

      if (selectedDrone.status !== 'offline') {
        setSelectedDrone(null);
      }
    } catch (err) {
      console.error('Failed to terminate drone', err);
      showToast('Failed to terminate drone', 'error');
    } finally {
      setTerminating(null);
    }
  };

  const onlineDrones = allDrones.filter(d => d.status === 'available' || d.status === 'busy');
  const offlineDrones = allDrones.filter(d => d.status === 'offline' || d.status === 'starting');

  if (!user) {
    return (
      <div className="flex-1 flex items-center justify-center bg-bg-primary">
        <p className="text-text-muted">Please sign in to view drones.</p>
      </div>
    );
  }

  return (
    <div className="flex-1 flex bg-bg-primary overflow-hidden">
      {toast && (
        <div className={`fixed top-16 right-4 z-50 px-4 py-3 rounded border ${
          toast.type === 'success'
            ? 'bg-green-900/80 border-green-600 text-green-100'
            : 'bg-red-900/80 border-red-600 text-red-100'
        }`}>
          {toast.message}
        </div>
      )}

      <aside className="w-80 border-r border-border-subtle bg-bg-secondary flex flex-col overflow-hidden">
        <div className="p-3 border-b border-border-subtle flex-shrink-0">
          <h2 className="text-lg font-semibold text-text-primary">Drone Manager</h2>
        </div>

        <div className="flex flex-col min-h-0 flex-1" style={{ minHeight: 0 }}>
          <div className="p-2 border-b border-border-subtle flex-shrink-0 bg-bg-tertiary">
            <h3 className="text-xs font-semibold text-text-secondary uppercase tracking-wider">
              Online Drones ({onlineDrones.length})
            </h3>
          </div>
          <div className="flex-1 overflow-y-auto p-2 space-y-2 min-h-0">
            {loading ? (
              <p className="text-sm text-text-muted p-2">Loading...</p>
            ) : onlineDrones.length === 0 ? (
              <div className="text-text-muted text-sm p-2">
                No online drones.
              </div>
            ) : (
              onlineDrones.map((drone) => (
                <div
                  key={drone._id}
                  onClick={() => handleSelectDrone(drone)}
                  className={`p-3 border rounded cursor-pointer transition-colors ${
                    selectedDrone?._id === drone._id
                      ? 'border-brand bg-bg-elevated'
                      : 'border-border-default bg-bg-tertiary hover:bg-bg-elevated'
                  }`}
                >
                  <div className="flex items-center justify-between mb-1">
                    <div className="flex items-center gap-2">
                      <span
                        className={`w-2 h-2 rounded-full ${
                          drone.status === 'available'
                            ? 'bg-green-500'
                            : 'bg-yellow-500'
                        }`}
                      />
                      <span className="font-mono text-sm font-medium text-text-primary">
                        {drone.hostname}
                      </span>
                    </div>
                    <span className={`text-xs px-2 py-0.5 rounded ${
                      drone.status === 'available'
                        ? 'bg-green-900/50 text-green-400'
                        : 'bg-yellow-900/50 text-yellow-400'
                    }`}>
                      {drone.status}
                    </span>
                  </div>
                  <div className="text-xs text-text-muted truncate">
                    {drone.workspaceDir}
                  </div>
                </div>
              ))
            )}
          </div>
        </div>

        <div className="flex flex-col min-h-0 flex-1" style={{ minHeight: 0 }}>
          <div className="p-2 border-t border-border-subtle flex-shrink-0 bg-bg-tertiary">
            <h3 className="text-xs font-semibold text-text-secondary uppercase tracking-wider">
              Offline Drones ({offlineDrones.length})
            </h3>
          </div>
          <div className="flex-1 overflow-y-auto p-2 space-y-2 min-h-0">
            {loading ? (
              <p className="text-sm text-text-muted p-2">Loading...</p>
            ) : offlineDrones.length === 0 ? (
              <div className="text-text-muted text-sm p-2">
                No offline drones.
              </div>
            ) : (
              offlineDrones.map((drone) => (
                <div
                  key={drone._id}
                  onClick={() => handleSelectDrone(drone)}
                  className={`p-3 border rounded cursor-pointer transition-colors ${
                    selectedDrone?._id === drone._id
                      ? 'border-brand bg-bg-elevated'
                      : 'border-border-default bg-bg-tertiary hover:bg-bg-elevated'
                  }`}
                >
                  <div className="flex items-center justify-between mb-1">
                    <div className="flex items-center gap-2">
                      <span className="w-2 h-2 rounded-full bg-gray-500" />
                      <span className="font-mono text-sm font-medium text-text-primary">
                        {drone.hostname}
                      </span>
                    </div>
                    <span className="text-xs px-2 py-0.5 rounded bg-gray-900/50 text-gray-400">
                      {drone.status}
                    </span>
                  </div>
                  <div className="text-xs text-text-muted truncate">
                    {drone.workspaceDir}
                  </div>
                </div>
              ))
            )}
          </div>
        </div>
      </aside>

      <main className="flex-1 flex flex-col overflow-hidden bg-bg-primary">
        {selectedDrone ? (
          <>
            <div className="p-6 border-b border-border-subtle flex-shrink-0">
              <div className="max-w-3xl">
                <div className="flex items-center justify-between mb-4">
                  <h2 className="text-xl font-semibold text-text-primary">Drone Details</h2>
                  {selectedDrone.status !== 'offline' && (
                    <button
                      onClick={handleTerminate}
                      disabled={terminating === selectedDrone._id}
                      className="px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed text-sm font-medium"
                    >
                      {terminating === selectedDrone._id ? 'Terminating...' : 'Terminate'}
                    </button>
                  )}
                </div>

                <div className="grid grid-cols-2 gap-4">
                  <div className="p-4 bg-bg-secondary border border-border-default rounded">
                    <div className="text-sm text-text-muted mb-1">Hostname</div>
                    <div className="font-mono text-text-primary">{selectedDrone.hostname}</div>
                  </div>
                  <div className="p-4 bg-bg-secondary border border-border-default rounded">
                    <div className="text-sm text-text-muted mb-1">Status</div>
                    <div className="flex items-center gap-2">
                      <span
                        className={`w-2 h-2 rounded-full ${
                          selectedDrone.status === 'available'
                            ? 'bg-green-500'
                            : selectedDrone.status === 'busy'
                            ? 'bg-yellow-500'
                            : 'bg-gray-500'
                        }`}
                      />
                      <span className="text-text-primary capitalize">{selectedDrone.status}</span>
                    </div>
                  </div>
                  <div className="p-4 bg-bg-secondary border border-border-default rounded">
                    <div className="text-sm text-text-muted mb-1">Workspace</div>
                    <div className="font-mono text-text-primary text-sm truncate">
                      {selectedDrone.workspaceDir}
                    </div>
                  </div>
                  <div className="p-4 bg-bg-secondary border border-border-default rounded">
                    <div className="text-sm text-text-muted mb-1">Registered</div>
                    <div className="text-text-primary">
                      {new Date(selectedDrone.createdAt).toLocaleString()}
                    </div>
                  </div>
                </div>
              </div>
            </div>

            <div className="flex-1 overflow-y-auto p-6 min-h-0 space-y-4">
              <div className="max-w-3xl space-y-4">
                <SubProcessTable
                  processes={processStats}
                  onSelect={setSelectedPid}
                  selectedPid={selectedPid}
                />
                <DroneMonitor visible={!!selectedDrone && selectedDrone.status !== 'offline'} />
              </div>

              <div className="flex flex-col min-h-[300px] max-h-[400px] border-t border-border-subtle">
                <div className="p-2 bg-bg-secondary border-b border-border-subtle flex-shrink-0">
                  <h3 className="text-xs font-semibold text-text-secondary uppercase tracking-wider">
                    Drone Log {selectedDrone.status !== 'offline' && '(Live)'}
                  </h3>
                </div>
                <div
                  ref={logContainerRef}
                  onScroll={handleScroll}
                  className="flex-1 overflow-y-auto"
                >
                  <LogRenderer logs={logEntries} containerClassName="min-h-full" />
                </div>
              </div>
            </div>
          </>
        ) : (
          <div className="flex-1 flex items-center justify-center text-text-muted">
            <div className="text-center">
              <p className="mb-2">Select a drone to view details</p>
              <p className="text-sm">Choose from the online or offline drone lists</p>
            </div>
          </div>
        )}
      </main>
    </div>
  );
}
