import { useState, useEffect, useCallback, useMemo } from 'react';
import { createPortal } from 'react-dom';
import { ExcelPreview } from './ExcelPreview';
import { DocxPreview } from './DocxPreview';
import { PptxPreview } from './PptxPreview';
import { PdfPreview } from './PdfPreview';
import { HwpPreview } from './HwpPreview';
import { FilePreviewFallback } from './FilePreviewFallback';
import { openLinkOnRightMonitor } from '../../lib/dualMonitor';
import {
  fileDisplayName,
  getFilePreviewKind,
  resolvePreviewMime,
} from '../../lib/fileDisplay';
import { useFileBlobUrl } from '../../hooks/useFileBuffer';
import type { FileRecord, MilestoneLink } from '../../types';

interface ResultPreviewProps {
  files: FileRecord[];
  links: MilestoneLink[];
  hasSelectedStage: boolean;
}

function ImagePreview({
  fileId,
  fileName,
  mime,
  zoom,
}: {
  fileId: string;
  fileName: string;
  mime: string;
  zoom: number;
}) {
  const { blobUrl, loading, error } = useFileBlobUrl(fileId, mime);

  if (error || (!loading && !blobUrl)) {
    return <FilePreviewFallback fileId={fileId} fileName={fileName} error={error} />;
  }
  if (loading || !blobUrl) {
    return <FilePreviewFallback fileId={fileId} fileName={fileName} loading />;
  }

  return (
    <img
      src={blobUrl}
      alt={fileName}
      className="max-h-full max-w-full object-contain transition-transform duration-150"
      style={{ transform: `scale(${zoom})` }}
      draggable={false}
    />
  );
}

function VideoPreview({ fileId, fileName, mime }: { fileId: string; fileName: string; mime: string }) {
  const { blobUrl, loading, error } = useFileBlobUrl(fileId, mime);

  if (error || (!loading && !blobUrl)) {
    return <FilePreviewFallback fileId={fileId} fileName={fileName} error={error} />;
  }
  if (loading || !blobUrl) {
    return <FilePreviewFallback fileId={fileId} fileName={fileName} loading />;
  }

  return <video src={blobUrl} controls className="max-h-full max-w-full" title={fileName} />;
}

function TextPreview({ fileId, fileName }: { fileId: string; fileName: string }) {
  const { blobUrl, loading, error } = useFileBlobUrl(fileId, 'text/plain;charset=utf-8');

  if (error || (!loading && !blobUrl)) {
    return <FilePreviewFallback fileId={fileId} fileName={fileName} error={error} />;
  }
  if (loading || !blobUrl) {
    return <FilePreviewFallback fileId={fileId} fileName={fileName} loading />;
  }

  return <iframe src={blobUrl} title={fileName} className="h-full w-full border-0 bg-white" />;
}

export function ResultPreview({ files, links, hasSelectedStage }: ResultPreviewProps) {
  const [fileId, setFileId] = useState<string | null>(null);
  const [zoom, setZoom] = useState(1);
  const [fullscreen, setFullscreen] = useState(false);

  useEffect(() => {
    if (files.length > 0) {
      setFileId((prev) => (prev && files.some((f) => f.id === prev) ? prev : files[0].id));
    } else {
      setFileId(null);
    }
    setZoom(1);
  }, [files]);

  const activeFile = fileId ? files.find((f) => f.id === fileId) ?? null : null;
  const previewKind = activeFile ? getFilePreviewKind(activeFile) : null;
  const previewMime = activeFile ? resolvePreviewMime(activeFile) : '';

  const fileIndex = activeFile ? files.findIndex((f) => f.id === activeFile.id) : -1;
  const isImage = previewKind === 'image';

  const goFile = useCallback(
    (delta: number) => {
      if (files.length === 0 || fileIndex < 0) return;
      const next = (fileIndex + delta + files.length) % files.length;
      setFileId(files[next].id);
      setZoom(1);
    },
    [files, fileIndex],
  );

  const handleOpenLink = (link: MilestoneLink, index: number) => {
    void openLinkOnRightMonitor(link.url, `eene_link_${index}`);
  };

  const headerTitle = activeFile ? fileDisplayName(activeFile) : '결과물 프리뷰';

  const previewContent = useMemo(() => {
    if (!activeFile || !previewKind) return null;
    const label = fileDisplayName(activeFile);

    switch (previewKind) {
      case 'excel':
        return <ExcelPreview fileId={activeFile.id} fileName={label} />;
      case 'image':
        return (
          <ImagePreview fileId={activeFile.id} fileName={label} mime={previewMime} zoom={zoom} />
        );
      case 'video':
        return <VideoPreview fileId={activeFile.id} fileName={label} mime={previewMime} />;
      case 'pdf':
        return <PdfPreview fileId={activeFile.id} fileName={label} />;
      case 'docx':
        return <DocxPreview fileId={activeFile.id} fileName={label} />;
      case 'pptx':
        return <PptxPreview fileId={activeFile.id} fileName={label} />;
      case 'text':
        return <TextPreview fileId={activeFile.id} fileName={label} />;
      case 'hwp':
        return <HwpPreview fileId={activeFile.id} fileName={label} />;
      default:
        return (
          <FilePreviewFallback
            fileId={activeFile.id}
            fileName={label}
            message="이 형식은 미리보기를 지원하지 않습니다. 다운로드 후 확인해 주세요."
          />
        );
    }
  }, [activeFile, previewKind, previewMime, zoom]);

  const renderContent = () => {
    if (activeFile && previewContent) return previewContent;
    if (links.length > 0) {
      return (
        <p className="px-6 text-center text-xl text-white/40">
          우측 📎 버튼을 클릭하면 링크가 우측 모니터 새 창에서 열립니다
        </p>
      );
    }
    return (
      <p className="text-xl text-white/40">
        {hasSelectedStage ? '첨부된 결과물이 없습니다' : '단계를 선택하세요'}
      </p>
    );
  };

  const toolbar = (
    <div className="flex shrink-0 items-center justify-between gap-3 border-b border-white/10 px-5 py-2">
      <span className="min-w-0 truncate text-lg font-bold text-white/75">{headerTitle}</span>

      {links.length > 0 && (
        <div className="flex shrink-0 flex-wrap items-center justify-end gap-1.5">
          {links.map((link, i) => (
            <button
              key={link.url + i}
              type="button"
              title={`${link.label}\n${link.url}`}
              onClick={() => handleOpenLink(link, i)}
              className="flex h-8 w-8 items-center justify-center rounded-lg bg-white/10 text-base text-white/70 transition-colors hover:bg-sky-500 hover:text-white"
            >
              📎
            </button>
          ))}
        </div>
      )}
    </div>
  );

  const controls = activeFile && (
    <div className="absolute right-4 top-4 z-20 flex flex-col gap-1">
      <button
        type="button"
        title="전체 보기"
        onClick={() => setFullscreen(true)}
        className="flex h-9 w-9 items-center justify-center rounded-lg bg-black/50 text-sm font-bold text-white/80 hover:bg-black/70"
      >
        ⛶
      </button>
      {isImage && (
        <>
          <button
            type="button"
            title="확대"
            onClick={() => setZoom((z) => Math.min(3, +(z + 0.25).toFixed(2)))}
            className="flex h-9 w-9 items-center justify-center rounded-lg bg-black/50 text-lg font-bold text-white/80 hover:bg-black/70"
          >
            +
          </button>
          <button
            type="button"
            title="축소"
            onClick={() => setZoom((z) => Math.max(0.5, +(z - 0.25).toFixed(2)))}
            className="flex h-9 w-9 items-center justify-center rounded-lg bg-black/50 text-lg font-bold text-white/80 hover:bg-black/70"
          >
            −
          </button>
          <button
            type="button"
            title="원본 크기"
            onClick={() => setZoom(1)}
            className="flex h-9 w-9 items-center justify-center rounded-lg bg-black/50 text-xs font-bold text-white/80 hover:bg-black/70"
          >
            1:1
          </button>
        </>
      )}
    </div>
  );

  const navArrows = activeFile && files.length > 1 && (
    <>
      <button
        type="button"
        onClick={() => goFile(-1)}
        className="absolute left-4 top-1/2 z-10 flex h-10 w-10 -translate-y-1/2 items-center justify-center bg-black/40 text-xl text-white/70 hover:bg-black/60"
      >
        ‹
      </button>
      <button
        type="button"
        onClick={() => goFile(1)}
        className="absolute right-4 top-1/2 z-10 flex h-10 w-10 -translate-y-1/2 items-center justify-center bg-black/40 text-xl text-white/70 hover:bg-black/60"
      >
        ›
      </button>
    </>
  );

  const footer = activeFile && (
    <div className="shrink-0 border-t border-white/10 px-5 py-1.5 text-center text-sm text-white/40">
      {`${fileIndex + 1} / ${files.length} 파일`}
      {isImage && ` · ${Math.round(zoom * 100)}%`}
    </div>
  );

  return (
    <>
      <main className="flex min-h-0 flex-1 flex-col overflow-hidden bg-[#0f1419]">
        {toolbar}
        <div className="relative flex min-h-0 flex-1 items-center justify-center overflow-hidden">
          {renderContent()}
          {controls}
          {navArrows}
        </div>
        {footer}
      </main>

      {fullscreen && activeFile &&
        createPortal(
          <div className="fixed inset-0 z-[10000] flex flex-col bg-black/95">
            <div className="flex shrink-0 items-center justify-between border-b border-white/10 px-5 py-3">
              <span className="truncate text-lg font-bold text-white/75">{headerTitle}</span>
              <div className="flex items-center gap-2">
                {isImage && (
                  <>
                    <button
                      type="button"
                      onClick={() => setZoom((z) => Math.max(0.5, +(z - 0.25).toFixed(2)))}
                      className="rounded bg-white/10 px-3 py-1 text-sm font-bold text-white hover:bg-white/20"
                    >
                      −
                    </button>
                    <span className="min-w-[3rem] text-center text-sm text-white/60">
                      {Math.round(zoom * 100)}%
                    </span>
                    <button
                      type="button"
                      onClick={() => setZoom((z) => Math.min(3, +(z + 0.25).toFixed(2)))}
                      className="rounded bg-white/10 px-3 py-1 text-sm font-bold text-white hover:bg-white/20"
                    >
                      +
                    </button>
                  </>
                )}
                <button
                  type="button"
                  onClick={() => setFullscreen(false)}
                  className="rounded bg-white/10 px-4 py-1 text-sm font-bold text-white hover:bg-white/20"
                >
                  닫기
                </button>
              </div>
            </div>
            <div className="relative flex min-h-0 flex-1 items-center justify-center overflow-auto p-4">
              {renderContent()}
            </div>
            {files.length > 1 && (
              <>
                <button
                  type="button"
                  onClick={() => goFile(-1)}
                  className="fixed left-6 top-1/2 z-[10001] flex h-12 w-12 -translate-y-1/2 items-center justify-center bg-black/60 text-2xl text-white"
                >
                  ‹
                </button>
                <button
                  type="button"
                  onClick={() => goFile(1)}
                  className="fixed right-6 top-1/2 z-[10001] flex h-12 w-12 -translate-y-1/2 items-center justify-center bg-black/60 text-2xl text-white"
                >
                  ›
                </button>
              </>
            )}
          </div>,
          document.body,
        )}
    </>
  );
}
