"use client";

import React, { useState, useEffect, useMemo } from "react";
import {
  MagnifyingGlassIcon,
  EyeIcon,
  ArrowDownTrayIcon,
  PhotoIcon,
  VideoCameraIcon,
  MusicalNoteIcon,
  DocumentIcon,
  Squares2X2Icon,
  ListBulletIcon,
} from "@heroicons/react/24/outline";

import { MediaFilter, MediaFilterOptions } from "./MediaFilter";
import { MediaSort, SortOptions } from "./MediaSort";
import { MediaPagination } from "./MediaPagination";
import { MediaPreview } from "./MediaPreview";

interface MediaFile {
  id: string;
  fileName: string;
  originalName: string;
  mimeType: string;
  size: number;
  url: string;
  thumbnailUrl?: string;
  createdAt: string;
  downloadCount?: number;
  viewCount?: number;
  tags?: string[];
  description?: string;
  dimensions?: {
    width: number;
    height: number;
  };
  metadata?: Record<string, unknown>;
}

interface MediaLibraryProps {
  files?: MediaFile[];
  onFileSelect?: (file: MediaFile) => void;
  onFileUpdate?: (file: MediaFile) => void;
  onFileDelete?: (fileId: string) => void;
  selectable?: boolean;
  multiple?: boolean;
  className?: string;
}

type ViewMode = "grid" | "list";

export function MediaLibrary({
  files = [],
  onFileSelect,
  onFileUpdate,
  onFileDelete,
  selectable = false,
  multiple = false,
  className = "",
}: MediaLibraryProps) {
  // State management
  const [filters, setFilters] = useState<MediaFilterOptions>({
    fileTypes: [],
    dateRange: {},
    sizeRange: {},
    tags: [],
    searchTerm: "",
  });

  const [sortOptions, setSortOptions] = useState<SortOptions>({
    field: "date",
    direction: "desc",
  });

  const [currentPage, setCurrentPage] = useState(1);
  const [itemsPerPage, setItemsPerPage] = useState(24);
  const [viewMode, setViewMode] = useState<ViewMode>("grid");
  const [selectedFiles, setSelectedFiles] = useState<string[]>([]);
  const [previewFile, setPreviewFile] = useState<MediaFile | null>(null);
  const [isPreviewOpen, setIsPreviewOpen] = useState(false);

  // Available tags for filtering
  const availableTags = useMemo(() => {
    const tagSet = new Set<string>();
    files.forEach((file) => {
      file.tags?.forEach((tag) => tagSet.add(tag));
    });
    return Array.from(tagSet);
  }, [files]);

  // Filter and sort files
  const filteredAndSortedFiles = useMemo(() => {
    const filtered = files.filter((file) => {
      // Search term filter
      if (filters.searchTerm) {
        const searchLower = filters.searchTerm.toLowerCase();
        if (
          !file.originalName.toLowerCase().includes(searchLower) &&
          !file.description?.toLowerCase().includes(searchLower)
        ) {
          return false;
        }
      }

      // File type filter
      if (filters.fileTypes.length > 0) {
        const hasMatchingType = filters.fileTypes.some((type) => {
          switch (type) {
            case "image":
              return file.mimeType.startsWith("image/");
            case "video":
              return file.mimeType.startsWith("video/");
            case "audio":
              return file.mimeType.startsWith("audio/");
            case "document":
              return (
                file.mimeType.includes("pdf") ||
                file.mimeType.includes("document") ||
                file.mimeType.includes("text")
              );
            default:
              return false;
          }
        });
        if (!hasMatchingType) return false;
      }

      // Date range filter
      if (filters.dateRange.start || filters.dateRange.end) {
        const fileDate = new Date(file.createdAt);
        if (
          filters.dateRange.start &&
          fileDate < new Date(filters.dateRange.start)
        ) {
          return false;
        }
        if (
          filters.dateRange.end &&
          fileDate > new Date(filters.dateRange.end)
        ) {
          return false;
        }
      }

      // Size range filter
      if (
        filters.sizeRange.min !== undefined &&
        file.size < filters.sizeRange.min
      ) {
        return false;
      }
      if (
        filters.sizeRange.max !== undefined &&
        file.size > filters.sizeRange.max
      ) {
        return false;
      }

      // Tags filter
      if (filters.tags.length > 0) {
        const hasMatchingTag = filters.tags.some((tag) =>
          file.tags?.includes(tag)
        );
        if (!hasMatchingTag) return false;
      }

      return true;
    });

    // Sort files
    filtered.sort((a, b) => {
      let aValue: string | number;
      let bValue: string | number;

      switch (sortOptions.field) {
        case "name":
          aValue = a.originalName.toLowerCase();
          bValue = b.originalName.toLowerCase();
          break;
        case "size":
          aValue = a.size;
          bValue = b.size;
          break;
        case "date":
          aValue = new Date(a.createdAt).getTime();
          bValue = new Date(b.createdAt).getTime();
          break;
        case "type":
          aValue = a.mimeType.toLowerCase();
          bValue = b.mimeType.toLowerCase();
          break;
        case "downloads":
          aValue = a.downloadCount || 0;
          bValue = b.downloadCount || 0;
          break;
        case "views":
          aValue = a.viewCount || 0;
          bValue = b.viewCount || 0;
          break;
        default:
          aValue = a.originalName.toLowerCase();
          bValue = b.originalName.toLowerCase();
      }

      if (typeof aValue === "string" && typeof bValue === "string") {
        return sortOptions.direction === "asc"
          ? aValue.localeCompare(bValue)
          : bValue.localeCompare(aValue);
      }

      return sortOptions.direction === "asc"
        ? (aValue as number) - (bValue as number)
        : (bValue as number) - (aValue as number);
    });

    return filtered;
  }, [files, filters, sortOptions]);

  // Pagination
  const totalPages = Math.ceil(filteredAndSortedFiles.length / itemsPerPage);
  const paginatedFiles = filteredAndSortedFiles.slice(
    (currentPage - 1) * itemsPerPage,
    currentPage * itemsPerPage
  );

  // Reset page when filters change
  useEffect(() => {
    setCurrentPage(1);
  }, [filters, sortOptions, itemsPerPage]);

  // File operations
  const handleFileClick = (file: MediaFile) => {
    if (selectable) {
      if (multiple) {
        setSelectedFiles((prev) =>
          prev.includes(file.id)
            ? prev.filter((id) => id !== file.id)
            : [...prev, file.id]
        );
      } else {
        setSelectedFiles([file.id]);
      }
      onFileSelect?.(file);
    } else {
      setPreviewFile(file);
      setIsPreviewOpen(true);
    }
  };

  const handlePreview = (file: MediaFile) => {
    setPreviewFile(file);
    setIsPreviewOpen(true);
  };

  const handleDownload = (file: MediaFile) => {
    const link = document.createElement("a");
    link.href = file.url;
    link.download = file.originalName;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  };

  // Utility functions
  const formatFileSize = (bytes: number): string => {
    if (bytes === 0) return "0 Bytes";
    const k = 1024;
    const sizes = ["Bytes", "KB", "MB", "GB"];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
  };

  const formatDate = (dateString: string): string => {
    return new Date(dateString).toLocaleDateString("ko-KR", {
      year: "numeric",
      month: "short",
      day: "numeric",
    });
  };

  const getFileIcon = (mimeType: string) => {
    if (mimeType.startsWith("image/")) return PhotoIcon;
    if (mimeType.startsWith("video/")) return VideoCameraIcon;
    if (mimeType.startsWith("audio/")) return MusicalNoteIcon;
    return DocumentIcon;
  };

  const getThumbnail = (file: MediaFile) => {
    if (file.mimeType.startsWith("image/")) {
      return file.thumbnailUrl || file.url;
    }
    return file.thumbnailUrl;
  };

  return (
    <div className={`w-full ${className}`}>
      {/* 헤더 - 검색, 필터, 정렬 */}
      <div className="mb-6 space-y-4">
        {/* 검색바 */}
        <div className="relative">
          <MagnifyingGlassIcon className="absolute left-3 top-1/2 transform -translate-y-1/2 h-5 w-5 text-gray-400" />
          <input
            type="text"
            placeholder="파일명이나 설명으로 검색..."
            value={filters.searchTerm}
            onChange={(e) =>
              setFilters({ ...filters, searchTerm: e.target.value })
            }
            className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500"
          />
        </div>

        {/* 필터 및 정렬 컨트롤 */}
        <div className="flex items-center justify-between flex-wrap gap-4">
          <div className="flex items-center space-x-4">
            <MediaFilter
              filters={filters}
              onFilterChange={setFilters}
              availableTags={availableTags}
            />

            <MediaSort
              sortOptions={sortOptions}
              onSortChange={setSortOptions}
            />
          </div>

          {/* 뷰 모드 및 결과 정보 */}
          <div className="flex items-center space-x-4">
            <span className="text-sm text-gray-500">
              {filteredAndSortedFiles.length}개 파일
            </span>

            <div className="flex items-center border border-gray-300 rounded-md">
              <button
                onClick={() => setViewMode("grid")}
                className={`p-2 ${
                  viewMode === "grid"
                    ? "bg-blue-50 text-blue-600"
                    : "text-gray-400 hover:text-gray-600"
                }`}
              >
                <Squares2X2Icon className="h-4 w-4" />
              </button>
              <button
                onClick={() => setViewMode("list")}
                className={`p-2 ${
                  viewMode === "list"
                    ? "bg-blue-50 text-blue-600"
                    : "text-gray-400 hover:text-gray-600"
                }`}
              >
                <ListBulletIcon className="h-4 w-4" />
              </button>
            </div>
          </div>
        </div>
      </div>

      {/* 파일 목록 */}
      {paginatedFiles.length === 0 ? (
        <div className="text-center py-12">
          <PhotoIcon className="h-12 w-12 text-gray-400 mx-auto mb-4" />
          <p className="text-gray-500">조건에 맞는 파일이 없습니다.</p>
        </div>
      ) : viewMode === "grid" ? (
        <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 xl:grid-cols-8 gap-4 mb-6">
          {paginatedFiles.map((file) => {
            const FileIcon = getFileIcon(file.mimeType);
            const thumbnail = getThumbnail(file);
            const isSelected = selectedFiles.includes(file.id);

            return (
              <div
                key={file.id}
                className={`
                  relative group cursor-pointer border rounded-lg overflow-hidden
                  transition-all duration-200 hover:shadow-md
                  ${isSelected ? "ring-2 ring-blue-500 bg-blue-50" : "bg-white"}
                `}
                onClick={() => handleFileClick(file)}
              >
                {/* 썸네일 */}
                <div className="aspect-square bg-gray-100 flex items-center justify-center">
                  {thumbnail ? (
                    <img
                      src={thumbnail}
                      alt={file.originalName}
                      className="w-full h-full object-cover"
                      onError={(e) => {
                        const target = e.target as HTMLImageElement;
                        target.style.display = "none";
                        target.nextElementSibling?.classList.remove("hidden");
                      }}
                    />
                  ) : null}
                  <div className={thumbnail ? "hidden" : ""}>
                    <FileIcon className="h-8 w-8 text-gray-400" />
                  </div>
                </div>

                {/* 파일 정보 */}
                <div className="p-2">
                  <p className="text-xs font-medium text-gray-900 truncate">
                    {file.originalName}
                  </p>
                  <p className="text-xs text-gray-500">
                    {formatFileSize(file.size)}
                  </p>
                </div>

                {/* 호버 액션 */}
                <div className="absolute inset-0 bg-black bg-opacity-50 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center space-x-2">
                  <button
                    onClick={(e) => {
                      e.stopPropagation();
                      handlePreview(file);
                    }}
                    className="p-2 bg-white rounded-full text-gray-600 hover:text-blue-600"
                    title="미리보기"
                  >
                    <EyeIcon className="h-4 w-4" />
                  </button>
                  <button
                    onClick={(e) => {
                      e.stopPropagation();
                      handleDownload(file);
                    }}
                    className="p-2 bg-white rounded-full text-gray-600 hover:text-blue-600"
                    title="다운로드"
                  >
                    <ArrowDownTrayIcon className="h-4 w-4" />
                  </button>
                </div>

                {/* 선택 표시 */}
                {selectable && isSelected && (
                  <div className="absolute top-2 right-2 w-5 h-5 bg-blue-600 rounded-full flex items-center justify-center">
                    <svg
                      className="w-3 h-3 text-white"
                      fill="currentColor"
                      viewBox="0 0 20 20"
                    >
                      <path
                        fillRule="evenodd"
                        d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
                        clipRule="evenodd"
                      />
                    </svg>
                  </div>
                )}
              </div>
            );
          })}
        </div>
      ) : (
        // 리스트 뷰
        <div className="bg-white border border-gray-200 rounded-lg overflow-hidden mb-6">
          <div className="grid grid-cols-12 gap-4 p-4 bg-gray-50 border-b text-sm font-medium text-gray-700">
            <div className="col-span-5">파일명</div>
            <div className="col-span-2">크기</div>
            <div className="col-span-2">형식</div>
            <div className="col-span-2">업로드 날짜</div>
            <div className="col-span-1">액션</div>
          </div>

          {paginatedFiles.map((file) => {
            const FileIcon = getFileIcon(file.mimeType);
            const isSelected = selectedFiles.includes(file.id);

            return (
              <div
                key={file.id}
                className={`
                  grid grid-cols-12 gap-4 p-4 border-b border-gray-100 hover:bg-gray-50 cursor-pointer
                  ${isSelected ? "bg-blue-50" : ""}
                `}
                onClick={() => handleFileClick(file)}
              >
                <div className="col-span-5 flex items-center space-x-3">
                  <FileIcon className="h-5 w-5 text-gray-400 flex-shrink-0" />
                  <div className="min-w-0 flex-1">
                    <p className="text-sm font-medium text-gray-900 truncate">
                      {file.originalName}
                    </p>
                    {file.description && (
                      <p className="text-xs text-gray-500 truncate">
                        {file.description}
                      </p>
                    )}
                  </div>
                </div>

                <div className="col-span-2 flex items-center">
                  <span className="text-sm text-gray-900">
                    {formatFileSize(file.size)}
                  </span>
                </div>

                <div className="col-span-2 flex items-center">
                  <span className="text-sm text-gray-500">
                    {file.mimeType.split("/")[1]?.toUpperCase()}
                  </span>
                </div>

                <div className="col-span-2 flex items-center">
                  <span className="text-sm text-gray-500">
                    {formatDate(file.createdAt)}
                  </span>
                </div>

                <div className="col-span-1 flex items-center space-x-1">
                  <button
                    onClick={(e) => {
                      e.stopPropagation();
                      handlePreview(file);
                    }}
                    className="p-1 text-gray-400 hover:text-blue-600"
                    title="미리보기"
                  >
                    <EyeIcon className="h-4 w-4" />
                  </button>
                  <button
                    onClick={(e) => {
                      e.stopPropagation();
                      handleDownload(file);
                    }}
                    className="p-1 text-gray-400 hover:text-blue-600"
                    title="다운로드"
                  >
                    <ArrowDownTrayIcon className="h-4 w-4" />
                  </button>
                </div>
              </div>
            );
          })}
        </div>
      )}

      {/* 페이지네이션 */}
      {totalPages > 1 && (
        <MediaPagination
          currentPage={currentPage}
          totalPages={totalPages}
          totalItems={filteredAndSortedFiles.length}
          itemsPerPage={itemsPerPage}
          onPageChange={setCurrentPage}
          onItemsPerPageChange={setItemsPerPage}
        />
      )}

      {/* 미리보기 모달 */}
      <MediaPreview
        file={previewFile}
        isOpen={isPreviewOpen}
        onClose={() => {
          setIsPreviewOpen(false);
          setPreviewFile(null);
        }}
        onUpdate={onFileUpdate}
        onDelete={onFileDelete}
      />
    </div>
  );
}
