import { useState, useEffect, useCallback, useRef } from 'react';
import type { ViewerSettings } from '../types';
import type { ChapterData } from '../types';
import { MangaPage } from './MangaPage';
import { ViewerToolbar } from './ViewerToolbar';
import { getCurrentWindow } from '@tauri-apps/api/window';
import { SettingsPanel } from './SettingsPanel';

interface MangaViewerProps {
  chapter: ChapterData;
  currentUrl: string;
  settings: ViewerSettings;
  onSettingsChange: (s: Partial<ViewerSettings>) => void;
  onNavigate: (url: string | null) => void;
  onGoHome: () => void;
  fetchImage: (url: string, referer: string) => Promise<string>;
  isNavigating: boolean;
  navError: string | null;
  needsAttention: boolean;
}

function buildSlots(images: string[], offset: number): Array<string[]> {
  const slots: Array<string[]> = [];
  let i = 0;

  // Pages before offset: single
  while (i < offset && i < images.length) {
    slots.push([images[i]]);
    i++;
  }

  // Remaining pages: pairs in natural order [Page N, Page N+1]
  while (i < images.length) {
    if (i + 1 < images.length) {
      slots.push([images[i], images[i + 1]]);
      i += 2;
    } else {
      slots.push([images[i]]);
      i++;
    }
  }

  return slots;
}

export function MangaViewer({
  chapter,
  currentUrl,
  settings,
  onSettingsChange,
  onNavigate,
  onGoHome,
  fetchImage,
  isNavigating,
  navError,
  needsAttention,
}: MangaViewerProps) {
  const [slotIndex, setSlotIndex] = useState(0);
  const [showToolbar, setShowToolbar] = useState(true);
  const [showSettings, setShowSettings] = useState(false);
  const [isFullscreen, setIsFullscreen] = useState(false);
  const [dismissNavError, setDismissNavError] = useState(false);
  const [boundaryWarning, setBoundaryWarning] = useState<'first' | 'last' | null>(null);
  const toolbarTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
  const containerRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    setDismissNavError(false);
    if (!navError) return;
    const t = setTimeout(() => setDismissNavError(true), 6000);
    return () => clearTimeout(t);
  }, [navError]);


  useEffect(() => {
    const handleFullscreenChange = () => {
      setIsFullscreen(!!document.fullscreenElement);
    };
    document.addEventListener('fullscreenchange', handleFullscreenChange);
    return () => document.removeEventListener('fullscreenchange', handleFullscreenChange);
  }, []);

  const slots =
    settings.mode === 'spread'
      ? buildSlots(chapter.images, settings.spreadStartOffset)
      : chapter.images.map((img) => [img]);

  const totalSlots = slots.length;
  const currentSlot = slots[slotIndex] ?? [];

  // Compute global page numbers for display
  const firstPageNum = slotIndex === 0
    ? (settings.mode === 'spread' ? 0 : 0)
    : slots.slice(0, slotIndex).reduce((acc, s) => acc + s.length, 0);

  const displayPage = firstPageNum + 1;
  const totalPages = chapter.images.length;

  // Reset state on new chapter
  useEffect(() => {
    setSlotIndex(0);
    setShowSettings(false);
    setBoundaryWarning(null);
  }, [currentUrl]);

  // Preload all images in the background so page turns are instant
  useEffect(() => {
    if (!chapter.images.length) return;
    let cancelled = false;
    const ref = new URL(currentUrl).origin;
    // Fire off all fetches concurrently; fetchImage caches results
    // so subsequent MangaPage renders will get instant cache hits.
    chapter.images.forEach((imgUrl) => {
      if (!cancelled) {
        fetchImage(imgUrl, ref).catch(() => {}); // swallow errors – page will retry on its own
      }
    });
    return () => { cancelled = true; };
  }, [chapter.images, currentUrl, fetchImage]);

  const goNext = useCallback(() => {
    if (slotIndex < totalSlots - 1) {
      setSlotIndex((i) => i + 1);
      setBoundaryWarning(null);
    } else if (chapter.next_chapter) {
      if (boundaryWarning === 'last') {
        onNavigate(chapter.next_chapter);
      } else {
        setBoundaryWarning('last');
      }
    }
  }, [slotIndex, totalSlots, chapter.next_chapter, boundaryWarning, onNavigate]);

  const goPrev = useCallback(() => {
    if (slotIndex > 0) {
      setSlotIndex((i) => i - 1);
      setBoundaryWarning(null);
    } else if (chapter.prev_chapter) {
      if (boundaryWarning === 'first') {
        onNavigate(chapter.prev_chapter);
      } else {
        setBoundaryWarning('first');
      }
    }
  }, [slotIndex, chapter.prev_chapter, boundaryWarning, onNavigate]);

  // Keyboard navigation
  useEffect(() => {
    const handler = (e: KeyboardEvent) => {
      if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) return;
      switch (e.key) {
        case 'ArrowRight':
          e.preventDefault();
          goNext();
          break;
        case 'ArrowLeft':
          e.preventDefault();
          goPrev();
          break;
        case 'f':
        case 'F':
          toggleFullscreen();
          break;
        case 's':
        case 'S':
          setShowSettings((v) => !v);
          break;
        case 'Escape':
          if (showSettings) setShowSettings(false);
          break;
      }
    };
    window.addEventListener('keydown', handler);
    return () => window.removeEventListener('keydown', handler);
  }, [goNext, goPrev, showSettings, settings.direction, toggleFullscreen]);

  // Auto-hide toolbar
  const resetToolbarTimer = useCallback(() => {
    setShowToolbar(true);
    if (toolbarTimer.current) clearTimeout(toolbarTimer.current);
    toolbarTimer.current = setTimeout(() => {
      if (!showSettings) setShowToolbar(false);
    }, 3000);
  }, [showSettings]);

  useEffect(() => {
    resetToolbarTimer();
    return () => {
      if (toolbarTimer.current) clearTimeout(toolbarTimer.current);
    };
  }, []);

  const toggleFullscreen = useCallback(async () => {
    try {
      const win = getCurrentWindow();
      const current = await win.isFullscreen();
      const nextState = !current;
      await win.setFullscreen(nextState);
      setIsFullscreen(nextState);
    } catch (e) {
      console.error('Failed to toggle fullscreen', e);
    }
  }, []);

  const bgMap = {
    black: '#000000',
    white: '#f8f8f8',
    gray: '#1a1a1a',
  };

  // Click zones: left third = prev, right third = next, middle = toggle toolbar
  const handleZoneClick = (e: React.MouseEvent) => {
    const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();
    const x = e.clientX - rect.left;
    const third = rect.width / 3;
    if (x < third) {
      goPrev();
    } else if (x > third * 2) {
      goNext();
    } else {
      setShowToolbar((v) => !v);
    }
  };

  const referer = new URL(currentUrl).origin;

  return (
    <div
      ref={containerRef}
      className="manga-viewer"
      style={{ backgroundColor: bgMap[settings.backgroundColor] }}
      onMouseMove={resetToolbarTimer}
      onClick={handleZoneClick}
    >
      {/* Toolbar */}
      <ViewerToolbar
        visible={showToolbar}
        title={chapter.title}
        currentPage={displayPage}
        totalPages={totalPages}
        currentSlot={slotIndex}
        totalSlots={totalSlots}
        hasPrev={slotIndex > 0 || !!chapter.prev_chapter}
        hasNext={slotIndex < totalSlots - 1 || !!chapter.next_chapter}
        settings={settings}
        isFullscreen={isFullscreen}
        onPrevChapter={() => onNavigate(chapter.prev_chapter)}
        onNextChapter={() => onNavigate(chapter.next_chapter)}
        onToggleSettings={() => setShowSettings((v) => !v)}
        onToggleFullscreen={toggleFullscreen}
        onGoHome={onGoHome}
        onSettingsChange={onSettingsChange}
      />

      {/* Page navigation arrows (floating in center) */}
      <button
        className={`page-nav-btn page-nav-prev ${!(slotIndex > 0 || !!chapter.prev_chapter) ? 'disabled' : ''}`}
        onClick={(e) => { e.stopPropagation(); goPrev(); }}
        disabled={!(slotIndex > 0 || !!chapter.prev_chapter)}
        title="이전 페이지 (←)"
        style={{ opacity: showToolbar ? 1 : 0, pointerEvents: showToolbar ? 'auto' : 'none' }}
      >
        <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
          <path d="M15 18l-6-6 6-6"/>
        </svg>
      </button>
      <button
        className={`page-nav-btn page-nav-next ${!(slotIndex < totalSlots - 1 || !!chapter.next_chapter) ? 'disabled' : ''}`}
        onClick={(e) => { e.stopPropagation(); goNext(); }}
        disabled={!(slotIndex < totalSlots - 1 || !!chapter.next_chapter)}
        title="다음 페이지 (→)"
        style={{ opacity: showToolbar ? 1 : 0, pointerEvents: showToolbar ? 'auto' : 'none' }}
      >
        <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
          <path d="M9 18l6-6-6-6"/>
        </svg>
      </button>

      {/* Full-screen Loading Overlay */}
      {isNavigating && (
        <div className="full-loading-overlay" onClick={(e) => e.stopPropagation()}>
          <div className="loading-spinner-large" />
          <div className="loading-text">
            {needsAttention
              ? '열린 창에서 사이트 인증(캡차/로그인 등)을 완료해주세요.'
              : '챕터를 불러오는 중...'}
          </div>
        </div>
      )}

      {/* Boundary Warning */}
      {boundaryWarning && (
        <div className="boundary-warning">
          {boundaryWarning === 'first' ? '첫 페이지입니다. 이전 화로 이동하려면 한 번 더 누르세요.' : '마지막 페이지입니다. 다음 화로 이동하려면 한 번 더 누르세요.'}
        </div>
      )}

      {/* Error Toast */}
      {!isNavigating && navError && !dismissNavError && (
        <div className="nav-status-toast" onClick={(e) => e.stopPropagation()}>
          <div className="error-banner">
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
              <circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/>
            </svg>
            <span>{navError}</span>
          </div>
        </div>
      )}



      {/* Page display */}
      <div
        className={`viewer-stage ${settings.mode === 'spread' && currentSlot.length === 2 ? 'spread-mode' : 'single-mode'}`}
        style={{ direction: settings.direction }}
      >
        {currentSlot.map((imgUrl, idx) => (
          <MangaPage
            key={imgUrl + idx}
            imageUrl={imgUrl}
            referer={referer}
            fitMode={settings.fitMode}
            fetchImage={fetchImage}
          />
        ))}
      </div>

      {/* Click zone overlays (visual hints) */}
      <div className="click-zones" aria-hidden>
        <div className="zone zone-prev" />
        <div className="zone zone-middle" />
        <div className="zone zone-next" />
      </div>

      {/* Page progress bar */}
      <div className="progress-bar-container">
        <div
          className="progress-bar"
          style={{ width: `${((slotIndex + 1) / totalSlots) * 100}%` }}
        />
      </div>

      {/* Settings panel */}
      {showSettings && (
        <SettingsPanel
          settings={settings}
          totalImages={chapter.images.length}
          onChange={onSettingsChange}
          onClose={() => setShowSettings(false)}
        />
      )}
    </div>
  );
}
