
import React, { useState, useEffect, useRef, useCallback } from 'react';
import { ConnectionPanel } from './components/ConnectionPanel';
import { InventoryPanel } from './components/InventoryPanel';
import { SettingsPanel } from './components/SettingsPanel';
import { MemoryPanel } from './components/MemoryPanel';
import { QuickTestPanel } from './components/QuickTestPanel';
import { ConnectionStatus, TagData, ReaderCommand, FrequencyBand, MemoryBank, LogEntry, SerialPort, ReaderInfo, QuickTestConfig } from './types';
import { RfidProtocol } from './services/rfidService';
import { calculateCRC16, bytesToHexString, hexStringToBytes, hexToAscii, asciiToHex } from './utils/crc16';
import { Terminal, Settings, LayoutDashboard, Database, Zap, ChevronUp, ChevronDown, Wifi, WifiOff } from 'lucide-react';

const App: React.FC = () => {
  // Serial State
  const [port, setPort] = useState<SerialPort | null>(null);
  const [status, setStatus] = useState<ConnectionStatus>(ConnectionStatus.DISCONNECTED);
  const [baudRate, setBaudRate] = useState(57600);
  const [address, setAddress] = useState(0xFF); // Broadcast address default

  // App State - Set Quick Test as Default
  const [activeTab, setActiveTab] = useState<'inventory' | 'settings' | 'memory' | 'quicktest'>('quicktest');
  const [logs, setLogs] = useState<LogEntry[]>([]);
  const [tags, setTags] = useState<TagData[]>([]);
  const [isScanning, setIsScanning] = useState(false);
  const [readerInfo, setReaderInfo] = useState<ReaderInfo | null>(null);
  const [readResult, setReadResult] = useState<string | null>(null);

  // Log Visibility State
  const [isLogExpanded, setIsLogExpanded] = useState(false);

  // Quick Action Config (Persisted in localStorage)
  const [quickTestConfig, setQuickTestConfig] = useState<QuickTestConfig>(() => {
    const saved = localStorage.getItem('quickTestConfig');
    return saved ? JSON.parse(saved) : { length: 3, format: 'ascii' };
  });

  // Quick Action State
  const [pendingQuickAction, setPendingQuickAction] = useState<'read' | 'write' | null>(null);
  const [quickWriteData, setQuickWriteData] = useState<string>(""); // Actual Hex data to write (State for UI consistency)
  const [quickWriteInput, setQuickWriteInput] = useState<string>(""); // UI Input state

  // References for streams and state tracking
  const readerRef = useRef<ReadableStreamDefaultReader<Uint8Array> | null>(null);
  const writerRef = useRef<WritableStreamDefaultWriter<Uint8Array> | null>(null);
  const scanIntervalRef = useRef<number | null>(null);
  const isConnectedRef = useRef<boolean>(false);

  // Track if a Quick Write is in progress to trigger auto-read verification
  const performingQuickWriteRef = useRef<boolean>(false);
  const quickWriteDataRef = useRef<string>(""); // Ref to hold write data for verification inside async loop
  const verificationRetriesRef = useRef<number>(0); // Track retries

  // Track which EPC is currently being queried for TID
  const currentTidReadEpc = useRef<string | null>(null);

  // Stale Closure Fix: Ref to hold the latest processFrame function
  const processFrameRef = useRef<(frame: Uint8Array) => void>(() => { });

  const addLog = (type: LogEntry['type'], message: string, data?: string) => {
    setLogs(prev => [{
      id: Math.random().toString(36).substr(2, 9),
      timestamp: new Date(),
      type,
      message,
      data
    }, ...prev].slice(0, 100)); // Keep last 100 logs
  };

  const saveQuickTestConfig = (config: QuickTestConfig) => {
    setQuickTestConfig(config);
    localStorage.setItem('quickTestConfig', JSON.stringify(config));
    addLog('INFO', `Quick Test Settings Saved to Browser: Len=${config.length}, Fmt=${config.format}`);
    alert("Quick Test settings saved to browser storage.");
  };

  // Auto-read settings when connected (With Warm-up Sequence)
  useEffect(() => {
    if (status === ConnectionStatus.CONNECTED && port) {
      // Start a warm-up sequence to stabilize connection
      const warmup = async () => {
        // 1. Initial delay for hardware port opening
        await new Promise(r => setTimeout(r, 300));

        // 2. Send a "Sacrificial" command. 
        // Devices often error on the very first byte received after connection/power-up due to sync issues.
        // We send this to clear the pipe, expecting it might fail (silent retry).
        addLog('INFO', 'Initializing Handshake...');
        await sendCommand(ReaderCommand.GET_INFO);

        // 3. Wait for the error/response to clear
        await new Promise(r => setTimeout(r, 500));

        // 4. Send the actual Sync command
        addLog('INFO', 'Syncing Reader Info...');
        handleGetInfo();
      };

      warmup();
    }
  }, [status, port]);

  // Quick Action Logic: Watch tags list updates
  useEffect(() => {
    if (pendingQuickAction && tags.length > 0) {
      const targetTag = tags[0]; // Pick the first tag found
      const action = pendingQuickAction;
      const dataToWrite = quickWriteData;

      // 1. Stop Scanning immediately
      if (scanIntervalRef.current) {
        clearInterval(scanIntervalRef.current);
        scanIntervalRef.current = null;
        setIsScanning(false);
      }

      // 2. Clear pending state so we don't fire again
      setPendingQuickAction(null);
      setQuickWriteData("");

      // 3. Execute Memory Operation with small delay to ensure bus is clear
      setTimeout(() => {
        if (action === 'read') {
          addLog('INFO', `Quick Read detected tag: ${targetTag.epc}`);
          handleMemoryRead(MemoryBank.EPC, 2, quickTestConfig.length, "00000000", targetTag.epc);
        } else if (action === 'write') {
          // Set Flag to trigger verification read on success
          performingQuickWriteRef.current = true;
          verificationRetriesRef.current = 0; // Reset retries

          addLog('INFO', `Quick Write detected tag: ${targetTag.epc}`);
          handleMemoryWrite(MemoryBank.EPC, 2, dataToWrite, "00000000", targetTag.epc);
        }
      }, 200);
    }
  }, [tags, pendingQuickAction, quickWriteData, quickTestConfig]);

  const connectSerial = async () => {
    try {
      setStatus(ConnectionStatus.CONNECTING);
      // @ts-ignore
      const p = await navigator.serial.requestPort();
      await p.open({ baudRate });
      setPort(p);

      isConnectedRef.current = true;
      setStatus(ConnectionStatus.CONNECTED);

      addLog('INFO', `Connected to serial port at ${baudRate}`);
      startReading(p);
    } catch (err: any) {
      console.error(err);
      setStatus(ConnectionStatus.ERROR);
      addLog('ERROR', 'Failed to connect: ' + err.message);
    }
  };

  const disconnectSerial = async () => {
    if (scanIntervalRef.current) {
      clearInterval(scanIntervalRef.current);
      scanIntervalRef.current = null;
      setIsScanning(false);
    }
    isConnectedRef.current = false;
    try {
      if (readerRef.current) {
        await readerRef.current.cancel().catch(() => { });
        readerRef.current = null;
      }
      if (writerRef.current) {
        await writerRef.current.releaseLock();
        writerRef.current = null;
      }
      if (port) {
        await port.close();
        setPort(null);
      }
      setStatus(ConnectionStatus.DISCONNECTED);
      addLog('INFO', 'Disconnected');
    } catch (err: any) {
      addLog('ERROR', 'Error disconnecting: ' + err.message);
    }
  };

  // --- Serial I/O ---

  const startReading = async (p: SerialPort) => {
    if (!p.readable) return;

    while (p.readable && isConnectedRef.current) {
      const reader = p.readable.getReader();
      readerRef.current = reader;
      try {
        let buffer = new Uint8Array(0);

        while (true) {
          const { value, done } = await reader.read();
          if (done) break;

          if (value && value.length > 0) {
            addLog('INFO', 'RAW RX', bytesToHexString(value));

            const newBuffer = new Uint8Array(buffer.length + value.length);
            newBuffer.set(buffer);
            newBuffer.set(value, buffer.length);
            buffer = newBuffer;

            while (buffer.length > 0) {
              const lenByte = buffer[0];
              if (lenByte === 0) {
                buffer = buffer.slice(1);
                continue;
              }
              const totalFrameSize = lenByte + 1;

              if (buffer.length >= totalFrameSize) {
                const frame = buffer.slice(0, totalFrameSize);
                // Call the latest logic via Ref
                processFrameRef.current(frame);
                buffer = buffer.slice(totalFrameSize);
              } else {
                break;
              }
            }
          }
        }
      } catch (error) {
        console.error("Read Error:", error);
        if (isConnectedRef.current) {
          addLog('ERROR', 'Read Loop Error', String(error));
        }
        break;
      } finally {
        try {
          reader.releaseLock();
        } catch (e) { }
      }
    }
  };

  const sendCommand = async (cmd: ReaderCommand, data: number[] = []) => {
    if (!port || !port.writable) {
      addLog('ERROR', 'Port not writable or disconnected');
      return;
    }

    try {
      let targetAddr = address;
      if (address === 0xFF && readerInfo && readerInfo.address !== 0xFF) {
        targetAddr = readerInfo.address;
      }

      const frame = RfidProtocol.buildCommand(targetAddr, cmd, data);
      addLog('TX', `CMD: 0x${cmd.toString(16).toUpperCase()}`, bytesToHexString(frame));

      const writer = port.writable.getWriter();
      writerRef.current = writer;
      await writer.write(frame);
      writer.releaseLock();
    } catch (e: any) {
      addLog('ERROR', 'Send Failed', e.message);
    }
  };

  // --- Logic ---

  const processFrame = (frame: Uint8Array) => {
    try {
      if (frame.length < 4) {
        addLog('ERROR', 'Incomplete Frame', bytesToHexString(frame));
        return;
      }

      const len = frame[0];
      const addr = frame[1];
      const reCmd = frame[2];
      const status = frame[3];
      let data = frame.length > 6 ? frame.slice(4, frame.length - 2) : new Uint8Array(0);

      addLog('RX', `Cmd:0x${reCmd.toString(16).toUpperCase()} Stat:0x${status.toString(16).toUpperCase()}`, bytesToHexString(frame));

      if (status === 0x00) {
        if (reCmd === ReaderCommand.GET_INFO) {
          handleGetInfoResponse(data, addr);
        } else if (reCmd === ReaderCommand.READ_DATA_G2) {
          if (data.length > 0 && data[0] === 0x00) {
            data = data.slice(1);
          }
          const hexData = bytesToHexString(data);

          let displayData = hexData;
          if (quickTestConfig.format === 'ascii') {
            displayData = hexToAscii(hexData);
          }

          setReadResult(displayData);

          if (activeTab === 'quicktest') {
            setQuickWriteInput(displayData);
          }

          addLog('INFO', 'Memory Read Success', hexData);

          if (currentTidReadEpc.current) {
            const targetEpc = currentTidReadEpc.current;
            setTags(prev => prev.map(t =>
              t.epc === targetEpc ? { ...t, tid: hexData } : t
            ));
          }

          // === Verification Logic ===
          if (performingQuickWriteRef.current) {
            // Compare Read Data (Hex) with Expected Write Data (Hex)
            const normalize = (s: string) => s.replace(/[\s-]/g, '').toUpperCase();
            const readHex = normalize(hexData);
            const expectedHex = normalize(quickWriteDataRef.current);

            if (readHex === expectedHex) {
              addLog('INFO', 'VERIFICATION SUCCESS: Data matches written value.');
              performingQuickWriteRef.current = false;
              verificationRetriesRef.current = 0;
              alert("Quick Test Successful: Write verified.");
            } else {
              if (verificationRetriesRef.current < 5) {
                verificationRetriesRef.current += 1;
                addLog('WARN', `Verification Mismatch (${verificationRetriesRef.current}/5). Retrying read...`, `Read: ${readHex}, Exp: ${expectedHex}`);

                setTimeout(() => {
                  handleQuickRead();
                }, 500);
              } else {
                addLog('ERROR', 'VERIFICATION FAILED: Data mismatch after 5 attempts.');
                performingQuickWriteRef.current = false;
                verificationRetriesRef.current = 0;
                alert("Quick Test Failed: Verification mismatch after 5 attempts.");
              }
            }
          }

        } else if (reCmd === ReaderCommand.WRITE_DATA_G2) {
          addLog('INFO', 'Memory Write Success');

          if (performingQuickWriteRef.current) {
            addLog('INFO', 'Verifying written data in 0.5s...');
            setTimeout(() => {
              handleQuickRead();
            }, 500);
          }

        } else if (reCmd === ReaderCommand.WRITE_EPC_G2) {
          addLog('INFO', 'EPC Write Success (Cmd 0x04)');
        } else if (reCmd === ReaderCommand.SET_ACCESS_EPC_MATCH) {
          addLog('INFO', 'Tag Selected Successfully');
        }
      }
      else if (reCmd === ReaderCommand.INVENTORY_G2) {
        if (status === 0x01 || status === 0x02 || status === 0x03 || status === 0x04) {
          handleInventoryResponse(data);
        }
      } else {
        let errorDetail = RfidProtocol.getStatusDescription(status);
        if (status === 0xFC && data.length > 0) {
          errorDetail += ` - ${RfidProtocol.getTagErrorDescription(data[0])}`;
        }
        addLog('ERROR', `Command 0x${reCmd.toString(16).toUpperCase()} Failed`, errorDetail);

        if (reCmd === ReaderCommand.WRITE_DATA_G2 && performingQuickWriteRef.current) {
          performingQuickWriteRef.current = false;
          verificationRetriesRef.current = 0;
          addLog('ERROR', 'Quick Write Verification Cancelled due to Write Error');
          alert("Quick Test Failed during Write operation.");
        }
      }

    } catch (err) {
      console.error("Frame Process Error", err);
      addLog('ERROR', 'Frame Parse Error', bytesToHexString(frame));
    }
  };

  // Sync the latest processFrame to the ref so the async loop uses the latest closure
  useEffect(() => {
    processFrameRef.current = processFrame;
  });

  const handleInventoryResponse = (data: Uint8Array) => {
    if (data.length === 0) return;
    let numTags = data[0];
    let offset = 1;
    for (let i = 0; i < numTags; i++) {
      if (offset >= data.length) break;
      const epcLen = data[offset];
      if (offset + 1 + epcLen > data.length) break;
      const epcBytes = data.slice(offset + 1, offset + 1 + epcLen);
      const epcString = bytesToHexString(epcBytes);
      updateTag(epcString);
      offset += 1 + epcLen;
    }
  };

  const handleGetInfoResponse = (data: Uint8Array, sourceAddr: number) => {
    let version = '1.0';
    let protocol: ReaderInfo['protocol'] = 'EPCC1-G2';
    let power = 0;
    let band: FrequencyBand = FrequencyBand.US;

    if (data.length > 0) {
      const maj = data[0];
      const min = data.length > 1 ? data[1] : 0;
      version = `${maj}.${min.toString(16).toUpperCase().padStart(2, '0')}`;
    }

    if (data.length >= 8) {
      if (data[3] >= 0 && data[3] <= 4) band = data[3] as FrequencyBand;
      if (data.length > 6) power = data[6];
    } else {
      if (data.length > 2) power = data[2];
    }

    setReaderInfo({
      model: 'RRU9809',
      version: version,
      address: sourceAddr,
      power: power,
      minFreq: 0,
      maxFreq: 0,
      protocol: protocol,
      maxResponseTime: 0,
      band: band
    });

    addLog('INFO', 'Reader Info Parsed', `Ver:${version}, Pwr:${power}dBm`);
  };

  const updateTag = (epc: string) => {
    setTags(prev => {
      const existing = prev.find(t => t.epc === epc);
      if (existing) {
        return prev.map(t => t.epc === epc ? { ...t, count: t.count + 1, timestamp: Date.now() } : t);
      } else {
        return [...prev, { epc, count: 1, timestamp: Date.now() }];
      }
    });
  };

  // --- Operations ---

  const toggleScanning = useCallback(() => {
    if (isScanning) {
      if (scanIntervalRef.current) clearInterval(scanIntervalRef.current);
      scanIntervalRef.current = null;
      setIsScanning(false);
    } else {
      setIsScanning(true);
      const runScan = () => sendCommand(ReaderCommand.INVENTORY_G2, []);
      runScan();
      scanIntervalRef.current = window.setInterval(runScan, 500);
    }
  }, [isScanning, address]);

  const handleQuickRead = () => {
    if (status !== ConnectionStatus.CONNECTED) {
      if (!performingQuickWriteRef.current) {
        alert("Reader is not connected! Please connect via serial port first.");
      }
      return;
    }

    setReadResult(null);
    setTags([]);
    setPendingQuickAction('read');
    if (!isScanning) {
      toggleScanning();
    }
  };

  const handleQuickWrite = (inputValue: string) => {
    if (status !== ConnectionStatus.CONNECTED) {
      alert("Reader is not connected! Please connect via serial port first.");
      return;
    }

    let finalHexData = inputValue;
    if (quickTestConfig.format === 'ascii') {
      finalHexData = asciiToHex(inputValue);
    }

    // Store in State for UI
    setQuickWriteData(finalHexData);
    // Store in Ref for Async Logic
    quickWriteDataRef.current = finalHexData;

    setTags([]);
    setPendingQuickAction('write');
    if (!isScanning) {
      toggleScanning();
    }
  };

  const handleCancelQuickAction = () => {
    if (scanIntervalRef.current) {
      clearInterval(scanIntervalRef.current);
      scanIntervalRef.current = null;
    }
    setIsScanning(false);
    setPendingQuickAction(null);
    performingQuickWriteRef.current = false;
    verificationRetriesRef.current = 0;
    addLog('INFO', 'Quick Test Cancelled by user');
  };

  const clearTags = () => setTags([]);

  const handleGetInfo = async () => {
    addLog('INFO', 'Requesting Reader Info...');
    await sendCommand(ReaderCommand.GET_INFO);
  };

  const handleSetParameters = async (settings: {
    address: number;
    baudRate: number;
    power: number;
    minFreq: number;
    maxFreq: number;
    band: FrequencyBand;
  }) => {
    await sendCommand(ReaderCommand.SET_POWER, [settings.power]);
    if (settings.address !== address) {
      await sendCommand(ReaderCommand.SET_ADDRESS, [settings.address]);
      setAddress(settings.address);
    }
    addLog('INFO', 'Parameters update command sent');
  };

  const handleFactoryReset = async () => {
    addLog('INFO', 'Sending Factory Reset...');
  };

  const getEpcData = (epc: string) => {
    const bytes = hexStringToBytes(epc);
    if (!bytes) return { bytes: [], words: 0 };
    return {
      bytes: Array.from(bytes),
      words: Math.ceil(bytes.length / 2)
    };
  };

  const handleFetchTids = async () => {
    if (isScanning) {
      if (scanIntervalRef.current) clearInterval(scanIntervalRef.current);
      scanIntervalRef.current = null;
      setIsScanning(false);
    }
    if (tags.length === 0) return;

    addLog('INFO', 'Starting Batch TID Read...');
    for (const tag of tags) {
      currentTidReadEpc.current = tag.epc;
      const { bytes: epcBytes, words: epcWords } = getEpcData(tag.epc);
      if (epcBytes.length === 0) continue;

      const payload = [
        epcWords, ...epcBytes, MemoryBank.TID, 0, 6, 0, 0, 0, 0, 0, 0
      ];
      addLog('INFO', `Reading TID for ${tag.epc}...`);
      await sendCommand(ReaderCommand.READ_DATA_G2, payload);
      await new Promise(r => setTimeout(r, 100));
    }
    currentTidReadEpc.current = null;
    addLog('INFO', 'Batch TID Read Complete');
  };

  const handleMemoryRead = async (bank: MemoryBank, ptr: number, len: number, pwd: string, targetEpc: string) => {
    const { bytes: epcBytes, words: epcWords } = getEpcData(targetEpc);
    let pwdBytes = hexStringToBytes(pwd) || new Uint8Array([0, 0, 0, 0]);

    const payload = [
      epcWords, ...epcBytes, bank, ptr & 0xFF, len & 0xFF, ...Array.from(pwdBytes), 0, 0
    ];

    addLog('INFO', `Read Req: Bank ${bank}, Ptr ${ptr}, Len ${len}`);
    await sendCommand(ReaderCommand.READ_DATA_G2, payload);
  };

  const handleMemoryWrite = async (bank: MemoryBank, ptr: number, dataStr: string, pwd: string, targetEpc: string) => {
    const { bytes: epcBytes, words: epcWords } = getEpcData(targetEpc);
    let pwdBytes = hexStringToBytes(pwd) || new Uint8Array([0, 0, 0, 0]);
    const dataBytes = hexStringToBytes(dataStr);

    if (!dataBytes) {
      addLog('ERROR', 'Invalid Hex Data for Write');
      return;
    }

    const wNum = Math.ceil(dataBytes.length / 2);
    const payload = [
      wNum, epcWords, ...epcBytes, bank, ptr & 0xFF, ...Array.from(dataBytes), ...Array.from(pwdBytes), 0, 0
    ];

    addLog('INFO', `Write Req: Bank ${bank}, Ptr ${ptr}, Data ${dataStr}`);
    await sendCommand(ReaderCommand.WRITE_DATA_G2, payload);
  };

  const handleWriteEpc = async (newEpc: string, pwd: string) => {
    const { bytes: epcBytes, words: epcWords } = getEpcData(newEpc);
    if (epcWords === 0) {
      addLog('ERROR', 'Invalid EPC Data');
      return;
    }
    let pwdBytes = hexStringToBytes(pwd) || new Uint8Array([0, 0, 0, 0]);
    const payload = [epcWords, ...Array.from(pwdBytes), ...epcBytes];

    addLog('INFO', `Write EPC (0x04): ${newEpc}`);
    await sendCommand(ReaderCommand.WRITE_EPC_G2, payload);
  };

  const getLogHeightClass = () => {
    if (isLogExpanded) return 'h-96';
    if (activeTab === 'quicktest' || activeTab === 'settings') return 'h-12';
    return 'h-48';
  };

  return (
    <div className="flex h-screen bg-slate-100">
      {/* Sidebar */}
      <div className="hidden md:flex w-64 bg-white border-r border-slate-200 flex-col z-10">
        <div className="p-6 border-b border-slate-100">
          <h1 className="text-xl font-bold text-slate-800 flex items-center gap-2">
            <Database className="text-blue-600" />
            UHF Reader
          </h1>
          <p className="text-xs text-slate-400 mt-1">Web Serial Controller</p>
        </div>

        <div className="p-4 space-y-2 flex-1">
          <button
            onClick={() => setActiveTab('quicktest')}
            className={`w-full flex items-center gap-3 px-4 py-3 rounded-lg text-sm font-medium transition-colors ${activeTab === 'quicktest' ? 'bg-indigo-50 text-indigo-700' : 'text-slate-600 hover:bg-slate-50'
              }`}
          >
            <Zap className="w-5 h-5" /> Quick Test
          </button>
          <button
            onClick={() => setActiveTab('inventory')}
            className={`w-full flex items-center gap-3 px-4 py-3 rounded-lg text-sm font-medium transition-colors ${activeTab === 'inventory' ? 'bg-blue-50 text-blue-700' : 'text-slate-600 hover:bg-slate-50'
              }`}
          >
            <LayoutDashboard className="w-5 h-5" /> Inventory
          </button>
          <button
            onClick={() => setActiveTab('memory')}
            className={`w-full flex items-center gap-3 px-4 py-3 rounded-lg text-sm font-medium transition-colors ${activeTab === 'memory' ? 'bg-blue-50 text-blue-700' : 'text-slate-600 hover:bg-slate-50'
              }`}
          >
            <Database className="w-5 h-5" /> Read / Write
          </button>
          <button
            onClick={() => setActiveTab('settings')}
            className={`w-full flex items-center gap-3 px-4 py-3 rounded-lg text-sm font-medium transition-colors ${activeTab === 'settings' ? 'bg-blue-50 text-blue-700' : 'text-slate-600 hover:bg-slate-50'
              }`}
          >
            <Settings className="w-5 h-5" /> Settings
          </button>
        </div>

        <div className="p-4 border-t border-slate-100">
          <ConnectionPanel
            status={status}
            onConnect={connectSerial}
            onDisconnect={disconnectSerial}
            baudRate={baudRate}
            setBaudRate={setBaudRate}
            address={address}
            setAddress={setAddress}
          />
        </div>
      </div>

      {/* Main Content */}
      <div className="flex-1 flex flex-col overflow-hidden relative">
        {/* Mobile Top Navigation Bar */}
        <div className="md:hidden bg-white border-b border-slate-200 p-2 flex items-center justify-between shrink-0 overflow-x-auto">
          <div className="flex items-center gap-3 pr-4 border-r border-slate-100 mr-2 shrink-0">
            <div className="flex items-center gap-1">
              <Database className="text-blue-600 w-5 h-5" />
              <span className="font-bold text-slate-800 text-sm">UHF</span>
            </div>

            {/* Connection Status Indicator */}
            <button
              onClick={() => setActiveTab('settings')}
              className={`flex items-center gap-1 px-2 py-1 rounded-full text-xs font-medium transition-colors ${status === ConnectionStatus.CONNECTED
                  ? 'bg-emerald-50 text-emerald-600 border border-emerald-100'
                  : 'bg-red-50 text-red-600 border border-red-100 animate-pulse'
                }`}
            >
              {status === ConnectionStatus.CONNECTED ? <Wifi className="w-3 h-3" /> : <WifiOff className="w-3 h-3" />}
              <span>{status === ConnectionStatus.CONNECTED ? 'On' : 'Connect'}</span>
            </button>
          </div>
          <div className="flex items-center gap-1 flex-1 justify-around">
            <button
              onClick={() => setActiveTab('quicktest')}
              className={`p-2 rounded-lg transition-colors flex flex-col items-center justify-center gap-1 ${activeTab === 'quicktest' ? 'bg-indigo-50 text-indigo-700' : 'text-slate-600 hover:bg-slate-50'
                }`}
            >
              <Zap className="w-5 h-5" />
              <span className="text-[10px] font-medium leading-none">Quick</span>
            </button>
            <button
              onClick={() => setActiveTab('inventory')}
              className={`p-2 rounded-lg transition-colors flex flex-col items-center justify-center gap-1 ${activeTab === 'inventory' ? 'bg-blue-50 text-blue-700' : 'text-slate-600 hover:bg-slate-50'
                }`}
            >
              <LayoutDashboard className="w-5 h-5" />
              <span className="text-[10px] font-medium leading-none">Inv.</span>
            </button>
            <button
              onClick={() => setActiveTab('memory')}
              className={`p-2 rounded-lg transition-colors flex flex-col items-center justify-center gap-1 ${activeTab === 'memory' ? 'bg-blue-50 text-blue-700' : 'text-slate-600 hover:bg-slate-50'
                }`}
            >
              <Database className="w-5 h-5" />
              <span className="text-[10px] font-medium leading-none">R/W</span>
            </button>
            <button
              onClick={() => setActiveTab('settings')}
              className={`p-2 rounded-lg transition-colors flex flex-col items-center justify-center gap-1 ${activeTab === 'settings' ? 'bg-blue-50 text-blue-700' : 'text-slate-600 hover:bg-slate-50'
                }`}
            >
              <Settings className="w-5 h-5" />
              <span className="text-[10px] font-medium leading-none">Set</span>
            </button>
          </div>
        </div>
        <main className="flex-1 p-6 overflow-auto">
          {activeTab === 'inventory' && (
            <InventoryPanel
              tags={tags}
              isScanning={isScanning}
              onToggleScan={toggleScanning}
              onClear={clearTags}
              onFetchTids={handleFetchTids}
            />
          )}
          {activeTab === 'quicktest' && (
            <QuickTestPanel
              onQuickRead={handleQuickRead}
              onQuickWrite={handleQuickWrite}
              onCancel={handleCancelQuickAction}
              writeInput={quickWriteInput}
              onWriteInputChange={setQuickWriteInput}
              result={readResult}
              isPending={pendingQuickAction !== null}
              isScanning={isScanning}
              config={quickTestConfig}
            />
          )}
          {activeTab === 'memory' && (
            <MemoryPanel
              tags={tags}
              isScanning={isScanning}
              onScan={toggleScanning}
              onRead={handleMemoryRead}
              onWrite={handleMemoryWrite}
              onWriteEpc={handleWriteEpc}
              selectedEpc={tags.length > 0 ? tags[0].epc : ""}
              readResult={readResult}
            />
          )}
          {activeTab === 'settings' && (
            <SettingsPanel
              readerInfo={readerInfo}
              onGetInfo={handleGetInfo}
              onSetParameters={handleSetParameters}
              onFactoryReset={handleFactoryReset}
              quickTestConfig={quickTestConfig}
              onSaveQuickTestConfig={saveQuickTestConfig}
            />
          )}
        </main>

        {/* Log Terminal */}
        <div className={`${getLogHeightClass()} bg-white border-t border-slate-200 flex flex-col transition-all duration-300 ease-in-out`}>
          <div
            className="px-4 py-2 bg-slate-50 border-b border-slate-100 flex items-center justify-between cursor-pointer hover:bg-slate-100"
            onClick={() => setIsLogExpanded(!isLogExpanded)}
          >
            <div className="flex items-center gap-2 text-xs font-semibold text-slate-700 uppercase tracking-wider">
              <Terminal className="w-3 h-3" /> System Logs
            </div>
            <div>
              {isLogExpanded ? <ChevronDown className="w-4 h-4 text-slate-400" /> : <ChevronUp className="w-4 h-4 text-slate-400" />}
            </div>
          </div>

          <div className="flex-1 overflow-auto p-4 font-mono text-xs space-y-1 text-slate-600">
            {logs.length === 0 && <span className="text-slate-400 italic">No logs yet...</span>}
            {logs.map(log => (
              <div key={log.id} className="flex gap-2">
                <span className="text-slate-400">[{log.timestamp.toLocaleTimeString()}]</span>
                <span className={`font-bold ${log.type === 'TX' ? 'text-blue-600' :
                  log.type.includes('RX') ? 'text-emerald-600' :
                    log.type === 'ERROR' ? 'text-red-600' :
                      log.type === 'WARN' ? 'text-amber-600' : 'text-slate-700'
                  }`}>
                  {log.type}
                </span>
                <span className="text-slate-800">{log.message}</span>
                {log.data && <span className="text-slate-500 ml-2">{log.data}</span>}
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
};

export default App;
