import { useState, useEffect, useRef, useCallback } from "react";
import { Button } from "./ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "./ui/card";
import { Badge } from "./ui/badge";
import { Alert, AlertDescription } from "./ui/alert";
import {
  teleoperate,
  type TeleoperationProcess,
  type TeleoperationState,
  type TeleoperateConfig,
} from "@lerobot/web";
import { getUnifiedRobotData } from "../lib/unified-storage";
import type { RobotConnection } from "@lerobot/web";
import { SO100_KEYBOARD_CONTROLS } from "@lerobot/web";

interface TeleoperationPanelProps {
  robot: RobotConnection;
  onClose: () => void;
}

export function TeleoperationPanel({
  robot,
  onClose,
}: TeleoperationPanelProps) {
  const [teleoperationState, setTeleoperationState] =
    useState<TeleoperationState>({
      isActive: false,
      motorConfigs: [],
      lastUpdate: 0,
      keyStates: {},
    });
  const [error, setError] = useState<string | null>(null);
  const [, setIsInitialized] = useState(false);

  // Separate refs for keyboard and direct teleoperators
  const keyboardProcessRef = useRef<TeleoperationProcess | null>(null);
  const directProcessRef = useRef<TeleoperationProcess | null>(null);

  // Initialize both teleoperation processes
  useEffect(() => {
    const initializeTeleoperation = async () => {
      if (!robot || !robot.robotType) {
        setError("No robot configuration available");
        return;
      }

      try {
        // Load calibration data from demo storage (app concern)
        let calibrationData;
        if (robot.serialNumber) {
          const data = getUnifiedRobotData(robot.serialNumber);
          calibrationData = data?.calibration;
          if (calibrationData) {
            console.log("✅ Loaded calibration data for", robot.serialNumber);
          }
        }

        // Create keyboard teleoperation process
        const keyboardConfig: TeleoperateConfig = {
          robot: robot,
          teleop: {
            type: "keyboard",
          },
          calibrationData,
          onStateUpdate: (state: TeleoperationState) => {
            setTeleoperationState(state);
          },
        };
        const keyboardProcess = await teleoperate(keyboardConfig);

        // Create direct teleoperation process
        const directConfig: TeleoperateConfig = {
          robot: robot,
          teleop: {
            type: "direct",
          },
          calibrationData,
        };
        const directProcess = await teleoperate(directConfig);

        keyboardProcessRef.current = keyboardProcess;
        directProcessRef.current = directProcess;
        setTeleoperationState(keyboardProcess.getState());
        setIsInitialized(true);
        setError(null);

        console.log("✅ Initialized both keyboard and direct teleoperators");
      } catch (error) {
        const errorMessage =
          error instanceof Error
            ? error.message
            : "Failed to initialize teleoperation";
        setError(errorMessage);
        console.error("❌ Failed to initialize teleoperation:", error);
      }
    };

    initializeTeleoperation();

    return () => {
      // Cleanup on unmount
      const cleanup = async () => {
        try {
          if (keyboardProcessRef.current) {
            await keyboardProcessRef.current.disconnect();
            keyboardProcessRef.current = null;
          }
          if (directProcessRef.current) {
            await directProcessRef.current.disconnect();
            directProcessRef.current = null;
          }
          console.log("🧹 Teleoperation cleanup completed");
        } catch (error) {
          console.warn("Error during teleoperation cleanup:", error);
        }
      };
      cleanup();
    };
  }, [robot]);

  // Keyboard event handlers
  const handleKeyDown = useCallback(
    (event: KeyboardEvent) => {
      if (!teleoperationState.isActive || !keyboardProcessRef.current) return;

      const key = event.key;
      event.preventDefault();
      keyboardProcessRef.current.updateKeyState(key, true);
    },
    [teleoperationState.isActive]
  );

  const handleKeyUp = useCallback(
    (event: KeyboardEvent) => {
      if (!teleoperationState.isActive || !keyboardProcessRef.current) return;

      const key = event.key;
      event.preventDefault();
      keyboardProcessRef.current.updateKeyState(key, false);
    },
    [teleoperationState.isActive]
  );

  // Register keyboard events
  useEffect(() => {
    if (teleoperationState.isActive) {
      window.addEventListener("keydown", handleKeyDown);
      window.addEventListener("keyup", handleKeyUp);

      return () => {
        window.removeEventListener("keydown", handleKeyDown);
        window.removeEventListener("keyup", handleKeyUp);
      };
    }
  }, [teleoperationState.isActive, handleKeyDown, handleKeyUp]);

  const handleStart = () => {
    if (!keyboardProcessRef.current || !directProcessRef.current) {
      setError("Teleoperation not initialized");
      return;
    }

    try {
      keyboardProcessRef.current.start();
      directProcessRef.current.start();
      console.log("🎮 Both keyboard and direct teleoperation started");
    } catch (error) {
      const errorMessage =
        error instanceof Error
          ? error.message
          : "Failed to start teleoperation";
      setError(errorMessage);
    }
  };

  const handleStop = async () => {
    try {
      if (keyboardProcessRef.current) {
        keyboardProcessRef.current.stop();
      }
      if (directProcessRef.current) {
        directProcessRef.current.stop();
      }
      console.log("🛑 Both keyboard and direct teleoperation stopped");
    } catch (error) {
      console.warn("Error during teleoperation stop:", error);
    }
  };

  const handleClose = async () => {
    try {
      if (keyboardProcessRef.current) {
        keyboardProcessRef.current.stop();
        await keyboardProcessRef.current.disconnect();
      }
      if (directProcessRef.current) {
        directProcessRef.current.stop();
        await directProcessRef.current.disconnect();
      }
      console.log("🔌 Properly disconnected from robot");
    } catch (error) {
      console.warn("Error during teleoperation cleanup:", error);
    }
    onClose();
  };

  const simulateKeyPress = (key: string) => {
    if (!keyboardProcessRef.current) return;
    keyboardProcessRef.current.updateKeyState(key, true);
  };

  const simulateKeyRelease = (key: string) => {
    if (!keyboardProcessRef.current) return;
    keyboardProcessRef.current.updateKeyState(key, false);
  };

  // Unified motor control: Both sliders AND keyboard use the same teleoperator
  // This ensures the UI always shows the correct motor positions
  const moveMotorToPosition = async (motorIndex: number, position: number) => {
    if (!keyboardProcessRef.current) return;

    try {
      const motorName = teleoperationState.motorConfigs[motorIndex]?.name;
      if (motorName) {
        const keyboardTeleoperator = keyboardProcessRef.current
          .teleoperator as any;
        await keyboardTeleoperator.moveMotor(motorName, position);
      }
    } catch (error) {
      console.warn(
        `Failed to move motor ${motorIndex + 1} to position ${position}:`,
        error
      );
    }
  };

  const isConnected = robot?.isConnected || false;
  const isActive = teleoperationState.isActive;
  const motorConfigs = teleoperationState.motorConfigs;
  const keyStates = teleoperationState.keyStates;

  // Virtual keyboard component
  const VirtualKeyboard = () => {
    const isKeyPressed = (key: string) => {
      return keyStates?.[key]?.pressed || false;
    };

    const KeyButton = ({
      keyCode,
      children,
      className = "",
      size = "default" as "default" | "sm" | "lg" | "icon",
    }: {
      keyCode: string;
      children: React.ReactNode;
      className?: string;
      size?: "default" | "sm" | "lg" | "icon";
    }) => {
      const control =
        SO100_KEYBOARD_CONTROLS[
          keyCode as keyof typeof SO100_KEYBOARD_CONTROLS
        ];
      const pressed = isKeyPressed(keyCode);

      const handleMouseDown = (e: React.MouseEvent) => {
        e.preventDefault();
        if (!isActive) return;
        simulateKeyPress(keyCode);
      };

      const handleMouseUp = (e: React.MouseEvent) => {
        e.preventDefault();
        if (!isActive) return;
        simulateKeyRelease(keyCode);
      };

      return (
        <Button
          variant={pressed ? "default" : "outline"}
          size={size}
          className={`
            ${className}
            ${
              pressed
                ? "bg-blue-600 text-white shadow-inner"
                : "hover:bg-gray-100"
            }
            transition-all duration-75 font-mono text-xs
            ${!isActive ? "opacity-50 cursor-not-allowed" : ""}
          `}
          disabled={!isActive}
          onMouseDown={handleMouseDown}
          onMouseUp={handleMouseUp}
          onMouseLeave={handleMouseUp}
          title={control?.description || keyCode}
        >
          {children}
        </Button>
      );
    };

    return (
      <div className="space-y-4">
        {/* Arrow Keys */}
        <div className="text-center">
          <h4 className="text-xs font-semibold mb-2 text-gray-600">Shoulder</h4>
          <div className="flex flex-col items-center gap-1">
            <KeyButton keyCode="ArrowUp" size="sm">
              ↑
            </KeyButton>
            <div className="flex gap-1">
              <KeyButton keyCode="ArrowLeft" size="sm">
                ←
              </KeyButton>
              <KeyButton keyCode="ArrowDown" size="sm">
                ↓
              </KeyButton>
              <KeyButton keyCode="ArrowRight" size="sm">
                →
              </KeyButton>
            </div>
          </div>
        </div>

        {/* WASD Keys */}
        <div className="text-center">
          <h4 className="text-xs font-semibold mb-2 text-gray-600">
            Elbow/Wrist
          </h4>
          <div className="flex flex-col items-center gap-1">
            <KeyButton keyCode="w" size="sm">
              W
            </KeyButton>
            <div className="flex gap-1">
              <KeyButton keyCode="a" size="sm">
                A
              </KeyButton>
              <KeyButton keyCode="s" size="sm">
                S
              </KeyButton>
              <KeyButton keyCode="d" size="sm">
                D
              </KeyButton>
            </div>
          </div>
        </div>

        {/* Q/E and Gripper */}
        <div className="flex justify-center gap-2">
          <div className="text-center">
            <h4 className="text-xs font-semibold mb-2 text-gray-600">Roll</h4>
            <div className="flex gap-1">
              <KeyButton keyCode="q" size="sm">
                Q
              </KeyButton>
              <KeyButton keyCode="e" size="sm">
                E
              </KeyButton>
            </div>
          </div>
          <div className="text-center">
            <h4 className="text-xs font-semibold mb-2 text-gray-600">
              Gripper
            </h4>
            <div className="flex gap-1">
              <KeyButton keyCode="o" size="sm">
                O
              </KeyButton>
              <KeyButton keyCode="c" size="sm">
                C
              </KeyButton>
            </div>
          </div>
        </div>

        {/* Emergency Stop */}
        <div className="text-center border-t pt-2">
          <KeyButton
            keyCode="Escape"
            className="bg-red-100 border-red-300 hover:bg-red-200 text-red-800 text-xs"
          >
            ESC
          </KeyButton>
        </div>
      </div>
    );
  };

  return (
    <div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100">
      <div className="container mx-auto px-6 py-8">
        {/* Header */}
        <div className="flex justify-between items-center mb-6">
          <div>
            <h1 className="text-3xl font-bold text-gray-900">
              🎮 Robot Teleoperation
            </h1>
            <p className="text-gray-600">
              {robot.robotId || robot.name} - {robot.serialNumber}
            </p>
          </div>
          <Button variant="outline" onClick={handleClose}>
            ← Back to Dashboard
          </Button>
        </div>

        {/* Error Alert */}
        {error && (
          <Alert variant="destructive" className="mb-6">
            <AlertDescription>{error}</AlertDescription>
          </Alert>
        )}

        <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
          {/* Status Panel */}
          <Card>
            <CardHeader>
              <CardTitle className="flex items-center gap-2">
                Status
                <Badge variant={isConnected ? "default" : "destructive"}>
                  {isConnected ? "Connected" : "Disconnected"}
                </Badge>
              </CardTitle>
            </CardHeader>
            <CardContent className="space-y-4">
              <div className="flex items-center justify-between">
                <span className="text-sm text-gray-600">Teleoperation</span>
                <Badge variant={isActive ? "default" : "secondary"}>
                  {isActive ? "Active" : "Stopped"}
                </Badge>
              </div>

              <div className="flex items-center justify-between">
                <span className="text-sm text-gray-600">Active Keys</span>
                <Badge variant="outline">
                  {
                    Object.values(keyStates || {}).filter(
                      (state) => state.pressed
                    ).length
                  }
                </Badge>
              </div>

              <div className="space-y-2">
                {isActive ? (
                  <Button
                    onClick={handleStop}
                    variant="destructive"
                    className="w-full"
                  >
                    ⏹️ Stop Teleoperation
                  </Button>
                ) : (
                  <Button
                    onClick={handleStart}
                    disabled={!isConnected}
                    className="w-full"
                  >
                    ▶️ Start Teleoperation
                  </Button>
                )}
              </div>
            </CardContent>
          </Card>

          {/* Virtual Keyboard */}
          <Card>
            <CardHeader>
              <CardTitle>Virtual Keyboard</CardTitle>
            </CardHeader>
            <CardContent>
              <VirtualKeyboard />
            </CardContent>
          </Card>

          {/* Motor Status */}
          <Card>
            <CardHeader>
              <CardTitle>Motor Positions</CardTitle>
            </CardHeader>
            <CardContent className="space-y-3">
              {motorConfigs.map((motor, index) => {
                return (
                  <div key={motor.name} className="space-y-1">
                    <div className="flex justify-between items-center">
                      <span className="text-sm font-medium">
                        {motor.name.replace("_", " ")}
                      </span>
                      <span className="text-xs text-gray-500">
                        {motor.currentPosition}
                      </span>
                    </div>
                    <input
                      type="range"
                      min={motor.minPosition}
                      max={motor.maxPosition}
                      value={motor.currentPosition}
                      disabled={!isActive}
                      className={`w-full h-2 rounded-lg appearance-none cursor-pointer bg-gray-200 slider-thumb ${
                        !isActive ? "opacity-50 cursor-not-allowed" : ""
                      }`}
                      style={{
                        background: isActive
                          ? `linear-gradient(to right, #3b82f6 0%, #3b82f6 ${
                              ((motor.currentPosition - motor.minPosition) /
                                (motor.maxPosition - motor.minPosition)) *
                              100
                            }%, #e5e7eb ${
                              ((motor.currentPosition - motor.minPosition) /
                                (motor.maxPosition - motor.minPosition)) *
                              100
                            }%, #e5e7eb 100%)`
                          : "#e5e7eb",
                      }}
                      onChange={async (e) => {
                        if (!isActive) return;
                        const newPosition = parseInt(e.target.value);
                        try {
                          await moveMotorToPosition(index, newPosition);
                        } catch (error) {
                          console.warn(
                            "Failed to move motor via slider:",
                            error
                          );
                        }
                      }}
                    />
                    <div className="flex justify-between text-xs text-gray-400">
                      <span>{motor.minPosition}</span>
                      <span>{motor.maxPosition}</span>
                    </div>
                  </div>
                );
              })}
            </CardContent>
          </Card>
        </div>

        {/* Help Card */}
        <Card className="mt-6">
          <CardHeader>
            <CardTitle>Control Instructions</CardTitle>
          </CardHeader>
          <CardContent>
            <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 text-sm">
              <div>
                <h4 className="font-semibold mb-2">Arrow Keys</h4>
                <ul className="space-y-1 text-gray-600">
                  <li>↑ ↓ Shoulder lift</li>
                  <li>← → Shoulder pan</li>
                </ul>
              </div>
              <div>
                <h4 className="font-semibold mb-2">WASD Keys</h4>
                <ul className="space-y-1 text-gray-600">
                  <li>W S Elbow flex</li>
                  <li>A D Wrist flex</li>
                </ul>
              </div>
              <div>
                <h4 className="font-semibold mb-2">Other Keys</h4>
                <ul className="space-y-1 text-gray-600">
                  <li>Q E Wrist roll</li>
                  <li>O Open gripper</li>
                  <li>C Close gripper</li>
                </ul>
              </div>
              <div>
                <h4 className="font-semibold mb-2 text-red-700">Emergency</h4>
                <ul className="space-y-1 text-red-600">
                  <li>ESC Emergency stop</li>
                </ul>
              </div>
            </div>
            <div className="mt-4 p-3 bg-blue-50 rounded-lg">
              <p className="text-sm text-blue-800">
                💡 <strong>Pro tip:</strong> Use your physical keyboard for
                faster control, or click the virtual keys below. Hold keys down
                for continuous movement.
              </p>
            </div>
          </CardContent>
        </Card>
      </div>
    </div>
  );
}
