"use client";

import React, { useState, useEffect } from "react";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { FileInfo } from "./types";
import { Download, X, AlertTriangle, FileText, Trash2, ExternalLink } from "lucide-react";
import { formatFileSize } from "@/lib/utils";
import { API_BASE_URL } from "@/lib/api/client";

// Office 문서 렌더링을 위한 CDN 라이브러리 로드
const loadOfficeLibrariesFromCDN = async () => {
  if (typeof window === "undefined") return { XLSX: null, mammoth: null };

  try {
    // XLSX 라이브러리가 이미 로드되어 있는지 확인
    if (!(window as any).XLSX) {
      await new Promise((resolve, reject) => {
        const script = document.createElement("script");
        script.src = "https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js";
        script.onload = resolve;
        script.onerror = reject;
        document.head.appendChild(script);
      });
    }

    // mammoth 라이브러리가 이미 로드되어 있는지 확인
    if (!(window as any).mammoth) {
      await new Promise((resolve, reject) => {
        const script = document.createElement("script");
        script.src = "https://cdnjs.cloudflare.com/ajax/libs/mammoth/1.4.2/mammoth.browser.min.js";
        script.onload = resolve;
        script.onerror = reject;
        document.head.appendChild(script);
      });
    }

    return {
      XLSX: (window as any).XLSX,
      mammoth: (window as any).mammoth,
    };
  } catch (error) {
    console.error("Office 라이브러리 CDN 로드 실패:", error);
    return { XLSX: null, mammoth: null };
  }
};

interface FileViewerModalProps {
  file: FileInfo | null;
  isOpen: boolean;
  onClose: () => void;
  onDownload?: (file: FileInfo) => void;
  onDelete?: (file: FileInfo) => void;
}

/**
 * 파일 뷰어 모달 컴포넌트
 */
export const FileViewerModal: React.FC<FileViewerModalProps> = ({ file, isOpen, onClose, onDownload, onDelete }) => {
  const [previewUrl, setPreviewUrl] = useState<string | null>(null);
  const [previewError, setPreviewError] = useState<string | null>(null);
  const [isLoading, setIsLoading] = useState(false);
  const [renderedContent, setRenderedContent] = useState<string | null>(null);

  // Office 문서를 CDN 라이브러리로 렌더링하는 함수
  const renderOfficeDocument = async (blob: Blob, fileExt: string, fileName: string) => {
    try {
      setIsLoading(true);

      // CDN에서 라이브러리 로드
      const { XLSX, mammoth } = await loadOfficeLibrariesFromCDN();

      if (fileExt === "docx" && mammoth) {
        // Word 문서 렌더링
        const arrayBuffer = await blob.arrayBuffer();
        const result = await mammoth.convertToHtml({ arrayBuffer });

        const htmlContent = `
          <div>
            <h4 style="margin: 0 0 15px 0; color: #333; font-size: 16px;">📄 ${fileName}</h4>
            <div class="word-content" style="max-height: 500px; overflow-y: auto; padding: 20px; background: white; border: 1px solid #ddd; border-radius: 5px; line-height: 1.6; font-family: 'Times New Roman', serif;">
              ${result.value || "내용을 읽을 수 없습니다."}
            </div>
          </div>
        `;

        setRenderedContent(htmlContent);
        return true;
      } else if (["xlsx", "xls"].includes(fileExt) && XLSX) {
        // Excel 문서 렌더링
        const arrayBuffer = await blob.arrayBuffer();
        const workbook = XLSX.read(arrayBuffer, { type: "array" });
        const sheetName = workbook.SheetNames[0];
        const worksheet = workbook.Sheets[sheetName];

        const html = XLSX.utils.sheet_to_html(worksheet, {
          table: { className: "excel-table" },
        });

        const htmlContent = `
          <div>
            <h4 style="margin: 0 0 10px 0; color: #333; font-size: 16px;">📊 ${fileName}</h4>
            <p style="margin: 0 0 15px 0; color: #666; font-size: 14px;">시트: ${sheetName}</p>
            <div style="max-height: 400px; overflow: auto; border: 1px solid #ddd; border-radius: 5px;">
              <style>
                .excel-table { border-collapse: collapse; width: 100%; }
                .excel-table td, .excel-table th { border: 1px solid #ddd; padding: 8px; text-align: left; font-size: 12px; }
                .excel-table th { background-color: #f5f5f5; font-weight: bold; }
              </style>
              ${html}
            </div>
          </div>
        `;

        setRenderedContent(htmlContent);
        return true;
      } else if (fileExt === "doc") {
        // .doc 파일은 .docx로 변환 안내
        const htmlContent = `
          <div style="text-align: center; padding: 40px;">
            <h3 style="color: #333; margin-bottom: 15px;">📄 ${fileName}</h3>
            <p style="color: #666; margin-bottom: 10px;">.doc 파일은 .docx로 변환 후 업로드해주세요.</p>
            <p style="color: #666; font-size: 14px;">(.docx 파일만 미리보기 지원)</p>
          </div>
        `;

        setRenderedContent(htmlContent);
        return true;
      } else if (["ppt", "pptx"].includes(fileExt)) {
        // PowerPoint는 미리보기 불가 안내
        const htmlContent = `
          <div style="text-align: center; padding: 40px;">
            <h3 style="color: #333; margin-bottom: 15px;">📑 ${fileName}</h3>
            <p style="color: #666; margin-bottom: 10px;">PowerPoint 파일은 브라우저에서 미리보기할 수 없습니다.</p>
            <p style="color: #666; font-size: 14px;">파일을 다운로드하여 확인해주세요.</p>
          </div>
        `;

        setRenderedContent(htmlContent);
        return true;
      }

      return false; // 지원하지 않는 형식
    } catch (error) {
      console.error("Office 문서 렌더링 오류:", error);

      const htmlContent = `
        <div style="color: red; text-align: center; padding: 20px;">
          Office 문서를 읽을 수 없습니다.<br>
          파일이 손상되었거나 지원하지 않는 형식일 수 있습니다.
        </div>
      `;

      setRenderedContent(htmlContent);
      return true; // 오류 메시지라도 표시
    } finally {
      setIsLoading(false);
    }
  };

  // 파일이 변경될 때마다 미리보기 URL 생성
  useEffect(() => {
    if (!file || !isOpen) {
      setPreviewUrl(null);
      setPreviewError(null);
      setRenderedContent(null);
      return;
    }

    setIsLoading(true);
    setPreviewError(null);

    // 로컬 파일인 경우
    if (file._file) {
      const url = URL.createObjectURL(file._file);
      setPreviewUrl(url);
      setIsLoading(false);

      return () => URL.revokeObjectURL(url);
    }

    let cleanup: (() => void) | undefined;

    // 서버 파일인 경우 - 미리보기 API 호출
    const generatePreviewUrl = async () => {
      try {
        const fileExt = file.fileExt.toLowerCase();

        // 미리보기 지원 파일 타입 정의
        const imageExtensions = ["jpg", "jpeg", "png", "gif", "webp", "svg"];
        const documentExtensions = [
          "pdf",
          "doc",
          "docx",
          "xls",
          "xlsx",
          "ppt",
          "pptx",
          "rtf",
          "odt",
          "ods",
          "odp",
          "hwp",
          "hwpx",
          "hwpml",
          "hcdt",
          "hpt",
          "pages",
          "numbers",
          "keynote",
        ];
        const textExtensions = ["txt", "md", "json", "xml", "csv"];
        const mediaExtensions = ["mp4", "webm", "ogg", "mp3", "wav"];

        const supportedExtensions = [...imageExtensions, ...documentExtensions, ...textExtensions, ...mediaExtensions];

        if (supportedExtensions.includes(fileExt)) {
          // 이미지나 PDF는 인증된 요청으로 Blob 생성
          if (imageExtensions.includes(fileExt) || fileExt === "pdf") {
            try {
              // 인증된 요청으로 파일 데이터 가져오기
              const response = await fetch(`${API_BASE_URL}/files/preview/${file.objid}`, {
                headers: {
                  Authorization: `Bearer ${localStorage.getItem("authToken")}`,
                },
              });

              if (response.ok) {
                const blob = await response.blob();
                const blobUrl = URL.createObjectURL(blob);
                setPreviewUrl(blobUrl);

                // 컴포넌트 언마운트 시 URL 정리를 위해 cleanup 함수 저장
                cleanup = () => URL.revokeObjectURL(blobUrl);
              } else {
                throw new Error(`HTTP ${response.status}`);
              }
            } catch (error) {
              console.error("파일 미리보기 로드 실패:", error);
              setPreviewError("파일을 불러올 수 없습니다. 권한을 확인해주세요.");
            }
          } else if (documentExtensions.includes(fileExt)) {
            // Office 문서는 OnlyOffice 또는 안정적인 뷰어 사용
            try {
              const response = await fetch(`${API_BASE_URL}/files/preview/${file.objid}`, {
                headers: {
                  Authorization: `Bearer ${localStorage.getItem("authToken")}`,
                },
              });

              if (response.ok) {
                const blob = await response.blob();
                const blobUrl = URL.createObjectURL(blob);

                // Office 문서를 위한 특별한 처리 - CDN 라이브러리 사용
                if (["doc", "docx", "xls", "xlsx", "ppt", "pptx"].includes(fileExt)) {
                  // CDN 라이브러리로 클라이언트 사이드 렌더링 시도
                  try {
                    const renderSuccess = await renderOfficeDocument(blob, fileExt, file.realFileName);

                    if (!renderSuccess) {
                      // 렌더링 실패 시 Blob URL 사용
                      setPreviewUrl(blobUrl);
                    }
                  } catch (error) {
                    console.error("Office 문서 렌더링 중 오류:", error);
                    // 오류 발생 시 Blob URL 사용
                    setPreviewUrl(blobUrl);
                  }
                } else {
                  // 기타 문서는 직접 Blob URL 사용
                  setPreviewUrl(blobUrl);
                }

                return () => URL.revokeObjectURL(blobUrl); // Cleanup function
              } else {
                throw new Error(`HTTP ${response.status}`);
              }
            } catch (error) {
              console.error("Office 문서 로드 실패:", error);
              // 오류 발생 시 다운로드 옵션 제공
              setPreviewError(`${fileExt.toUpperCase()} 문서를 미리보기할 수 없습니다. 다운로드하여 확인해주세요.`);
            }
          } else {
            // 기타 파일은 다운로드 URL 사용
            // 주의: 프로덕션 URL이 https://api.vexplor.com/api 이므로
            // 끝의 /api만 제거해야 호스트명이 깨지지 않음
            const url = `${API_BASE_URL.replace(/\/api$/, "")}/api/files/download/${file.objid}`;
            setPreviewUrl(url);
          }
        } else {
          // 지원하지 않는 파일 타입
          setPreviewError(`${file.fileExt.toUpperCase()} 파일은 미리보기를 지원하지 않습니다.`);
        }
      } catch (error) {
        console.error("미리보기 URL 생성 오류:", error);
        setPreviewError("미리보기를 불러오는데 실패했습니다.");
      } finally {
        setIsLoading(false);
      }
    };

    generatePreviewUrl();

    // cleanup 함수 반환
    return () => {
      if (cleanup) {
        cleanup();
      }
    };
  }, [file, isOpen]);

  if (!file) return null;

  // 파일 타입별 미리보기 컴포넌트
  const renderPreview = () => {
    if (isLoading) {
      return (
        <div className="flex h-96 items-center justify-center">
          <div className="h-12 w-12 animate-spin rounded-full border-b-2 border-primary"></div>
        </div>
      );
    }

    if (previewError) {
      return (
        <div className="flex h-96 flex-col items-center justify-center">
          <AlertTriangle className="mb-4 h-16 w-16 text-amber-500" />
          <p className="mb-2 text-lg font-medium">미리보기 불가</p>
          <p className="text-center text-sm">{previewError}</p>
          <Button variant="outline" onClick={() => onDownload?.(file)} className="mt-4">
            <Download className="mr-2 h-4 w-4" />
            파일 다운로드
          </Button>
        </div>
      );
    }

    const fileExt = file.fileExt.toLowerCase();

    // 이미지 파일
    if (["jpg", "jpeg", "png", "gif", "webp", "svg"].includes(fileExt)) {
      return (
        <div className="flex max-h-96 items-center justify-center overflow-hidden">
          <img
            src={previewUrl || ""}
            alt={file.realFileName}
            className="max-h-full max-w-full rounded-lg object-contain shadow-lg"
            onError={(e) => {
              console.error("이미지 로드 오류:", previewUrl, e);
              setPreviewError("이미지를 불러올 수 없습니다. 파일이 손상되었거나 서버에서 접근할 수 없습니다.");
            }}
            onLoad={() => {
              console.log("이미지 로드 성공:", previewUrl);
            }}
          />
        </div>
      );
    }

    // 텍스트 파일
    if (["txt", "md", "json", "xml", "csv"].includes(fileExt)) {
      return (
        <div className="h-96 overflow-auto">
          <iframe
            src={previewUrl || ""}
            className="h-full w-full rounded-lg border"
            onError={() => setPreviewError("텍스트 파일을 불러올 수 없습니다.")}
          />
        </div>
      );
    }

    // PDF 파일 - 브라우저 기본 뷰어 사용
    if (fileExt === "pdf") {
      return (
        <div className="h-[600px] overflow-auto rounded-lg border bg-muted">
          <object
            data={previewUrl || ""}
            type="application/pdf"
            className="h-full w-full rounded-lg"
            title="PDF Viewer"
          >
            <iframe src={previewUrl || ""} className="h-full w-full rounded-lg" title="PDF Viewer Fallback">
              <div className="flex h-full flex-col items-center justify-center p-8">
                <FileText className="mb-4 h-16 w-16 text-muted-foreground/70" />
                <p className="mb-2 text-lg font-medium">PDF를 표시할 수 없습니다</p>
                <p className="mb-4 text-center text-sm text-muted-foreground">
                  브라우저가 PDF 표시를 지원하지 않습니다. 다운로드하여 확인해주세요.
                </p>
                <Button variant="outline" onClick={() => onDownload?.(file)}>
                  <Download className="mr-2 h-4 w-4" />
                  PDF 다운로드
                </Button>
              </div>
            </iframe>
          </object>
        </div>
      );
    }

    // Office 문서 - 모든 Office 문서는 다운로드 권장
    if (
      [
        "doc",
        "docx",
        "xls",
        "xlsx",
        "ppt",
        "pptx",
        "hwp",
        "hwpx",
        "hwpml",
        "hcdt",
        "hpt",
        "pages",
        "numbers",
        "keynote",
      ].includes(fileExt)
    ) {
      // Office 문서 안내 메시지 표시
      return (
        <div className="relative flex h-96 flex-col items-center justify-center overflow-auto rounded-lg border bg-gradient-to-br from-primary/5 to-indigo-50 p-8">
          <FileText className="mb-6 h-20 w-20 text-primary" />
          <h3 className="mb-2 text-xl font-semibold text-foreground">Office 문서</h3>
          <p className="mb-6 max-w-md text-center text-sm text-muted-foreground">
            {fileExt === "docx" || fileExt === "doc"
              ? "Word 문서"
              : fileExt === "xlsx" || fileExt === "xls"
                ? "Excel 문서"
                : fileExt === "pptx" || fileExt === "ppt"
                  ? "PowerPoint 문서"
                  : "Office 문서"}
            는 브라우저에서 미리보기가 지원되지 않습니다.
            <br />
            다운로드하여 확인해주세요.
          </p>
          <div className="flex gap-3">
            <Button onClick={() => onDownload?.(file)} size="lg" className="shadow-md">
              <Download className="mr-2 h-5 w-5" />
              다운로드하여 열기
            </Button>
          </div>
        </div>
      );
    }

    // 비디오 파일
    if (["mp4", "webm", "ogg"].includes(fileExt)) {
      return (
        <div className="flex items-center justify-center">
          <video controls className="max-h-96 w-full" onError={() => setPreviewError("비디오를 재생할 수 없습니다.")}>
            <source src={previewUrl || ""} type={`video/${fileExt}`} />
          </video>
        </div>
      );
    }

    // 오디오 파일
    if (["mp3", "wav", "ogg"].includes(fileExt)) {
      return (
        <div className="flex h-96 flex-col items-center justify-center">
          <div className="mb-6 flex h-32 w-32 items-center justify-center rounded-full bg-muted">
            <svg className="h-16 w-16 text-muted-foreground/70" fill="currentColor" viewBox="0 0 20 20">
              <path
                fillRule="evenodd"
                d="M9.383 3.076A1 1 0 0110 4v12a1 1 0 01-1.707.707L4.586 13H2a1 1 0 01-1-1V8a1 1 0 011-1h2.586l3.707-3.707a1 1 0 011.09-.217zM15.657 6.343a1 1 0 011.414 0A9.972 9.972 0 0119 12a9.972 9.972 0 01-1.929 5.657 1 1 0 11-1.414-1.414A7.971 7.971 0 0017 12c0-1.594-.471-3.078-1.343-4.343a1 1 0 010-1.414zm-2.829 2.828a1 1 0 011.415 0A5.983 5.983 0 0115 12a5.984 5.984 0 01-.757 2.829 1 1 0 01-1.415-1.414A3.987 3.987 0 0013 12a3.988 3.988 0 00-.172-1.171 1 1 0 010-1.414z"
                clipRule="evenodd"
              />
            </svg>
          </div>
          <audio controls className="w-full max-w-md" onError={() => setPreviewError("오디오를 재생할 수 없습니다.")}>
            <source src={previewUrl || ""} type={`audio/${fileExt}`} />
          </audio>
        </div>
      );
    }

    // 기타 파일 타입
    return (
      <div className="flex h-96 flex-col items-center justify-center">
        <FileText className="mb-4 h-16 w-16 text-muted-foreground/70" />
        <p className="mb-2 text-lg font-medium">미리보기 불가</p>
        <p className="mb-4 text-center text-sm">{file.fileExt.toUpperCase()} 파일은 미리보기를 지원하지 않습니다.</p>
        <Button variant="outline" onClick={() => onDownload?.(file)}>
          <Download className="mr-2 h-4 w-4" />
          파일 다운로드
        </Button>
      </div>
    );
  };

  return (
    <Dialog open={isOpen} onOpenChange={() => {}}>
      <DialogContent className="max-h-[90vh] max-w-4xl overflow-hidden [&>button]:hidden">
        <DialogHeader>
          <div className="flex items-center justify-between">
            <div className="flex items-center space-x-3">
              <DialogTitle className="truncate text-lg font-semibold">{file.realFileName}</DialogTitle>
              <Badge variant="secondary" className="text-xs">
                {file.fileExt.toUpperCase()}
              </Badge>
            </div>
          </div>
          <DialogDescription>
            파일 크기: {formatFileSize(file.fileSize || file.size || 0)} | 파일 형식: {file.fileExt.toUpperCase()}
          </DialogDescription>
        </DialogHeader>

        <div className="flex-1 overflow-hidden">{renderPreview()}</div>

        {/* 파일 정보 및 액션 버튼 */}
        <div className="mt-2 flex items-center space-x-4 text-sm text-muted-foreground">
          <span>크기: {formatFileSize(file.fileSize || file.size || 0)}</span>
          {(file.uploadedAt || file.regdate) && (
            <span>업로드: {new Date(file.uploadedAt || file.regdate || "").toLocaleString()}</span>
          )}
        </div>

        <div className="flex justify-end space-x-2 border-t pt-4">
          <Button variant="outline" size="sm" onClick={() => onDownload?.(file)}>
            <Download className="mr-2 h-4 w-4" />
            다운로드
          </Button>
          {onDelete && (
            <Button
              variant="outline"
              size="sm"
              className="text-destructive hover:bg-destructive/10 hover:text-destructive"
              onClick={() => onDelete(file)}
            >
              <Trash2 className="mr-2 h-4 w-4" />
              삭제
            </Button>
          )}
          <Button variant="outline" size="sm" onClick={onClose}>
            <X className="mr-2 h-4 w-4" />
            닫기
          </Button>
        </div>
      </DialogContent>
    </Dialog>
  );
};
