import React, { useState, useEffect } from "react";
import { Button } from "./ui/button";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "./ui/card";
import { Alert, AlertDescription } from "./ui/alert";
import { Badge } from "./ui/badge";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "./ui/dialog";
import { isWebSerialSupported } from "../../lerobot/web/calibrate";
import type { ConnectedRobot } from "../types";

interface PortManagerProps {
  connectedRobots: ConnectedRobot[];
  onConnectedRobotsChange: (robots: ConnectedRobot[]) => void;
  onCalibrate?: (
    port: SerialPort,
    robotType: "so100_follower" | "so100_leader",
    robotId: string
  ) => void;
  onTeleoperate?: (robot: ConnectedRobot) => void;
}

export function PortManager({
  connectedRobots,
  onConnectedRobotsChange,
  onCalibrate,
  onTeleoperate,
}: PortManagerProps) {
  const [isConnecting, setIsConnecting] = useState(false);
  const [isFindingPorts, setIsFindingPorts] = useState(false);
  const [findPortsLog, setFindPortsLog] = useState<string[]>([]);
  const [error, setError] = useState<string | null>(null);
  const [confirmDeleteDialog, setConfirmDeleteDialog] = useState<{
    open: boolean;
    robotIndex: number;
    robotName: string;
    serialNumber: string;
  }>({
    open: false,
    robotIndex: -1,
    robotName: "",
    serialNumber: "",
  });
  // Load saved port data from localStorage on mount
  useEffect(() => {
    loadSavedPorts();
  }, []);

  // Note: Robot data is now automatically saved to unified storage when robot config is updated

  const loadSavedPorts = async () => {
    try {
      const existingPorts = await navigator.serial.getPorts();
      const restoredPorts: ConnectedRobot[] = [];

      for (const port of existingPorts) {
        // Get USB device metadata to determine serial number
        let serialNumber = null;
        let usbMetadata = null;

        try {
          // Get all USB devices and try to match with this serial port
          const usbDevices = await navigator.usb.getDevices();
          const portInfo = port.getInfo();

          // Try to find matching USB device by vendor/product ID
          const matchingDevice = usbDevices.find(
            (device) =>
              device.vendorId === portInfo.usbVendorId &&
              device.productId === portInfo.usbProductId
          );

          if (matchingDevice) {
            serialNumber =
              matchingDevice.serialNumber ||
              `${matchingDevice.vendorId}-${
                matchingDevice.productId
              }-${Date.now()}`;
            usbMetadata = {
              vendorId: `0x${matchingDevice.vendorId
                .toString(16)
                .padStart(4, "0")}`,
              productId: `0x${matchingDevice.productId
                .toString(16)
                .padStart(4, "0")}`,
              serialNumber: matchingDevice.serialNumber || "Generated ID",
              manufacturerName: matchingDevice.manufacturerName || "Unknown",
              productName: matchingDevice.productName || "Unknown",
              usbVersionMajor: matchingDevice.usbVersionMajor,
              usbVersionMinor: matchingDevice.usbVersionMinor,
              deviceClass: matchingDevice.deviceClass,
              deviceSubclass: matchingDevice.deviceSubclass,
              deviceProtocol: matchingDevice.deviceProtocol,
            };
            console.log("✅ Restored USB metadata for port:", serialNumber);
          }
        } catch (usbError) {
          console.log("⚠️ Could not restore USB metadata:", usbError);
          // Generate fallback if no USB metadata available
          serialNumber = `fallback-${Date.now()}-${Math.random()
            .toString(36)
            .substr(2, 9)}`;
        }

        // Load robot configuration from unified storage
        let robotType: "so100_follower" | "so100_leader" | undefined;
        let robotId: string | undefined;
        let shouldAutoConnect = false;

        if (serialNumber) {
          try {
            const { getUnifiedRobotData } = await import(
              "../lib/unified-storage"
            );
            const unifiedData = getUnifiedRobotData(serialNumber);
            if (unifiedData?.device_info) {
              robotType = unifiedData.device_info.robotType;
              robotId = unifiedData.device_info.robotId;
              shouldAutoConnect = true;
              console.log(
                `📋 Loaded robot config from unified storage: ${robotType} (${robotId})`
              );
            }
          } catch (error) {
            console.warn("Failed to load unified robot data:", error);
          }
        }

        // Auto-connect to configured robots
        let isConnected = false;
        try {
          // Check if already open
          if (port.readable !== null && port.writable !== null) {
            isConnected = true;
            console.log("Port already open, reusing connection");
          } else if (shouldAutoConnect && robotType && robotId) {
            // Auto-open robots that have saved configuration
            console.log(
              `Auto-connecting to saved robot: ${robotType} (${robotId})`
            );
            await port.open({ baudRate: 1000000 });
            isConnected = true;

            // Register with singleton connection manager
            try {
              const { getRobotConnectionManager } = await import(
                "../../lerobot/web/robot-connection"
              );
              const connectionManager = getRobotConnectionManager();
              await connectionManager.connect(
                port,
                robotType,
                robotId,
                serialNumber!
              );
            } catch (error) {
              console.warn(
                "Failed to register with connection manager:",
                error
              );
            }
          } else {
            console.log(
              "Port found but no saved robot configuration, skipping auto-connect"
            );
            isConnected = false;
          }
        } catch (error) {
          console.log("Could not auto-connect to robot:", error);
          isConnected = false;
        }

        restoredPorts.push({
          port,
          name: getPortDisplayName(port),
          isConnected,
          robotType,
          robotId,
          serialNumber: serialNumber!,
          usbMetadata: usbMetadata || undefined,
        });
      }

      onConnectedRobotsChange(restoredPorts);
    } catch (error) {
      console.error("Failed to load saved ports:", error);
    }
  };

  const getPortDisplayName = (port: SerialPort): string => {
    try {
      const info = port.getInfo();
      if (info.usbVendorId && info.usbProductId) {
        return `USB Port (${info.usbVendorId}:${info.usbProductId})`;
      }
      if (info.usbVendorId) {
        return `Serial Port (VID:${info.usbVendorId
          .toString(16)
          .toUpperCase()})`;
      }
    } catch (error) {
      // getInfo() might not be available
    }
    return `Serial Port ${Date.now()}`;
  };

  const handleConnect = async () => {
    if (!isWebSerialSupported()) {
      setError("Web Serial API is not supported in this browser");
      return;
    }

    try {
      setIsConnecting(true);
      setError(null);

      // Step 1: Request Web Serial port
      console.log("Step 1: Requesting Web Serial port...");
      const port = await navigator.serial.requestPort();
      await port.open({ baudRate: 1000000 });

      // Step 2: Request WebUSB device for metadata
      console.log(
        "Step 2: Requesting WebUSB device for unique identification..."
      );
      let serialNumber = null;
      let usbMetadata = null;

      try {
        // Request USB device access for metadata
        const usbDevice = await navigator.usb.requestDevice({
          filters: [
            { vendorId: 0x0403 }, // FTDI
            { vendorId: 0x067b }, // Prolific
            { vendorId: 0x10c4 }, // Silicon Labs
            { vendorId: 0x1a86 }, // QinHeng Electronics (CH340)
            { vendorId: 0x239a }, // Adafruit
            { vendorId: 0x2341 }, // Arduino
            { vendorId: 0x2e8a }, // Raspberry Pi Foundation
            { vendorId: 0x1b4f }, // SparkFun
          ],
        });

        if (usbDevice) {
          serialNumber =
            usbDevice.serialNumber ||
            `${usbDevice.vendorId}-${usbDevice.productId}-${Date.now()}`;
          usbMetadata = {
            vendorId: `0x${usbDevice.vendorId.toString(16).padStart(4, "0")}`,
            productId: `0x${usbDevice.productId.toString(16).padStart(4, "0")}`,
            serialNumber: usbDevice.serialNumber || "Generated ID",
            manufacturerName: usbDevice.manufacturerName || "Unknown",
            productName: usbDevice.productName || "Unknown",
            usbVersionMajor: usbDevice.usbVersionMajor,
            usbVersionMinor: usbDevice.usbVersionMinor,
            deviceClass: usbDevice.deviceClass,
            deviceSubclass: usbDevice.deviceSubclass,
            deviceProtocol: usbDevice.deviceProtocol,
          };
          console.log("✅ USB device metadata acquired:", usbMetadata);
        }
      } catch (usbError) {
        console.log(
          "⚠️ WebUSB request failed, generating fallback ID:",
          usbError
        );
        // Generate a fallback unique ID if WebUSB fails
        serialNumber = `fallback-${Date.now()}-${Math.random()
          .toString(36)
          .substr(2, 9)}`;
        usbMetadata = {
          vendorId: "Unknown",
          productId: "Unknown",
          serialNumber: serialNumber,
          manufacturerName: "USB Metadata Not Available",
          productName: "Check browser WebUSB support",
        };
      }

      const portName = getPortDisplayName(port);

      // Step 3: Check if this robot (by serial number) is already connected
      const existingIndex = connectedRobots.findIndex(
        (robot) => robot.serialNumber === serialNumber
      );

      if (existingIndex === -1) {
        // New robot - add to list
        const newRobot: ConnectedRobot = {
          port,
          name: portName,
          isConnected: true,
          serialNumber: serialNumber!,
          usbMetadata: usbMetadata || undefined,
        };

        // Try to load saved robot info by serial number using unified storage
        if (serialNumber) {
          try {
            const { getRobotConfig } = await import("../lib/unified-storage");
            const savedConfig = getRobotConfig(serialNumber);
            if (savedConfig) {
              newRobot.robotType = savedConfig.robotType as
                | "so100_follower"
                | "so100_leader";
              newRobot.robotId = savedConfig.robotId;
              console.log("📋 Loaded saved robot configuration:", savedConfig);
            }
          } catch (error) {
            console.warn("Failed to load saved robot data:", error);
          }
        }

        onConnectedRobotsChange([...connectedRobots, newRobot]);
        console.log("🤖 New robot connected with ID:", serialNumber);

        // Register with singleton connection manager if robot is configured
        if (newRobot.robotType && newRobot.robotId) {
          try {
            const { getRobotConnectionManager } = await import(
              "../../lerobot/web/robot-connection"
            );
            const connectionManager = getRobotConnectionManager();
            await connectionManager.connect(
              port,
              newRobot.robotType,
              newRobot.robotId,
              serialNumber!
            );
          } catch (error) {
            console.warn(
              "Failed to register new connection with manager:",
              error
            );
          }
        }
      } else {
        // Existing robot - update port and connection status
        const updatedRobots = connectedRobots.map((robot, index) =>
          index === existingIndex
            ? { ...robot, port, isConnected: true, name: portName }
            : robot
        );
        onConnectedRobotsChange(updatedRobots);
        console.log("🔄 Existing robot reconnected:", serialNumber);
      }
    } catch (error) {
      if (
        error instanceof Error &&
        (error.message.includes("cancelled") ||
          error.message.includes("No port selected by the user") ||
          error.name === "NotAllowedError")
      ) {
        // User cancelled - no error message needed, just log to console
        console.log("Connection cancelled by user");
        return;
      }
      setError(
        error instanceof Error ? error.message : "Failed to connect to robot"
      );
    } finally {
      setIsConnecting(false);
    }
  };

  const handleDisconnect = async (index: number) => {
    const portInfo = connectedRobots[index];
    const robotName = portInfo.robotId || portInfo.name;
    const serialNumber = portInfo.serialNumber || "unknown";

    // Show confirmation dialog
    setConfirmDeleteDialog({
      open: true,
      robotIndex: index,
      robotName,
      serialNumber,
    });
  };

  const confirmDelete = async () => {
    const { robotIndex } = confirmDeleteDialog;
    const portInfo = connectedRobots[robotIndex];

    setConfirmDeleteDialog({
      open: false,
      robotIndex: -1,
      robotName: "",
      serialNumber: "",
    });

    try {
      // Close the serial port connection
      if (portInfo.isConnected) {
        await portInfo.port.close();
      }

      // Delete from unified storage if serial number is available
      if (portInfo.serialNumber) {
        try {
          const { getUnifiedKey } = await import("../lib/unified-storage");
          const unifiedKey = getUnifiedKey(portInfo.serialNumber);

          // Remove unified storage data
          localStorage.removeItem(unifiedKey);
          console.log(`🗑️ Deleted unified robot data: ${unifiedKey}`);
        } catch (error) {
          console.warn("Failed to delete unified storage data:", error);
        }
      }

      // Remove from UI
      const updatedRobots = connectedRobots.filter((_, i) => i !== robotIndex);
      onConnectedRobotsChange(updatedRobots);

      console.log(
        `✅ Robot "${confirmDeleteDialog.robotName}" permanently removed from system`
      );
    } catch (error) {
      setError(
        error instanceof Error ? error.message : "Failed to remove robot"
      );
    }
  };

  const cancelDelete = () => {
    setConfirmDeleteDialog({
      open: false,
      robotIndex: -1,
      robotName: "",
      serialNumber: "",
    });
  };

  const handleUpdatePortInfo = (
    index: number,
    robotType: "so100_follower" | "so100_leader",
    robotId: string
  ) => {
    const updatedRobots = connectedRobots.map((robot, i) => {
      if (i === index) {
        const updatedRobot = { ...robot, robotType, robotId };

        // Save robot configuration using unified storage
        if (updatedRobot.serialNumber) {
          import("../lib/unified-storage")
            .then(({ saveRobotConfig }) => {
              saveRobotConfig(
                updatedRobot.serialNumber!,
                robotType,
                robotId,
                updatedRobot.usbMetadata
              );
              console.log(
                "💾 Saved robot configuration for:",
                updatedRobot.serialNumber
              );
            })
            .catch((error) => {
              console.warn("Failed to save robot configuration:", error);
            });
        }

        return updatedRobot;
      }
      return robot;
    });
    onConnectedRobotsChange(updatedRobots);
  };

  const handleFindPorts = async () => {
    if (!isWebSerialSupported()) {
      setError("Web Serial API is not supported in this browser");
      return;
    }

    try {
      setIsFindingPorts(true);
      setFindPortsLog([]);
      setError(null);

      // Get initial ports
      const initialPorts = await navigator.serial.getPorts();
      setFindPortsLog((prev) => [
        ...prev,
        `Found ${initialPorts.length} existing paired port(s)`,
      ]);

      // Ask user to disconnect
      setFindPortsLog((prev) => [
        ...prev,
        "Please disconnect the USB cable from your robot and click OK",
      ]);

      // Simple implementation - just show the instruction
      // In a real implementation, we'd monitor port changes
      const confirmed = confirm(
        "Disconnect the USB cable from your robot and click OK when done"
      );

      if (confirmed) {
        setFindPortsLog((prev) => [...prev, "Reconnect the USB cable now"]);

        // Request port selection
        const port = await navigator.serial.requestPort();
        await port.open({ baudRate: 1000000 });

        const portName = getPortDisplayName(port);
        setFindPortsLog((prev) => [...prev, `Identified port: ${portName}`]);

        // Add to connected ports if not already there
        const existingIndex = connectedRobots.findIndex(
          (p) => p.name === portName
        );
        if (existingIndex === -1) {
          const newPort: ConnectedRobot = {
            port,
            name: portName,
            isConnected: true,
          };
          onConnectedRobotsChange([...connectedRobots, newPort]);
        }
      }
    } catch (error) {
      if (
        error instanceof Error &&
        (error.message.includes("cancelled") ||
          error.name === "NotAllowedError")
      ) {
        // User cancelled - no message needed, just log to console
        console.log("Port identification cancelled by user");
        return;
      }
      setError(error instanceof Error ? error.message : "Failed to find ports");
    } finally {
      setIsFindingPorts(false);
    }
  };

  const ensurePortIsOpen = async (robotIndex: number) => {
    const robot = connectedRobots[robotIndex];
    if (!robot) return false;

    try {
      // If port is already open, we're good
      if (robot.port.readable !== null && robot.port.writable !== null) {
        return true;
      }

      // Try to open the port
      await robot.port.open({ baudRate: 1000000 });

      // Update the robot's connection status
      const updatedRobots = connectedRobots.map((r, i) =>
        i === robotIndex ? { ...r, isConnected: true } : r
      );
      onConnectedRobotsChange(updatedRobots);

      return true;
    } catch (error) {
      console.error("Failed to open port for calibration:", error);
      setError(error instanceof Error ? error.message : "Failed to open port");
      return false;
    }
  };

  const handleCalibrate = async (port: ConnectedRobot) => {
    if (!port.robotType || !port.robotId) {
      setError("Please set robot type and ID before calibrating");
      return;
    }

    // Find the robot index
    const robotIndex = connectedRobots.findIndex((r) => r.port === port.port);
    if (robotIndex === -1) {
      setError("Robot not found in connected robots list");
      return;
    }

    // Ensure port is open before calibrating
    const isOpen = await ensurePortIsOpen(robotIndex);
    if (!isOpen) {
      return; // Error already set in ensurePortIsOpen
    }

    if (onCalibrate) {
      onCalibrate(port.port, port.robotType, port.robotId);
    }
  };

  return (
    <Card>
      <CardHeader>
        <CardTitle>🔌 Robot Connection Manager</CardTitle>
        <CardDescription>
          Connect, identify, and manage your robot arms
        </CardDescription>
      </CardHeader>
      <CardContent>
        <div className="space-y-6">
          {/* Error Display */}
          {error && (
            <Alert variant="destructive">
              <AlertDescription>{error}</AlertDescription>
            </Alert>
          )}

          {/* Connection Controls */}
          <div className="flex gap-2">
            <Button
              onClick={handleConnect}
              disabled={isConnecting || !isWebSerialSupported()}
              className="flex-1"
            >
              {isConnecting ? "Connecting..." : "Connect Robot"}
            </Button>
            <Button
              variant="outline"
              onClick={handleFindPorts}
              disabled={isFindingPorts || !isWebSerialSupported()}
              className="flex-1"
            >
              {isFindingPorts ? "Finding..." : "Find Port"}
            </Button>
          </div>

          {/* Find Ports Log */}
          {findPortsLog.length > 0 && (
            <div className="bg-gray-50 p-3 rounded-md text-sm space-y-1">
              {findPortsLog.map((log, index) => (
                <div key={index} className="text-gray-700">
                  {log}
                </div>
              ))}
            </div>
          )}

          {/* Connected Ports */}
          <div>
            <h4 className="font-semibold mb-3">
              Connected Robots ({connectedRobots.length})
            </h4>

            {connectedRobots.length === 0 ? (
              <div className="text-center py-8 text-gray-500">
                <div className="text-2xl mb-2">🤖</div>
                <p>No robots connected</p>
                <p className="text-xs">
                  Use "Connect Robot" or "Find Port" to add robots
                </p>
              </div>
            ) : (
              <div className="space-y-4">
                {connectedRobots.map((portInfo, index) => (
                  <PortCard
                    key={index}
                    portInfo={portInfo}
                    onDisconnect={() => handleDisconnect(index)}
                    onUpdateInfo={(robotType, robotId) =>
                      handleUpdatePortInfo(index, robotType, robotId)
                    }
                    onCalibrate={() => handleCalibrate(portInfo)}
                    onTeleoperate={() => onTeleoperate?.(portInfo)}
                  />
                ))}
              </div>
            )}
          </div>
        </div>
      </CardContent>

      {/* Confirmation Dialog */}
      <Dialog open={confirmDeleteDialog.open} onOpenChange={cancelDelete}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>🗑️ Permanently Delete Robot Data?</DialogTitle>
            <DialogDescription>
              This action cannot be undone. All robot data will be permanently
              deleted.
            </DialogDescription>
          </DialogHeader>

          <div className="space-y-3">
            <div className="p-4 bg-red-50 rounded-lg border border-red-200">
              <div className="font-medium text-red-900 mb-2">
                Robot Information:
              </div>
              <div className="text-sm text-red-800 space-y-1">
                <div>
                  • Name:{" "}
                  <span className="font-mono">
                    {confirmDeleteDialog.robotName}
                  </span>
                </div>
                <div>
                  • Serial:{" "}
                  <span className="font-mono">
                    {confirmDeleteDialog.serialNumber}
                  </span>
                </div>
              </div>
            </div>

            <div className="p-4 bg-red-50 rounded-lg border border-red-200">
              <div className="font-medium text-red-900 mb-2">
                This will permanently delete:
              </div>
              <div className="text-sm text-red-800 space-y-1">
                <div>• Robot configuration</div>
                <div>• Calibration data</div>
                <div>• All saved settings</div>
              </div>
            </div>
          </div>

          <DialogFooter>
            <Button variant="outline" onClick={cancelDelete}>
              Cancel
            </Button>
            <Button variant="destructive" onClick={confirmDelete}>
              Delete Forever
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </Card>
  );
}

interface PortCardProps {
  portInfo: ConnectedRobot;
  onDisconnect: () => void;
  onUpdateInfo: (
    robotType: "so100_follower" | "so100_leader",
    robotId: string
  ) => void;
  onCalibrate: () => void;
  onTeleoperate: () => void;
}

function PortCard({
  portInfo,
  onDisconnect,
  onUpdateInfo,
  onCalibrate,
  onTeleoperate,
}: PortCardProps) {
  const [robotType, setRobotType] = useState<"so100_follower" | "so100_leader">(
    portInfo.robotType || "so100_follower"
  );
  const [robotId, setRobotId] = useState(portInfo.robotId || "");
  const [isEditing, setIsEditing] = useState(false);
  const [isScanning, setIsScanning] = useState(false);
  const [motorIDs, setMotorIDs] = useState<number[]>([]);
  const [portMetadata, setPortMetadata] = useState<any>(null);
  const [showDeviceInfo, setShowDeviceInfo] = useState(false);

  // Check for calibration using unified storage
  const getCalibrationStatus = () => {
    // Use the same serial number logic as calibration: prefer main serialNumber, fallback to USB metadata, then "unknown"
    const serialNumber =
      portInfo.serialNumber || portInfo.usbMetadata?.serialNumber || "unknown";

    try {
      // Use unified storage system with automatic migration
      import("../lib/unified-storage")
        .then(({ getCalibrationStatus }) => {
          const status = getCalibrationStatus(serialNumber);
          return status;
        })
        .catch((error) => {
          console.warn("Failed to load unified calibration data:", error);
          return null;
        });

      // For immediate synchronous return, try to get existing unified data first
      const unifiedKey = `lerobotjs-${serialNumber}`;
      const existing = localStorage.getItem(unifiedKey);
      if (existing) {
        const data = JSON.parse(existing);
        if (data.calibration?.metadata) {
          return {
            timestamp: data.calibration.metadata.timestamp,
            readCount: data.calibration.metadata.readCount,
          };
        }
      }
    } catch (error) {
      console.warn("Failed to read calibration from unified storage:", error);
    }
    return null;
  };

  const calibrationStatus = getCalibrationStatus();

  const handleSave = () => {
    if (robotId.trim()) {
      onUpdateInfo(robotType, robotId.trim());
      setIsEditing(false);
    }
  };

  // Use current values (either from props or local state)
  const currentRobotType = portInfo.robotType || robotType;
  const currentRobotId = portInfo.robotId || robotId;

  const handleCancel = () => {
    setRobotType(portInfo.robotType || "so100_follower");
    setRobotId(portInfo.robotId || "");
    setIsEditing(false);
  };

  // Scan for motor IDs and gather USB device metadata
  const scanDeviceInfo = async () => {
    if (!portInfo.port || !portInfo.isConnected) {
      console.warn("Port not connected");
      return;
    }

    setIsScanning(true);
    setMotorIDs([]);
    setPortMetadata(null);
    const foundIDs: number[] = [];

    try {
      // Try to get USB device info using WebUSB for better metadata
      let usbDeviceInfo = null;

      try {
        // First, check if we already have USB device permissions
        let usbDevices = await navigator.usb.getDevices();
        console.log("Already permitted USB devices:", usbDevices);

        // If no devices found, request permission for USB-to-serial devices
        if (usbDevices.length === 0) {
          console.log(
            "No USB permissions yet, requesting access to USB-to-serial devices..."
          );

          // Request access to common USB-to-serial chips
          try {
            const device = await navigator.usb.requestDevice({
              filters: [
                { vendorId: 0x0403 }, // FTDI
                { vendorId: 0x067b }, // Prolific
                { vendorId: 0x10c4 }, // Silicon Labs
                { vendorId: 0x1a86 }, // QinHeng Electronics (CH340)
                { vendorId: 0x239a }, // Adafruit
                { vendorId: 0x2341 }, // Arduino
                { vendorId: 0x2e8a }, // Raspberry Pi Foundation
                { vendorId: 0x1b4f }, // SparkFun
              ],
            });

            if (device) {
              usbDevices = [device];
              console.log("USB device access granted:", device);
            }
          } catch (requestError) {
            console.log(
              "User cancelled USB device selection or no devices found"
            );
            // Try requesting any device as fallback
            try {
              const anyDevice = await navigator.usb.requestDevice({
                filters: [], // Allow any USB device
              });
              if (anyDevice) {
                usbDevices = [anyDevice];
                console.log("Fallback USB device selected:", anyDevice);
              }
            } catch (fallbackError) {
              console.log("No USB device selected");
            }
          }
        }

        // Try to match with Web Serial port (this is tricky, so we'll take the first available)
        if (usbDevices.length > 0) {
          // Look for common USB-to-serial chip vendor IDs
          const serialChipVendors = [
            0x0403, // FTDI
            0x067b, // Prolific
            0x10c4, // Silicon Labs
            0x1a86, // QinHeng Electronics (CH340)
            0x239a, // Adafruit
            0x2341, // Arduino
            0x2e8a, // Raspberry Pi Foundation
            0x1b4f, // SparkFun
          ];

          const serialDevice =
            usbDevices.find((device) =>
              serialChipVendors.includes(device.vendorId)
            ) || usbDevices[0]; // Fallback to first device

          if (serialDevice) {
            usbDeviceInfo = {
              vendorId: `0x${serialDevice.vendorId
                .toString(16)
                .padStart(4, "0")}`,
              productId: `0x${serialDevice.productId
                .toString(16)
                .padStart(4, "0")}`,
              serialNumber: serialDevice.serialNumber || "Not available",
              manufacturerName: serialDevice.manufacturerName || "Unknown",
              productName: serialDevice.productName || "Unknown",
              usbVersionMajor: serialDevice.usbVersionMajor,
              usbVersionMinor: serialDevice.usbVersionMinor,
              deviceClass: serialDevice.deviceClass,
              deviceSubclass: serialDevice.deviceSubclass,
              deviceProtocol: serialDevice.deviceProtocol,
            };
            console.log("USB device info:", usbDeviceInfo);
          }
        }
      } catch (usbError) {
        console.log("WebUSB not available or no permissions:", usbError);
        // Fallback to Web Serial API info
        const portInfo_metadata = portInfo.port.getInfo();
        console.log("Serial port metadata fallback:", portInfo_metadata);
        if (Object.keys(portInfo_metadata).length > 0) {
          usbDeviceInfo = {
            vendorId: portInfo_metadata.usbVendorId
              ? `0x${portInfo_metadata.usbVendorId
                  .toString(16)
                  .padStart(4, "0")}`
              : "Not available",
            productId: portInfo_metadata.usbProductId
              ? `0x${portInfo_metadata.usbProductId
                  .toString(16)
                  .padStart(4, "0")}`
              : "Not available",
            serialNumber: "Not available via Web Serial",
            manufacturerName: "Not available via Web Serial",
            productName: "Not available via Web Serial",
          };
        }
      }

      setPortMetadata(usbDeviceInfo);

      // Get reader/writer for the port
      const reader = portInfo.port.readable?.getReader();
      const writer = portInfo.port.writable?.getWriter();

      if (!reader || !writer) {
        console.warn("Cannot access port reader/writer");
        setShowDeviceInfo(true);
        return;
      }

      // Test motor IDs 1-10 (common range for servos)
      for (let motorId = 1; motorId <= 10; motorId++) {
        try {
          // Create STS3215 ping packet
          const packet = new Uint8Array([
            0xff,
            0xff,
            motorId,
            0x02,
            0x01,
            0x00,
          ]);
          const checksum = ~(motorId + 0x02 + 0x01) & 0xff;
          packet[5] = checksum;

          // Send ping
          await writer.write(packet);

          // Wait a bit for response
          await new Promise((resolve) => setTimeout(resolve, 20));

          // Try to read response with timeout
          const timeoutPromise = new Promise((_, reject) =>
            setTimeout(() => reject(new Error("Timeout")), 50)
          );

          try {
            const result = (await Promise.race([
              reader.read(),
              timeoutPromise,
            ])) as ReadableStreamReadResult<Uint8Array>;

            if (
              result &&
              !result.done &&
              result.value &&
              result.value.length >= 6
            ) {
              const response = result.value;
              const responseId = response[2];

              // If we got a response with matching ID, motor exists
              if (responseId === motorId) {
                foundIDs.push(motorId);
              }
            }
          } catch (readError) {
            // No response from this motor ID - that's normal
          }
        } catch (error) {
          console.warn(`Error testing motor ID ${motorId}:`, error);
        }

        // Small delay between tests
        await new Promise((resolve) => setTimeout(resolve, 10));
      }

      reader.releaseLock();
      writer.releaseLock();

      setMotorIDs(foundIDs);
      setShowDeviceInfo(true);
    } catch (error) {
      console.error("Device info scan failed:", error);
    } finally {
      setIsScanning(false);
    }
  };

  return (
    <div className="border rounded-lg p-4 space-y-3">
      {/* Header with port name and status */}
      <div className="flex items-center justify-between">
        <div className="flex items-center space-x-2">
          <div className="flex flex-col">
            <span className="font-medium">{portInfo.name}</span>
            {portInfo.serialNumber && (
              <span className="text-xs text-gray-500 font-mono">
                ID:{" "}
                {portInfo.serialNumber.length > 20
                  ? portInfo.serialNumber.substring(0, 20) + "..."
                  : portInfo.serialNumber}
              </span>
            )}
          </div>
          <Badge variant={portInfo.isConnected ? "default" : "outline"}>
            {portInfo.isConnected ? "Connected" : "Available"}
          </Badge>
        </div>
        <Button variant="destructive" size="sm" onClick={onDisconnect}>
          Remove
        </Button>
      </div>

      {/* Robot Info Display (when not editing) */}
      {!isEditing && currentRobotType && currentRobotId && (
        <div className="flex items-center justify-between p-3 bg-gray-50 rounded-lg">
          <div className="flex items-center space-x-3">
            <div>
              <div className="font-medium text-sm">{currentRobotId}</div>
              <div className="text-xs text-gray-600">
                {currentRobotType.replace("_", " ")}
              </div>
            </div>
            {calibrationStatus && (
              <Badge variant="default" className="bg-green-100 text-green-800">
                ✅ Calibrated
              </Badge>
            )}
          </div>
          <Button
            variant="outline"
            size="sm"
            onClick={() => setIsEditing(true)}
          >
            Edit
          </Button>
        </div>
      )}

      {/* Setup prompt for unconfigured robots */}
      {!isEditing && (!currentRobotType || !currentRobotId) && (
        <div className="flex items-center justify-between p-3 bg-blue-50 rounded-lg">
          <div className="text-sm text-blue-800">
            Robot needs configuration before use
          </div>
          <Button
            variant="outline"
            size="sm"
            onClick={() => setIsEditing(true)}
          >
            Configure
          </Button>
        </div>
      )}

      {/* Robot Configuration Form (when editing) */}
      {isEditing && (
        <div className="space-y-3 p-3 bg-gray-50 rounded-lg">
          <div className="grid grid-cols-2 gap-3">
            <div>
              <label className="text-sm font-medium block mb-1">
                Robot Type
              </label>
              <select
                value={robotType}
                onChange={(e) =>
                  setRobotType(
                    e.target.value as "so100_follower" | "so100_leader"
                  )
                }
                className="w-full px-2 py-1 border rounded text-sm"
              >
                <option value="so100_follower">SO-100 Follower</option>
                <option value="so100_leader">SO-100 Leader</option>
              </select>
            </div>
            <div>
              <label className="text-sm font-medium block mb-1">Robot ID</label>
              <input
                type="text"
                value={robotId}
                onChange={(e) => setRobotId(e.target.value)}
                placeholder="e.g., my_robot"
                className="w-full px-2 py-1 border rounded text-sm"
              />
            </div>
          </div>

          <div className="flex gap-2">
            <Button size="sm" onClick={handleSave} disabled={!robotId.trim()}>
              Save
            </Button>
            <Button size="sm" variant="outline" onClick={handleCancel}>
              Cancel
            </Button>
          </div>
        </div>
      )}

      {/* Calibration Status and Action */}
      {currentRobotType && currentRobotId && (
        <div className="space-y-3">
          <div className="flex items-center justify-between">
            <div className="text-sm text-gray-600">
              {calibrationStatus ? (
                <span>
                  Last calibrated:{" "}
                  {new Date(calibrationStatus.timestamp).toLocaleDateString()}
                  <span className="text-xs ml-1">
                    ({calibrationStatus.readCount} readings)
                  </span>
                </span>
              ) : (
                <span>Not calibrated yet</span>
              )}
            </div>
            <div className="flex gap-2">
              <Button
                size="sm"
                variant={calibrationStatus ? "outline" : "default"}
                onClick={onCalibrate}
                disabled={!currentRobotType || !currentRobotId}
              >
                {calibrationStatus ? "Re-calibrate" : "Calibrate"}
              </Button>
              <Button
                size="sm"
                variant="outline"
                onClick={onTeleoperate}
                disabled={
                  !currentRobotType || !currentRobotId || !portInfo.isConnected
                }
              >
                🎮 Teleoperate
              </Button>
            </div>
          </div>

          {/* Device Info Scanner */}
          <div className="flex items-center justify-between">
            <div className="text-sm text-gray-600">
              Scan device info and motor IDs
            </div>
            <Button
              size="sm"
              variant="outline"
              onClick={scanDeviceInfo}
              disabled={!portInfo.isConnected || isScanning}
            >
              {isScanning ? "Scanning..." : "Show Device Info"}
            </Button>
          </div>

          {/* Device Info Results */}
          {showDeviceInfo && (
            <div className="p-3 bg-gray-50 rounded-lg space-y-3">
              {/* USB Device Information */}
              {portMetadata && (
                <div>
                  <div className="text-sm font-medium mb-2">
                    📱 USB Device Info:
                  </div>
                  <div className="space-y-1 text-xs">
                    <div className="flex justify-between">
                      <span className="text-gray-600">Vendor ID:</span>
                      <span className="font-mono">{portMetadata.vendorId}</span>
                    </div>
                    <div className="flex justify-between">
                      <span className="text-gray-600">Product ID:</span>
                      <span className="font-mono">
                        {portMetadata.productId}
                      </span>
                    </div>
                    <div className="flex justify-between">
                      <span className="text-gray-600">Serial Number:</span>
                      <span className="font-mono text-green-600 font-semibold">
                        {portMetadata.serialNumber}
                      </span>
                    </div>
                    <div className="flex justify-between">
                      <span className="text-gray-600">Manufacturer:</span>
                      <span>{portMetadata.manufacturerName}</span>
                    </div>
                    <div className="flex justify-between">
                      <span className="text-gray-600">Product:</span>
                      <span>{portMetadata.productName}</span>
                    </div>
                    {portMetadata.usbVersionMajor && (
                      <div className="flex justify-between">
                        <span className="text-gray-600">USB Version:</span>
                        <span>
                          {portMetadata.usbVersionMajor}.
                          {portMetadata.usbVersionMinor}
                        </span>
                      </div>
                    )}
                    {portMetadata.deviceClass !== undefined && (
                      <div className="flex justify-between">
                        <span className="text-gray-600">Device Class:</span>
                        <span>
                          0x
                          {portMetadata.deviceClass
                            .toString(16)
                            .padStart(2, "0")}
                        </span>
                      </div>
                    )}
                  </div>
                </div>
              )}

              {/* Motor IDs */}
              <div>
                <div className="text-sm font-medium mb-2">
                  🤖 Found Motor IDs:
                </div>
                {motorIDs.length > 0 ? (
                  <div className="flex flex-wrap gap-2">
                    {motorIDs.map((id) => (
                      <Badge key={id} variant="outline" className="text-xs">
                        Motor {id}
                      </Badge>
                    ))}
                  </div>
                ) : (
                  <div className="text-sm text-gray-500">
                    No motor IDs found. Check connection and power.
                  </div>
                )}
              </div>

              <Button
                size="sm"
                variant="outline"
                onClick={() => setShowDeviceInfo(false)}
                className="mt-2 text-xs"
              >
                Hide
              </Button>
            </div>
          )}
        </div>
      )}
    </div>
  );
}
