import { X, ArrowLeft, ArrowRight, RotateCw, Plus, Globe, Maximize2, Minimize2, ShieldCheck, Lock, Camera, Scissors } from 'lucide-react';
import { useAppStore } from '../store';
import { useState, useRef, useEffect, useCallback } from 'react';
import { invoke } from '@tauri-apps/api/core';
import { listen } from '@tauri-apps/api/event';

const bookmarks = [
  { name: 'ArtStation', icon: '🎨', url: 'https://artstation.com' },
  { name: 'Pinterest', icon: '📌', url: 'https://pinterest.com' },
  { name: 'Unsplash', icon: '📷', url: 'https://unsplash.com' },
  { name: 'Sketchfab', icon: '📦', url: 'https://sketchfab.com' },
  { name: 'Google Images', icon: '🔍', url: 'https://images.google.com' },
  { name: 'PolyHaven', icon: '🌍', url: 'https://polyhaven.com' },
  { name: 'Anatomy360', icon: '🦴', url: 'https://anatomy360.info' },
  { name: 'Line of Action', icon: '🏃', url: 'https://line-of-action.com' },
];

let browserInitPromise: Promise<any> | null = null;
function ensureBrowserInit() {
  if (!browserInitPromise) {
    browserInitPromise = invoke<any>('browser_init', { layout: { x: 0, y: 0, width: 1, height: 1 } }).catch((err) => {
      console.error('[BrowserPanel] browser_init failed', err);
      browserInitPromise = null;
      return null;
    });
  }
  return browserInitPromise;
}

export const BrowserPanel = () => {
  const { isBrowserOpen, setIsBrowserOpen, isWhisperBrowser, setImages, pan, zoom } = useAppStore();
  const [url, setUrl] = useState('https://unsplash.com');
  const [isFullscreen, setIsFullscreen] = useState(false);
  const [canGoBack, setCanGoBack] = useState(false);
  const [canGoForward, setCanGoForward] = useState(false);
  const [activeTabId, setActiveTabId] = useState<string | null>(null);
  const [webviewVisible, setWebviewVisible] = useState(false);
  const [isBrowserReady, setIsBrowserReady] = useState(false);
  const [isCapturing, setIsCapturing] = useState(false);
  const [isSnipping, setIsSnipping] = useState(false);
  const [frozenFrame, setFrozenFrame] = useState<string | null>(null);
  const [snipStart, setSnipStart] = useState<{x:number;y:number} | null>(null);
  const [snipCurrent, setSnipCurrent] = useState<{x:number;y:number} | null>(null);
  const contentRef = useRef<HTMLDivElement>(null);
  const syncTimerRef = useRef<number | null>(null);

  const computeLayout = useCallback(() => {
    const el = contentRef.current;
    if (!el) return null;
    const rect = el.getBoundingClientRect();
    if (rect.width < 80 || rect.height < 80) return null;
    return { x: rect.left, y: rect.top, width: rect.width, height: rect.height };
  }, []);

  const hideWebview = useCallback(() => {
    if (syncTimerRef.current) window.clearTimeout(syncTimerRef.current);
    // Hard-hide all tabs, not just active tab. Native child webviews are independent
    // of the React shell and can otherwise remain visible after drawer close.
    invoke('browser_hide_all').catch(() => {
      invoke('browser_set_visible', { visible: false, layout: { x: 0, y: 0, width: 1, height: 1 } }).catch(() => {});
    });
    setWebviewVisible(false);
  }, []);

  const syncWebviewNow = useCallback(async () => {
    if (!isBrowserOpen || isSnipping) return;
    const layout = computeLayout();
    if (!layout) return;
    const snap = await ensureBrowserInit();
    if (snap?.active && !activeTabId) setActiveTabId(snap.active);
    try {
      await invoke('browser_set_visible', { visible: true, layout });
      setWebviewVisible(true);
    } catch (err) {
      console.error('[BrowserPanel] browser_set_visible failed', err);
    }
  }, [isBrowserOpen, isSnipping, computeLayout, activeTabId]);

  const scheduleSync = useCallback((delay = 0) => {
    if (syncTimerRef.current) window.clearTimeout(syncTimerRef.current);
    syncTimerRef.current = window.setTimeout(() => requestAnimationFrame(() => syncWebviewNow()), delay);
  }, [syncWebviewNow]);

  useEffect(() => {
    ensureBrowserInit().then((snap) => { if (snap?.active) setActiveTabId(snap.active); setIsBrowserReady(true); });
    return () => hideWebview();
  }, [hideWebview]);

  useEffect(() => {
    if (!isBrowserOpen) { hideWebview(); return; }
    scheduleSync(50);
    const timers = [160, 300, 450, 700, 1100].map(ms => window.setTimeout(() => scheduleSync(0), ms));
    return () => timers.forEach(t => window.clearTimeout(t));
  }, [isBrowserOpen, scheduleSync, hideWebview]);

  useEffect(() => {
    if (!isBrowserOpen) return;
    hideWebview();
    scheduleSync(80);
    const timers = [220, 420, 800].map(ms => window.setTimeout(() => scheduleSync(0), ms));
    return () => timers.forEach(t => window.clearTimeout(t));
  }, [isFullscreen, isWhisperBrowser, isBrowserOpen, hideWebview, scheduleSync]);

  useEffect(() => {
    const ro = new ResizeObserver(() => { if (isBrowserOpen && !isSnipping) scheduleSync(20); });
    if (contentRef.current) ro.observe(contentRef.current);
    const onResize = () => { if (isBrowserOpen && !isSnipping) scheduleSync(20); };
    window.addEventListener('resize', onResize);
    return () => { ro.disconnect(); window.removeEventListener('resize', onResize); };
  }, [isBrowserOpen, isSnipping, scheduleSync]);

  useEffect(() => {
    const unlisten = listen<any>('browser://tabs', (event) => {
      const snap = event.payload;
      const active = snap.tabs?.find((t: any) => t.id === snap.active);
      if (active) { setUrl(active.url || ''); setCanGoBack(Boolean(active.can_go_back)); setCanGoForward(Boolean(active.can_go_forward)); setActiveTabId(snap.active || null); }
    });
    return () => { unlisten.then(fn => fn()); };
  }, []);

  const navigate = async (targetUrl: string) => { const snap = await ensureBrowserInit(); const tabId = activeTabId || snap?.active; if (tabId) invoke('tab_navigate', { tabId, url: targetUrl }).catch(console.error); };
  const goBack = () => { if (activeTabId) invoke('tab_back', { tabId: activeTabId }).catch(() => {}); };
  const goForward = () => { if (activeTabId) invoke('tab_forward', { tabId: activeTabId }).catch(() => {}); };
  const reload = () => { if (activeTabId) invoke('tab_reload', { tabId: activeTabId }).catch(() => {}); };
  const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); navigate(url); };

  function addCapturedImage(dataUrl: string, w: number, h: number) {
    const ratio = Math.max(0.1, w / h); const tw = Math.min(w, 800);
    setImages(prev => [...prev, { id: crypto.randomUUID(), url: dataUrl, sourceUrl: url, x: (-pan.x + window.innerWidth / 2 - tw / 2) / zoom, y: (-pan.y + window.innerHeight / 2 - (tw / ratio) / 2) / zoom, width: Math.round(tw), height: Math.round(tw / ratio), aspectRatio: ratio }]);
  }

  const captureViewport = async () => { const layout = computeLayout(); if (!layout || isCapturing) return; setIsCapturing(true); try { const dataUrl = await invoke<string>('browser_capture_viewport', { layout }); addCapturedImage(dataUrl, layout.width, layout.height); } catch (err) { console.error('[BrowserPanel] viewport capture failed', err); } finally { setIsCapturing(false); } };
  const startSnip = async () => { const layout = computeLayout(); if (!layout || isCapturing || isSnipping) return; setIsCapturing(true); try { const frame = await invoke<string>('browser_capture_viewport', { layout }); hideWebview(); setFrozenFrame(frame); setIsSnipping(true); } catch (err) { console.error('[BrowserPanel] snip prep failed', err); } finally { setIsCapturing(false); } };
  const cancelSnip = () => { setIsSnipping(false); setFrozenFrame(null); setSnipStart(null); setSnipCurrent(null); scheduleSync(0); };
  const onSnipDown = (e: React.PointerEvent) => { const r = e.currentTarget.getBoundingClientRect(); setSnipStart({x:e.clientX-r.left,y:e.clientY-r.top}); setSnipCurrent({x:e.clientX-r.left,y:e.clientY-r.top}); };
  const onSnipMove = (e: React.PointerEvent) => { if (!snipStart) return; const r = e.currentTarget.getBoundingClientRect(); setSnipCurrent({x:e.clientX-r.left,y:e.clientY-r.top}); };
  const onSnipUp = (e: React.PointerEvent) => { if (!snipStart || !snipCurrent || !frozenFrame) { cancelSnip(); return; } const r = e.currentTarget.getBoundingClientRect(); const ex=e.clientX-r.left, ey=e.clientY-r.top; const sx=Math.min(snipStart.x,ex), sy=Math.min(snipStart.y,ey); const sw=Math.abs(ex-snipStart.x), sh=Math.abs(ey-snipStart.y); if (sw<20||sh<20){cancelSnip();return;} const img=new Image(); img.onload=()=>{const scaleX=img.width/r.width, scaleY=img.height/r.height; const canvas=document.createElement('canvas'); canvas.width=Math.round(sw*scaleX); canvas.height=Math.round(sh*scaleY); const ctx=canvas.getContext('2d'); if(ctx){ctx.drawImage(img,Math.round(sx*scaleX),Math.round(sy*scaleY),canvas.width,canvas.height,0,0,canvas.width,canvas.height); addCapturedImage(canvas.toDataURL('image/png'),sw,sh);} cancelSnip();}; img.onerror=cancelSnip; img.src=frozenFrame; };
  useEffect(() => { if (!isSnipping) return; const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') cancelSnip(); }; window.addEventListener('keydown', onKey); return () => window.removeEventListener('keydown', onKey); }, [isSnipping]);

  const widthClass = isFullscreen ? 'w-[100vw]' : isWhisperBrowser ? 'w-[320px] min-w-[280px]' : 'w-[50vw] min-w-[400px] max-w-[700px]';

  return (
    <div className={`absolute right-0 top-0 h-full bg-[#1C1C1E] shadow-2xl flex flex-col z-[60] transform transition-transform duration-[350ms] ease-[cubic-bezier(0.16,1,0.3,1)] ${isBrowserOpen ? 'translate-x-0' : 'translate-x-full'} ${widthClass}`}>
      <div className="flex flex-col bg-[#1C1C1E] z-10 px-4 pt-4 pb-2 shrink-0">
        <div className="flex items-center gap-2 mb-3">
          <div className="flex items-center gap-0.5"><button onClick={goBack} disabled={!canGoBack} className={`w-8 h-8 flex items-center justify-center rounded-md transition-colors ${canGoBack ? 'text-[#A0A0A0] hover:text-white hover:bg-white/5' : 'text-[#404040] cursor-default'}`}><ArrowLeft size={16} /></button><button onClick={goForward} disabled={!canGoForward} className={`w-8 h-8 flex items-center justify-center rounded-md transition-colors ${canGoForward ? 'text-[#A0A0A0] hover:text-white hover:bg-white/5' : 'text-[#404040] cursor-default'}`}><ArrowRight size={16} /></button><button onClick={reload} className="w-8 h-8 flex items-center justify-center text-[#A0A0A0] hover:text-white rounded-md hover:bg-white/5"><RotateCw size={14} /></button></div>
          <form onSubmit={handleSubmit} className="flex-1 relative flex items-center bg-black/40 rounded-lg border border-white/5 focus-within:border-[#0A84FF]/40 transition-colors"><div className="absolute left-3 flex items-center gap-1.5 pointer-events-none"><ShieldCheck size={13} className="text-emerald-500" /><Lock size={12} className="text-[#808080]" /></div><input type="text" value={url} onChange={e => setUrl(e.target.value)} className="w-full bg-transparent text-[#E0E0E0] pl-14 pr-8 py-2 text-[13px] outline-none" spellCheck={false} />{url && <button type="button" onClick={() => setUrl('')} className="absolute right-2.5 text-[#808080] hover:text-white"><X size={14} /></button>}</form>
          <div className="flex items-center gap-0.5 ml-1"><button onClick={startSnip} disabled={isCapturing || isSnipping} className={`w-8 h-8 flex items-center justify-center rounded-md transition-colors ${isSnipping ? 'bg-[#FFD60A]/20 text-[#FFD60A]' : 'text-[#A0A0A0] hover:text-[#FFD60A] hover:bg-white/5'} ${isCapturing ? 'opacity-50 cursor-not-allowed' : ''}`} title="Area Snip"><Scissors size={16} /></button><button onClick={captureViewport} disabled={isCapturing} className={`w-8 h-8 flex items-center justify-center rounded-md transition-colors text-[#A0A0A0] hover:text-[#0A84FF] hover:bg-white/5 ${isCapturing ? 'opacity-50 cursor-not-allowed' : ''}`} title="Full Web Clip"><Camera size={16} className={isCapturing ? 'animate-pulse' : ''} /></button><button onClick={() => setIsFullscreen(!isFullscreen)} className="w-8 h-8 flex items-center justify-center text-[#A0A0A0] hover:text-white rounded-md hover:bg-white/5">{isFullscreen ? <Minimize2 size={16} /> : <Maximize2 size={16} />}</button><button onClick={() => setIsBrowserOpen(false)} className="w-8 h-8 flex items-center justify-center text-[#A0A0A0] hover:text-white rounded-md hover:bg-white/5"><X size={18} /></button></div>
        </div>
        {!isWhisperBrowser && <div className="flex items-center gap-2 overflow-x-auto pb-2 hide-scrollbar">{bookmarks.map((bm, i) => <button key={i} onClick={() => navigate(bm.url)} className="flex items-center gap-1.5 px-3 py-1.5 bg-white/5 hover:bg-white/10 border border-white/5 rounded-md text-[11px] font-medium text-white whitespace-nowrap transition-colors"><span>{bm.icon}</span><span>{bm.name}</span></button>)}</div>}
      </div>
      <div ref={contentRef} className="flex-1 bg-[#0A0A0B] relative overflow-hidden">
        {!webviewVisible && <div className="absolute inset-0 flex items-center justify-center pointer-events-none"><div className="text-center text-[#404040]"><Globe size={28} className="mx-auto mb-2 opacity-30 animate-pulse" /><p className="text-[11px]">{isBrowserReady ? 'Positioning browser...' : 'Starting browser...'}</p></div></div>}
        {isSnipping && frozenFrame && <div className="absolute inset-0 z-[100] cursor-crosshair select-none" onPointerDown={onSnipDown} onPointerMove={onSnipMove} onPointerUp={onSnipUp} onPointerCancel={cancelSnip}><img src={frozenFrame} className="absolute inset-0 w-full h-full object-fill pointer-events-none" draggable={false} /><div className="absolute inset-0 bg-black/25 pointer-events-none" />{snipStart && snipCurrent && <div className="absolute border-2 border-dashed border-white/90" style={{ left: Math.min(snipStart.x, snipCurrent.x), top: Math.min(snipStart.y, snipCurrent.y), width: Math.abs(snipCurrent.x - snipStart.x), height: Math.abs(snipCurrent.y - snipStart.y), boxShadow: '0 0 0 9999px rgba(0,0,0,0.5)' }} />}<div className="absolute top-4 left-1/2 -translate-x-1/2 bg-[#FFD60A] text-black text-xs font-bold px-3 py-1.5 rounded-full shadow-lg pointer-events-none">Drag to select area • Esc to cancel</div></div>}
      </div>
    </div>
  );
};
