import { useEffect, useState } from 'react';
import {
  Printer, HardDrive, Network, Box, ChevronRight, RefreshCw, FolderOpen,
  Computer, Cable, CassetteTape, Plug, Zap, MoreVertical,
  Info, Tag, Database, CheckCircle, Activity,
} from 'lucide-react';
import {
  Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription,
} from './ui/dialog';
import DeviceDetailOverlay from './DeviceDetailOverlay';
import MediaBrowser from './MediaBrowser';
import { toast } from 'sonner';
import { useWs } from '../ws';

interface Device {
  id: string;
  number: string;
  type: 'printer' | 'drive' | 'network' | 'other' | 'meatloaf';
  name?: string;
  enabled: boolean | number;
  base_url?: string;
  url?: string;
  mode?: number;
}

interface PhysicalDevice {
  number: string;
  model: string;
  status: 'Ready' | 'Busy' | 'Not Responding';
}

type DeviceStatus = 'Virtual' | 'Disabled' | 'Ready' | 'Busy' | 'Not Responding';

interface DisplayDevice extends Device {
  physical: boolean;
  physicalModel?: string;
  deviceStatus: DeviceStatus;
}

interface DeviceAction {
  label: string;
  Icon: React.ComponentType<{ className?: string }>;
  cmd: string;
  variant?: 'primary' | 'danger';
}

function getDeviceActions(device: DisplayDevice): DeviceAction[] {
  const actions: DeviceAction[] = [
    { label: 'Initialize', Icon: Zap, cmd: `iec init ${device.number}`, variant: 'primary' },
  ];
  if (device.type === 'drive') {
    actions.push(
      { label: 'Read Directory', Icon: FolderOpen,  cmd: `iec dir ${device.number}`,  variant: 'primary' },
      { label: 'Test Drive',     Icon: CheckCircle, cmd: `iec test ${device.number}` },
    );
    if (device.physical) {
      actions.push({ label: 'Identify', Icon: Tag, cmd: `iec id ${device.number}` });
    }
    actions.push({ label: 'Format Disk', Icon: Database, cmd: `iec format ${device.number}`, variant: 'danger' });
  }
  if (device.type === 'printer') {
    actions.push(
      { label: 'Test Print',   Icon: Printer,   cmd: `iec print ${device.number}` },
      { label: 'Reset Device', Icon: RefreshCw, cmd: `iec reset ${device.number}`, variant: 'danger' },
    );
  }
  if (device.type === 'network') {
    actions.push(
      { label: 'Ping',         Icon: Activity,  cmd: `iec ping ${device.number}` },
      { label: 'Reset Device', Icon: RefreshCw, cmd: `iec reset ${device.number}`, variant: 'danger' },
    );
  }
  if (device.type === 'meatloaf') {
    actions.push(
      { label: 'System Info',  Icon: Info,      cmd: `iec info ${device.number}` },
      { label: 'Reset Device', Icon: RefreshCw, cmd: `iec reset ${device.number}`, variant: 'danger' },
    );
  }
  return actions;
}

const PHYSICAL_MODELS = ['SD2IEC', '1541', '1541-II', '1571', '1581', 'RAMLINK', 'CMD HD40', 'PI1541'];
const PHYSICAL_STATUSES: PhysicalDevice['status'][] = ['Ready', 'Ready', 'Ready', 'Busy', 'Not Responding'];

interface DevicesPageProps {
  config: any;
  setConfig: (config: any) => void;
  openDeviceId?: string | null;
  onClearOpenDevice?: () => void;
}

export default function DevicesPage({ config, setConfig, openDeviceId, onClearOpenDevice }: DevicesPageProps) {
  const updateSetting = (path: string[], value: any) => {
    const newConfig = JSON.parse(JSON.stringify(config));
    let current = newConfig;
    for (let i = 0; i < path.length - 1; i++) {
      current = current[path[i]];
    }
    current[path[path.length - 1]] = value;
    setConfig(newConfig);
  };

  const [selectedDeviceIndex, setSelectedDeviceIndex] = useState<number | null>(null);
  const [isScanning, setIsScanning]                   = useState(false);
  const [showCassetteUrlBrowser, setShowCassetteUrlBrowser] = useState(false);
  const [physicalDevices, setPhysicalDevices]         = useState<PhysicalDevice[]>([]);
  const [actionDevice, setActionDevice]               = useState<DisplayDevice | null>(null);

  const hardware = config.hardware || {};
  const cassette = config.cassette || {};

  // Virtual devices from config (used for detail overlay navigation)
  const devices: Device[] = [];
  if (config.iec?.devices) {
    Object.entries(config.iec.devices).forEach(([num, device]: [string, any]) => {
      const type = device.type as Device['type'];
      const name = device.name || (
        type === 'drive'    ? `Drive ${num}` :
        type === 'network'  ? `Network ${num}` :
        type === 'meatloaf' ? `Meatloaf ${num}` :
        undefined
      );
      devices.push({
        id: `${type}-${num}`,
        number: num,
        type,
        name,
        enabled: device.enabled,
        base_url: device.base_url,
        url: device.url,
        mode: device.mode,
      });
    });
  }

  // Unified display list: physical devices shadow virtual ones at the same bus address
  const physicalNums = new Set(physicalDevices.map(p => p.number));

  const displayDevices: DisplayDevice[] = [];
  devices.forEach(d => {
    if (physicalNums.has(d.number)) return;
    displayDevices.push({ ...d, physical: false, deviceStatus: d.enabled ? 'Virtual' : 'Disabled' });
  });
  physicalDevices.forEach(p => {
    displayDevices.push({
      id: `physical-${p.number}`,
      number: p.number,
      type: 'drive',
      name: p.model,
      enabled: 1,
      physical: true,
      physicalModel: p.model,
      deviceStatus: p.status,
    });
  });
  displayDevices.sort((a, b) => parseInt(a.number) - parseInt(b.number));

  // Auto-open the overlay when the parent passes a device ID
  useEffect(() => {
    if (!openDeviceId) return;
    const idx = devices.findIndex(d => d.id === openDeviceId);
    if (idx >= 0) setSelectedDeviceIndex(idx);
    onClearOpenDevice?.();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [openDeviceId]);

  const getDeviceIcon = (type: Device['type']) => {
    switch (type) {
      case 'printer':  return <Printer   className="w-5 h-5" />;
      case 'drive':    return <HardDrive className="w-5 h-5" />;
      case 'network':  return <Network   className="w-5 h-5" />;
      case 'meatloaf': return <Computer  className="w-5 h-5" />;
      default:         return <Box       className="w-5 h-5" />;
    }
  };

  const iconColor = (device: DisplayDevice) => {
    if (device.physical) {
      if (device.deviceStatus === 'Not Responding') return 'text-red-500';
      if (device.deviceStatus === 'Busy')           return 'text-amber-500';
      return 'text-green-600';
    }
    return device.enabled ? 'text-blue-600' : 'text-neutral-400';
  };

  const statusEl = (status: DeviceStatus) => {
    const dot = (cls: string) => <span className={`inline-block w-1.5 h-1.5 rounded-full mr-1.5 ${cls}`} />;
    switch (status) {
      case 'Ready':          return <><span className="text-green-600">{dot('bg-green-500')}Ready</span></>;
      case 'Busy':           return <><span className="text-amber-600">{dot('bg-amber-400')}Busy</span></>;
      case 'Not Responding': return <><span className="text-red-600">{dot('bg-red-500')}Not Responding</span></>;
      case 'Disabled':       return <span className="text-neutral-400">Disabled</span>;
      default:               return <span className="text-blue-600">Virtual</span>;
    }
  };

  const handleDeviceClick = (dd: DisplayDevice) => {
    if (dd.physical) return;
    const idx = devices.findIndex(d => d.number === dd.number);
    if (idx >= 0) setSelectedDeviceIndex(idx);
  };

  const handleCloseOverlay = () => setSelectedDeviceIndex(null);

  const handleNavigate = (direction: 'prev' | 'next') => {
    if (selectedDeviceIndex === null) return;
    if (direction === 'prev' && selectedDeviceIndex > 0)
      setSelectedDeviceIndex(selectedDeviceIndex - 1);
    else if (direction === 'next' && selectedDeviceIndex < devices.length - 1)
      setSelectedDeviceIndex(selectedDeviceIndex + 1);
  };

  const { send: wsSend } = useWs();

  const rescanBus = async () => {
    setIsScanning(true);
    wsSend('iec scan');
    const toastId = toast.loading('Scanning IEC bus...');

    await new Promise(resolve => setTimeout(resolve, 2000));

    const count    = 2 + Math.floor(Math.random() * 3);
    const shuffled = [...PHYSICAL_MODELS].sort(() => Math.random() - 0.5).slice(0, count);
    const usedIds  = new Set<string>();
    const found: PhysicalDevice[] = shuffled.map(model => {
      let id: number;
      do { id = 8 + Math.floor(Math.random() * 22); } while (usedIds.has(String(id)));
      usedIds.add(String(id));
      return {
        number: String(id),
        model,
        status: PHYSICAL_STATUSES[Math.floor(Math.random() * PHYSICAL_STATUSES.length)],
      };
    });
    found.sort((a, b) => parseInt(a.number) - parseInt(b.number));

    setPhysicalDevices(found);
    setIsScanning(false);
    toast.dismiss(toastId);
    toast.success(`Found ${found.length} physical device${found.length !== 1 ? 's' : ''} on the bus`);
  };

  const handleAction = (action: DeviceAction) => {
    wsSend(action.cmd);
    toast.success(`${action.label} sent to device #${actionDevice?.number}`);
    setActionDevice(null);
  };

  const toggleDeviceEnabled = (device: DisplayDevice, e: React.MouseEvent) => {
    e.stopPropagation();
    const newConfig = JSON.parse(JSON.stringify(config));
    newConfig.iec.devices[device.number].enabled = device.enabled ? 0 : 1;
    setConfig(newConfig);
    toast.success(`Device #${device.number} ${device.enabled ? 'disabled' : 'enabled'}`);
  };

  return (
    <div className="p-4">
      {/* ── Host Settings ── */}
      <h2 className="text-sm text-neutral-500 mb-2 flex items-center gap-2"><Computer className="w-4 h-4" /> Host Settings</h2>
      <div className="bg-white border border-neutral-200 rounded-lg divide-y divide-neutral-200 mb-6">
        <div className="p-4">
          <label className="text-sm text-neutral-500 block mb-2">Model</label>
          <select
            value={config.host?.model?.split('|')[0] || 'c64'}
            onChange={(e) => updateSetting(['host', 'model'], e.target.value)}
            className="w-full px-3 py-2 border border-neutral-300 rounded-lg"
          >
            <option value="c64">C64/C64c/SX64</option>
            <option value="c64u">C64/C64c Ultimate / Ultimate 64</option>
            <option value="dtv">DTV</option>
            <option value="thec64">TheC64 Mini/Maxi</option>
            <option value="c128">C128</option>
            <option value="c16">C16</option>
            <option value="plus4">C116/Plus/4</option>
            <option value="pet">PET</option>
            <option value="cbm2">CBM2</option>
            <option value="cx16">CX16 / OtterX</option>
            <option value="foenix">Foenix</option>
          </select>
        </div>
        <div className="p-4">
          <label className="text-sm text-neutral-500 block mb-2">Video</label>
          <select
            value={config.host?.video?.split('|')[0] || 'ntsc'}
            onChange={(e) => updateSetting(['host', 'video'], e.target.value)}
            className="w-full px-3 py-2 border border-neutral-300 rounded-lg"
          >
            <option value="ntsc">NTSC</option>
            <option value="pal">PAL</option>
          </select>
        </div>
        <div className="p-4">
          <label className="text-sm text-neutral-500 block mb-2">Kernal</label>
          <select
            value={config.host?.kernal?.split('|')[0] || 'stock'}
            onChange={(e) => updateSetting(['host', 'kernal'], e.target.value)}
            className="w-full px-3 py-2 border border-neutral-300 rounded-lg"
          >
            <option value="stock">Stock</option>
            <option value="jiffydos">JiffyDOS</option>
            <option value="dolphindos">DolphinDOS</option>
            <option value="speeddos">SpeedDOS</option>
          </select>
        </div>
        <div className="p-4">
          <label className="text-sm text-neutral-500 block mb-2">BASIC</label>
          <select
            value={config.host?.basic?.split('|')[0] || '2'}
            onChange={(e) => updateSetting(['host', 'basic'], e.target.value)}
            className="w-full px-3 py-2 border border-neutral-300 rounded-lg"
          >
            <option value="2">BASIC 2</option>
            <option value="3">BASIC 3</option>
            <option value="7">BASIC 7</option>
            <option value="10">BASIC 10</option>
          </select>
        </div>
      </div>

      {/* ── IEC Serial Devices ── */}
      <div className="flex items-center justify-between mb-3">
        <h2 className="text-sm text-neutral-500 flex items-center gap-2"><Cable className="w-4 h-4" /> IEC Serial Devices</h2>
        <button
          onClick={rescanBus}
          disabled={isScanning}
          className="flex items-center gap-2 px-3 py-1.5 bg-blue-600 text-white text-sm rounded-lg disabled:opacity-50"
        >
          <RefreshCw className={`w-4 h-4 ${isScanning ? 'animate-spin' : ''}`} />
          Rescan Bus
        </button>
      </div>

      <div className="space-y-2">
        {displayDevices.map((device) => (
          <div
            key={device.id}
            className="w-full bg-white border border-neutral-200 rounded-lg p-4 flex items-center gap-3"
          >
            {/* Icon */}
            <div className={`flex-shrink-0 ${iconColor(device)}`}>
              {getDeviceIcon(device.type)}
            </div>

            {/* Info — clickable for virtual devices */}
            <button
              onClick={() => handleDeviceClick(device)}
              disabled={device.physical}
              className="flex-1 min-w-0 text-left disabled:cursor-default"
            >
              <div className="flex items-center gap-2 flex-wrap">
                <span className={!device.physical && !device.enabled ? 'text-neutral-400' : 'text-neutral-900'}>
                  {device.name || `Device ${device.number}`}
                </span>
                <span className="text-xs text-neutral-500 px-1.5 py-0.5 bg-neutral-100 rounded">
                  #{device.number}
                </span>
                {device.physical && (
                  <span className="text-xs text-green-700 px-1.5 py-0.5 bg-green-50 border border-green-200 rounded">
                    Physical
                  </span>
                )}
              </div>
              {(device.base_url || device.url) && (
                <div className="text-sm text-neutral-500 truncate mt-0.5">
                  {[device.base_url, device.url].filter(Boolean).join('')}
                </div>
              )}
              <div className="text-xs mt-1 flex items-center">
                {statusEl(device.deviceStatus)}
              </div>
            </button>

            {/* Controls */}
            <div className="flex items-center gap-2 flex-shrink-0">
              {!device.physical && (
                <>
                  <button
                    onClick={(e) => toggleDeviceEnabled(device, e)}
                    className={`relative w-11 h-6 rounded-full transition-colors ${
                      device.enabled ? 'bg-blue-600' : 'bg-neutral-300'
                    }`}
                  >
                    <div className={`absolute top-0.5 w-5 h-5 bg-white rounded-full transition-transform ${
                      device.enabled ? 'translate-x-5' : 'translate-x-0.5'
                    }`} />
                  </button>
                  <button onClick={() => handleDeviceClick(device)}>
                    <ChevronRight className="w-4 h-4 text-neutral-400" />
                  </button>
                </>
              )}
              <button
                onClick={(e) => { e.stopPropagation(); setActionDevice(device); }}
                className="p-2 rounded hover:bg-neutral-200 flex-shrink-0"
                title="Actions"
              >
                <MoreVertical className="w-4 h-4" />
              </button>
            </div>
          </div>
        ))}
      </div>

      {/* DeviceDetailOverlay — virtual devices only */}
      {selectedDeviceIndex !== null && (
        <DeviceDetailOverlay
          device={devices[selectedDeviceIndex]}
          config={config}
          setConfig={setConfig}
          onClose={handleCloseOverlay}
          onNavigate={handleNavigate}
          hasPrev={selectedDeviceIndex > 0}
          hasNext={selectedDeviceIndex < devices.length - 1}
        />
      )}

      {/* Action Dialog */}
      <Dialog open={actionDevice !== null} onOpenChange={open => !open && setActionDevice(null)}>
        <DialogContent className="max-w-sm">
          <DialogHeader>
            <DialogTitle>{actionDevice?.name || `Device ${actionDevice?.number}`}</DialogTitle>
            <DialogDescription>
              #{actionDevice?.number}
              {actionDevice?.physical
                ? ` · ${actionDevice.physicalModel} · Physical`
                : ' · Virtual'}
            </DialogDescription>
          </DialogHeader>
          {actionDevice && (
            <div className="flex flex-col gap-2">
              {getDeviceActions(actionDevice).map(action => (
                <button
                  key={action.label}
                  onClick={() => handleAction(action)}
                  className={`w-full text-left px-4 py-3 rounded border inline-flex items-center gap-3 ${
                    action.variant === 'danger'
                      ? 'border-red-200 hover:bg-red-50 text-red-700'
                      : action.variant === 'primary'
                      ? 'border-neutral-200 hover:bg-blue-50 hover:border-blue-300'
                      : 'border-neutral-200 hover:bg-neutral-50'
                  }`}
                >
                  <action.Icon className={`w-4 h-4 flex-shrink-0 ${
                    action.variant === 'danger' ? 'text-red-500' : 'text-neutral-500'
                  }`} />
                  <span>{action.label}</span>
                </button>
              ))}
            </div>
          )}
        </DialogContent>
      </Dialog>

      {/* ── Cassette ── */}
      <h2 className="text-sm text-neutral-500 pt-4 flex items-center gap-2"><CassetteTape className="w-4 h-4" /> Cassette</h2>
      <div className="bg-white border border-neutral-200 rounded-lg divide-y divide-neutral-200">
        <div className="p-4 flex items-center justify-between">
          <label className="text-sm text-neutral-500">Enabled</label>
          <button
            onClick={() => updateSetting(['cassette', 'enabled'], cassette.enabled ? 0 : 1)}
            className={`relative w-12 h-6 rounded-full transition-colors ${cassette.enabled ? 'bg-blue-600' : 'bg-neutral-300'}`}
          >
            <div className={`absolute top-0.5 w-5 h-5 bg-white rounded-full transition-transform ${cassette.enabled ? 'translate-x-6' : 'translate-x-0.5'}`} />
          </button>
        </div>
        <div className="p-4">
          <label className="text-sm text-neutral-500 block mb-2">URL</label>
          <div className="flex gap-2">
            <input
              type="text"
              value={cassette.url || ''}
              onChange={(e) => updateSetting(['cassette', 'url'], e.target.value)}
              className="flex-1 px-3 py-2 border border-neutral-300 rounded-lg"
            />
            <button
              onClick={() => setShowCassetteUrlBrowser(true)}
              className="px-3 py-2 border border-neutral-300 rounded-lg bg-neutral-50 hover:bg-neutral-100"
            >
              <FolderOpen className="w-5 h-5" />
            </button>
          </div>
        </div>
      </div>

      {showCassetteUrlBrowser && (
        <MediaBrowser
          currentPath={cassette.url || '/'}
          onSelect={(p) => updateSetting(['cassette', 'url'], p)}
          onClose={() => setShowCassetteUrlBrowser(false)}
        />
      )}

      {/* ── User Port ── */}
      <h2 className="text-sm text-neutral-500 pt-4 flex items-center gap-2"><Plug className="w-4 h-4" /> User Port</h2>
      <div className="bg-white border border-neutral-200 rounded-lg divide-y divide-neutral-200">
        <div className="p-4 flex items-center justify-between">
          <label className="text-sm text-neutral-500">User Port Enabled</label>
          <button
            onClick={() => updateSetting(['hardware', 'userport', 'enabled'], hardware.userport?.enabled ? 0 : 1)}
            className={`relative w-12 h-6 rounded-full transition-colors ${hardware.userport?.enabled ? 'bg-blue-600' : 'bg-neutral-300'}`}
          >
            <div className={`absolute top-0.5 w-5 h-5 bg-white rounded-full transition-transform ${hardware.userport?.enabled ? 'translate-x-6' : 'translate-x-0.5'}`} />
          </button>
        </div>
        <div className="p-4">
          <label className="text-sm text-neutral-500 block mb-2">User Port Mode</label>
          <select
            value={hardware.userport?.mode?.split('|')[0] || 'serial'}
            onChange={(e) => updateSetting(['hardware', 'userport', 'mode'], e.target.value)}
            className="w-full px-3 py-2 border border-neutral-300 rounded-lg"
          >
            <option value="serial">Serial</option>
            <option value="parallel">Parallel</option>
            <option value="wic64">WiC64</option>
            <option value="IEEE-488">IEEE-488</option>
          </select>
        </div>
      </div>
    </div>
  );
}
