/**
 * 관리자 앨범 사진 관리 페이지
 */
import { useState, useEffect, useRef } from 'react';
import { Link, useParams } from 'react-router-dom';
import { useQuery } from '@tanstack/react-query';
import { motion, AnimatePresence, Reorder } from 'framer-motion';
import { Upload, Trash2, Image, Plus, Home, ChevronRight, FolderOpen, Save } from 'lucide-react';
import { Toast } from '@/components/common';
import {
  AdminLayout,
  ConfirmDialog,
  PendingFileItem,
  BulkEditPanel,
  PhotoGrid,
  PhotoPreviewModal,
  parseRange,
} from '@/components/pc/admin';
import { useAdminAuth } from '@/hooks/pc/admin';
import { useToast } from '@/hooks/common';
import { adminAlbumApi, adminMemberApi } from '@/api/admin';
import useAuthStore from '@/stores/useAuthStore';

function AdminAlbumPhotos() {
  const { albumId } = useParams();
  const fileInputRef = useRef(null);
  const photoListRef = useRef(null);

  const { user, isAuthenticated } = useAdminAuth();
  const { toast, setToast } = useToast();
  const [selectedPhotos, setSelectedPhotos] = useState([]);
  const [uploading, setUploading] = useState(false);
  const [uploadProgress, setUploadProgress] = useState(0);
  const [deleteDialog, setDeleteDialog] = useState({ show: false, photos: [] });
  const [deleting, setDeleting] = useState(false);
  const [previewPhoto, setPreviewPhoto] = useState(null);
  const [dragOver, setDragOver] = useState(false);

  // 업로드 대기 중인 파일들
  const [pendingFiles, setPendingFiles] = useState([]);
  const [photoType, setPhotoType] = useState('concept');
  const [conceptName, setConceptName] = useState('');
  const [startNumber, setStartNumber] = useState(1);
  const [saving, setSaving] = useState(false);
  const [processingStatus, setProcessingStatus] = useState('');
  const [processingProgress, setProcessingProgress] = useState({ current: 0, total: 0 });
  const [pendingDeleteId, setPendingDeleteId] = useState(null);
  const [uploadConfirmDialog, setUploadConfirmDialog] = useState(false);
  const [activeTab, setActiveTab] = useState('upload');
  const [manageSubTab, setManageSubTab] = useState('concept');

  // 일괄 편집 도구 상태
  const [bulkEdit, setBulkEdit] = useState({
    range: '',
    groupType: '',
    members: [],
    conceptName: '',
  });

  // 일괄 편집 적용
  const applyBulkEdit = () => {
    const indices = parseRange(bulkEdit.range, startNumber);
    if (indices.length === 0) {
      setToast({ message: '적용할 번호 범위를 입력하세요.', type: 'warning' });
      return;
    }

    const validIndices = indices.filter((i) => i < pendingFiles.length);
    if (validIndices.length === 0) {
      setToast({ message: '유효한 번호가 없습니다.', type: 'error' });
      return;
    }

    setPendingFiles((prev) =>
      prev.map((file, idx) => {
        if (!validIndices.includes(idx)) return file;

        const updates = {};
        if (bulkEdit.groupType) {
          updates.groupType = bulkEdit.groupType;
          if (bulkEdit.groupType === 'group') {
            updates.members = [];
          } else if (bulkEdit.members.length > 0) {
            updates.members =
              bulkEdit.groupType === 'solo' ? [bulkEdit.members[0]] : [...bulkEdit.members];
          }
        } else if (bulkEdit.members.length > 0) {
          updates.members = [...bulkEdit.members];
        }

        if (bulkEdit.conceptName) {
          updates.conceptName = bulkEdit.conceptName;
        }

        return { ...file, ...updates };
      })
    );

    setToast({ message: `${validIndices.length}개 사진에 일괄 적용되었습니다.`, type: 'success' });
    setBulkEdit({ range: '', groupType: '', members: [], conceptName: '' });
  };

  // 앨범 정보 로드
  const {
    data: album,
    isLoading: albumLoading,
    error: albumError,
    refetch: refetchAlbum,
  } = useQuery({
    queryKey: ['admin', 'album', albumId],
    queryFn: () => adminAlbumApi.getAlbum(albumId),
    enabled: isAuthenticated && !!albumId,
    staleTime: 0,
  });

  // 멤버 목록 로드
  const { data: members = [] } = useQuery({
    queryKey: ['admin', 'members'],
    queryFn: adminMemberApi.getMembers,
    enabled: isAuthenticated,
    staleTime: 5 * 60 * 1000,
  });

  // 컨셉 포토 목록 로드
  const { data: photos = [], refetch: refetchPhotos } = useQuery({
    queryKey: ['admin', 'album', albumId, 'photos'],
    queryFn: () => adminAlbumApi.getAlbumPhotos(albumId),
    enabled: isAuthenticated && !!albumId,
    staleTime: 0,
  });

  // 티저 이미지 목록 로드
  const { data: teasers = [], refetch: refetchTeasers } = useQuery({
    queryKey: ['admin', 'album', albumId, 'teasers'],
    queryFn: () => adminAlbumApi.getAlbumTeasers(albumId),
    enabled: isAuthenticated && !!albumId,
    staleTime: 0,
  });

  const loading = albumLoading;

  // 에러 처리
  useEffect(() => {
    if (albumError) {
      console.error('앨범 로드 오류:', albumError);
      setToast({ message: albumError.message || '앨범 로드 중 오류가 발생했습니다.', type: 'error' });
    }
  }, [albumError, setToast]);

  // 데이터 새로고침 함수
  const fetchAlbumData = async () => {
    await Promise.all([refetchAlbum(), refetchPhotos(), refetchTeasers()]);
  };

  // 타입 변경 시 시작 번호 자동 업데이트
  useEffect(() => {
    if (photoType === 'concept') {
      const maxOrder = photos.length > 0 ? Math.max(...photos.map((p) => p.sort_order || 0)) : 0;
      setStartNumber(maxOrder + 1);
    } else if (photoType === 'teaser') {
      const maxOrder = teasers.length > 0 ? Math.max(...teasers.map((t) => t.sort_order || 0)) : 0;
      setStartNumber(maxOrder + 1);
    }
  }, [photoType, photos, teasers]);

  // 파일 선택
  const handleFileSelect = (e) => {
    const files = Array.from(e.target.files);
    addFilesToPending(files);
    e.target.value = '';
  };

  // 드래그 앤 드롭
  const dragCounterRef = useRef(0);

  const handleDragEnter = (e) => {
    e.preventDefault();
    e.stopPropagation();
    dragCounterRef.current++;
    if (e.dataTransfer.types.includes('Files')) {
      setDragOver(true);
    }
  };

  const handleDragOver = (e) => {
    e.preventDefault();
    e.stopPropagation();
  };

  const handleDragLeave = (e) => {
    e.preventDefault();
    e.stopPropagation();
    dragCounterRef.current--;
    if (dragCounterRef.current === 0) {
      setDragOver(false);
    }
  };

  const handleDrop = (e) => {
    e.preventDefault();
    e.stopPropagation();
    dragCounterRef.current = 0;
    setDragOver(false);
    const files = Array.from(e.dataTransfer.files).filter((f) => f.type.startsWith('image/'));
    if (files.length > 0) {
      addFilesToPending(files);
    }
  };

  // 대기 목록에 파일 추가
  const addFilesToPending = (files) => {
    const existingKeys = new Set(pendingFiles.map((f) => `${f.filename}_${f.file.size}`));

    const uniqueFiles = files.filter((file) => {
      const key = `${file.name}_${file.size}`;
      if (existingKeys.has(key)) {
        return false;
      }
      existingKeys.add(key);
      return true;
    });

    if (uniqueFiles.length < files.length) {
      const duplicateCount = files.length - uniqueFiles.length;
      setToast({
        message: `${duplicateCount}개의 중복 파일이 제외되었습니다.`,
        type: 'warning',
      });
    }

    if (uniqueFiles.length === 0) return;

    const newFiles = uniqueFiles.map((file, index) => ({
      id: Date.now() + index,
      file,
      preview: URL.createObjectURL(file),
      filename: file.name,
      isVideo: file.type === 'video/mp4',
      groupType: 'group',
      members: [],
      conceptName: '',
    }));
    setPendingFiles((prev) => [...prev, ...newFiles]);
  };

  // 대기 파일 순서 변경
  const handleReorder = (newOrder) => {
    setPendingFiles(newOrder);
  };

  // 직접 순서 변경
  const moveToPosition = (fileId, newPosition) => {
    const pos = parseInt(newPosition, 10);
    if (isNaN(pos) || pos < startNumber) return;

    setPendingFiles((prev) => {
      const targetIndex = Math.min(pos - startNumber, prev.length - 1);
      const currentIndex = prev.findIndex((f) => f.id === fileId);
      if (currentIndex === -1 || currentIndex === targetIndex) return prev;

      const newFiles = [...prev];
      const [removed] = newFiles.splice(currentIndex, 1);
      newFiles.splice(targetIndex, 0, removed);
      return newFiles;
    });
  };

  // 대기 파일 삭제
  const confirmDeletePendingFile = () => {
    if (!pendingDeleteId) return;
    setPendingFiles((prev) => {
      const file = prev.find((f) => f.id === pendingDeleteId);
      if (file) URL.revokeObjectURL(file.preview);
      return prev.filter((f) => f.id !== pendingDeleteId);
    });
    setPendingDeleteId(null);
  };

  // 대기 파일 메타 정보 수정
  const updatePendingFile = (id, field, value) => {
    setPendingFiles((prev) => prev.map((f) => (f.id === id ? { ...f, [field]: value } : f)));
  };

  // 멤버 토글
  const toggleMember = (fileId, member) => {
    setPendingFiles((prev) =>
      prev.map((f) => {
        if (f.id !== fileId) return f;

        if (f.groupType === 'solo') {
          return { ...f, members: f.members.includes(member) ? [] : [member] };
        }

        const members = f.members.includes(member)
          ? f.members.filter((m) => m !== member)
          : [...f.members, member];
        return { ...f, members };
      })
    );
  };

  // 타입 변경
  const changeGroupType = (fileId, newType) => {
    setPendingFiles((prev) =>
      prev.map((f) => {
        if (f.id !== fileId) return f;
        if (newType === 'group') {
          return { ...f, groupType: newType, members: [] };
        }
        if (newType === 'solo' && f.members.length > 1) {
          return { ...f, groupType: newType, members: [f.members[0]] };
        }
        return { ...f, groupType: newType };
      })
    );
  };

  // 업로드 처리
  const handleUpload = async () => {
    if (pendingFiles.length === 0) {
      setToast({ message: '업로드할 사진을 선택해주세요.', type: 'warning' });
      return;
    }

    if (photoType === 'concept') {
      const missingMembers = pendingFiles.some(
        (f) => (f.groupType === 'solo' || f.groupType === 'unit') && f.members.length === 0
      );
      if (missingMembers) {
        setToast({ message: '개인/유닛 사진에는 멤버를 선택해주세요.', type: 'warning' });
        return;
      }
    }

    setSaving(true);
    setUploadProgress(0);
    setProcessingProgress({ current: 0, total: pendingFiles.length });
    setProcessingStatus('');

    try {
      const token = useAuthStore.getState().token;

      const formData = new FormData();
      const metadata = pendingFiles.map((pf) => ({
        groupType: pf.groupType,
        members: pf.members,
        conceptName: pf.conceptName,
      }));

      pendingFiles.forEach((pf) => {
        formData.append('photos', pf.file);
      });
      formData.append('metadata', JSON.stringify(metadata));
      formData.append('startNumber', startNumber);
      formData.append('photoType', photoType);

      const response = await fetch(`/api/albums/${albumId}/photos`, {
        method: 'POST',
        headers: {
          Authorization: `Bearer ${token}`,
        },
        body: formData,
      });

      setUploadProgress(100);

      // SSE 응답 읽기
      const reader = response.body.getReader();
      const decoder = new TextDecoder();
      let result = null;

      while (true) {
        const { done, value } = await reader.read();
        if (done) break;

        const text = decoder.decode(value);
        const lines = text.split('\n');

        for (const line of lines) {
          if (line.startsWith('data: ')) {
            try {
              const data = JSON.parse(line.slice(6));
              if (data.done) {
                result = data;
              } else if (data.error) {
                throw new Error(data.error);
              } else if (data.current) {
                setProcessingProgress({ current: data.current, total: data.total });
                setProcessingStatus(data.message);
              }
            } catch (e) {
              // JSON 파싱 실패 무시
            }
          }
        }
      }

      if (result) {
        setToast({ message: result.message, type: 'success' });
      }

      pendingFiles.forEach((f) => URL.revokeObjectURL(f.preview));
      setPendingFiles([]);
      setConceptName('');

      fetchAlbumData();
    } catch (error) {
      console.error('업로드 오류:', error);
      setToast({ message: error.message || '업로드 중 오류가 발생했습니다.', type: 'error' });
    } finally {
      setSaving(false);
      setUploadProgress(0);
      setProcessingProgress({ current: 0, total: 0 });
      setProcessingStatus('');
    }
  };

  // 삭제 처리
  const handleDelete = async () => {
    setDeleting(true);

    try {
      const photoIds = deleteDialog.photos.filter(
        (id) => typeof id === 'number' || !String(id).startsWith('teaser-')
      );
      const teaserIds = deleteDialog.photos
        .filter((id) => String(id).startsWith('teaser-'))
        .map((id) => parseInt(String(id).replace('teaser-', '')));

      for (const photoId of photoIds) {
        await adminAlbumApi.deleteAlbumPhoto(albumId, photoId);
      }

      for (const teaserId of teaserIds) {
        await adminAlbumApi.deleteAlbumTeaser(albumId, teaserId);
      }

      if (photoIds.length > 0) await refetchPhotos();
      if (teaserIds.length > 0) await refetchTeasers();
      setSelectedPhotos([]);

      const totalDeleted = photoIds.length + teaserIds.length;
      setToast({ message: `${totalDeleted}개 항목이 삭제되었습니다.`, type: 'success' });
    } catch (error) {
      console.error('삭제 오류:', error);
      setToast({ message: '삭제 중 오류가 발생했습니다.', type: 'error' });
    } finally {
      setDeleteDialog({ show: false, photos: [] });
      setDeleting(false);
    }
  };

  if (loading) {
    return (
      <AdminLayout user={user}>
        <div
          className="max-w-7xl mx-auto px-6 py-8 flex items-center justify-center"
          style={{ minHeight: 'calc(100vh - 80px)' }}
        />
      </AdminLayout>
    );
  }

  return (
    <AdminLayout user={user}>
      <Toast toast={toast} onClose={() => setToast(null)} />

      {/* 삭제 확인 다이얼로그 */}
      <ConfirmDialog
        isOpen={deleteDialog.show}
        onClose={() => setDeleteDialog({ show: false, photos: [] })}
        onConfirm={handleDelete}
        title="사진 삭제"
        message={
          <>
            <span className="font-medium text-gray-900">{deleteDialog.photos.length}개</span>의 사진을
            삭제하시겠습니까?
            <br />
            <span className="text-sm text-red-500">이 작업은 되돌릴 수 없습니다.</span>
          </>
        }
        loading={deleting}
      />

      {/* 이미지 미리보기 */}
      <PhotoPreviewModal photo={previewPhoto} onClose={() => setPreviewPhoto(null)} />

      <div className="max-w-7xl mx-auto px-6 py-8">
        {/* 브레드크럼 */}
        <div className="flex items-center gap-2 text-sm text-gray-400 mb-8">
          <Link to="/admin/dashboard" className="hover:text-primary transition-colors">
            <Home size={16} />
          </Link>
          <ChevronRight size={14} />
          <Link to="/admin/albums" className="hover:text-primary transition-colors">
            앨범 관리
          </Link>
          <ChevronRight size={14} />
          <span className="text-gray-700">{album?.title} - 사진 관리</span>
        </div>

        {/* 타이틀 + 액션 버튼 */}
        <motion.div
          initial={{ opacity: 0, y: 12 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{
            duration: 0.4,
            ease: [0.25, 0.1, 0.25, 1],
            delay: 0.15,
          }}
          className="flex items-center justify-between mb-8"
        >
          <div className="flex items-center gap-4">
            <img
              src={album?.cover_thumb_url || album?.cover_original_url}
              alt={album?.title}
              className="w-14 h-14 rounded-xl object-cover"
            />
            <div>
              <h1 className="text-2xl font-bold text-gray-900">{album?.title}</h1>
              <p className="text-gray-500">사진 업로드 및 관리</p>
            </div>
          </div>
          {pendingFiles.length > 0 && (
            <div className="flex items-center gap-3">
              <button
                onClick={() => {
                  pendingFiles.forEach((f) => URL.revokeObjectURL(f.preview));
                  setPendingFiles([]);
                }}
                className="px-4 py-2 text-gray-600 hover:text-gray-900 transition-colors"
              >
                취소
              </button>
              <button
                onClick={() => setUploadConfirmDialog(true)}
                disabled={pendingFiles.length === 0 || saving}
                className="flex items-center gap-2 px-5 py-2 bg-primary text-white rounded-lg hover:bg-primary-dark transition-colors disabled:opacity-50"
              >
                {saving ? (
                  <>
                    <span className="w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin" />
                    업로드 중...
                  </>
                ) : (
                  <>
                    <Save size={18} />
                    {pendingFiles.length}개 사진 업로드
                  </>
                )}
              </button>
            </div>
          )}
        </motion.div>

        {/* 탭 UI */}
        <div className="flex gap-1 p-1 bg-gray-100 rounded-xl mb-6">
          <button
            onClick={() => setActiveTab('upload')}
            className={`flex-1 flex items-center justify-center gap-2 px-4 py-2.5 rounded-lg font-medium transition-all ${
              activeTab === 'upload'
                ? 'bg-white text-primary shadow-sm'
                : 'text-gray-500 hover:text-gray-700'
            }`}
          >
            <Upload size={18} />
            업로드
          </button>
          <button
            onClick={() => setActiveTab('manage')}
            className={`flex-1 flex items-center justify-center gap-2 px-4 py-2.5 rounded-lg font-medium transition-all ${
              activeTab === 'manage'
                ? 'bg-white text-primary shadow-sm'
                : 'text-gray-500 hover:text-gray-700'
            }`}
          >
            <FolderOpen size={18} />
            관리
            {photos.length > 0 && (
              <span className="px-2 py-0.5 bg-primary/10 text-primary text-xs rounded-full">
                {photos.length}
              </span>
            )}
          </button>
        </div>

        {/* 업로드 탭 */}
        {activeTab === 'upload' && (
          <>
            {/* 업로드 설정 */}
            <div className="bg-white rounded-2xl border border-gray-100 shadow-sm p-6 mb-6">
              <h2 className="text-lg font-bold text-gray-900 mb-4 flex items-center gap-2">
                <FolderOpen size={20} />
                업로드 설정
              </h2>

              {/* 타입 선택 */}
              <div>
                <label className="block text-sm font-medium text-gray-700 mb-2">사진 타입 *</label>
                <div className="flex gap-2 max-w-xs">
                  <button
                    onClick={() => setPhotoType('concept')}
                    disabled={pendingFiles.length > 0}
                    className={`flex-1 py-2 px-4 rounded-lg text-sm font-medium transition-colors ${
                      photoType === 'concept'
                        ? 'bg-primary text-white'
                        : 'bg-gray-100 text-gray-600 hover:bg-gray-200'
                    } ${pendingFiles.length > 0 ? 'opacity-50 cursor-not-allowed' : ''}`}
                  >
                    컨셉 포토
                  </button>
                  <button
                    onClick={() => setPhotoType('teaser')}
                    disabled={pendingFiles.length > 0}
                    className={`flex-1 py-2 px-4 rounded-lg text-sm font-medium transition-colors ${
                      photoType === 'teaser'
                        ? 'bg-primary text-white'
                        : 'bg-gray-100 text-gray-600 hover:bg-gray-200'
                    } ${pendingFiles.length > 0 ? 'opacity-50 cursor-not-allowed' : ''}`}
                  >
                    티저 이미지
                  </button>
                </div>
                <p className="text-xs text-gray-400 mt-2">
                  {pendingFiles.length > 0
                    ? '파일이 추가된 상태에서는 타입을 변경할 수 없습니다.'
                    : photoType === 'teaser'
                      ? '티저 이미지는 순서만 지정하면 됩니다.'
                      : '컨셉/티저 이름은 각 사진별로 입력합니다.'}
                </p>
              </div>

              {/* 시작 번호 설정 */}
              <div className="mt-4 pt-4 border-t border-gray-100">
                <label className="block text-sm font-medium text-gray-700 mb-2">시작 번호</label>
                <div className="flex items-center gap-3">
                  <input
                    type="number"
                    min="1"
                    value={startNumber}
                    onChange={(e) => setStartNumber(Math.max(1, parseInt(e.target.value) || 1))}
                    className="w-20 px-3 py-2 border border-gray-200 rounded-lg text-center focus:outline-none focus:ring-2 focus:ring-primary [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
                  />
                  <span className="text-sm text-gray-500">
                    → {String(startNumber).padStart(2, '0')}.webp ~{' '}
                    {String(startNumber + Math.max(0, pendingFiles.length - 1)).padStart(2, '0')}.webp
                  </span>
                </div>
                <p className="text-xs text-gray-400 mt-2">
                  추가 업로드 시 기존 사진 다음 번호로 설정하세요.
                </p>
              </div>
            </div>

            {/* 업로드 진행률 */}
            {saving && (
              <div className="mb-6 bg-white rounded-xl p-4 border border-gray-100 shadow-sm">
                <div className="flex items-center justify-between mb-2">
                  <div className="flex items-center gap-2">
                    <span className="w-4 h-4 border-2 border-primary/30 border-t-primary rounded-full animate-spin" />
                    {uploadProgress < 100 ? (
                      <span className="text-sm text-gray-600">파일 업로드 중...</span>
                    ) : processingProgress.current > 0 ? (
                      <span className="text-sm text-gray-600">
                        {processingStatus ||
                          `${processingProgress.current}/${processingProgress.total} 처리 중...`}
                      </span>
                    ) : (
                      <span className="text-sm text-gray-600">서버 연결 중...</span>
                    )}
                  </div>
                  <span className="text-sm font-medium text-primary">
                    {uploadProgress < 100
                      ? `${uploadProgress}%`
                      : processingProgress.total > 0
                        ? `${Math.round((processingProgress.current / processingProgress.total) * 100)}%`
                        : '0%'}
                  </span>
                </div>
                <div className="h-2 bg-gray-100 rounded-full overflow-hidden">
                  <motion.div
                    initial={{ width: 0 }}
                    animate={{
                      width:
                        uploadProgress < 100
                          ? `${uploadProgress}%`
                          : processingProgress.total > 0
                            ? `${(processingProgress.current / processingProgress.total) * 100}%`
                            : '0%',
                    }}
                    transition={{ duration: 0.3 }}
                    className="h-full bg-primary rounded-full"
                  />
                </div>
              </div>
            )}

            {/* 2-column 레이아웃 */}
            <div ref={photoListRef} className="flex gap-6">
              {/* 드래그 앤 드롭 영역 + 파일 목록 */}
              <div
                onDragEnter={handleDragEnter}
                onDragOver={handleDragOver}
                onDragLeave={handleDragLeave}
                onDrop={handleDrop}
                className={`flex-1 relative rounded-2xl border-2 border-dashed transition-colors bg-white ${
                  dragOver ? 'border-primary bg-primary/5' : 'border-gray-200'
                }`}
              >
                {/* 드래그 오버레이 */}
                {dragOver && (
                  <div className="absolute inset-0 flex items-center justify-center bg-primary/10 rounded-2xl z-10">
                    <div className="text-center">
                      <Upload size={48} className="mx-auto text-primary mb-2" />
                      <p className="text-primary font-medium">여기에 사진을 놓으세요</p>
                    </div>
                  </div>
                )}

                {pendingFiles.length === 0 ? (
                  <div className="py-20 text-center">
                    <Image size={48} className="mx-auto text-gray-300 mb-4" />
                    <p className="text-gray-500 mb-2">사진을 드래그하여 업로드하세요</p>
                    <p className="text-gray-400 text-sm mb-4">
                      {photoType === 'teaser' ? 'JPG, PNG, WebP, MP4 지원' : 'JPG, PNG, WebP 지원'}
                    </p>
                    <button
                      onClick={() => fileInputRef.current?.click()}
                      className="inline-flex items-center gap-2 px-4 py-2 bg-primary text-white rounded-lg hover:bg-primary-dark transition-colors"
                    >
                      <Plus size={18} />
                      파일 선택
                    </button>
                  </div>
                ) : (
                  <div className="p-6">
                    <div className="flex items-center justify-between mb-4">
                      <p className="text-sm text-gray-500">
                        드래그하여 순서를 변경할 수 있습니다. 순서대로{' '}
                        <code className="bg-gray-100 px-1 rounded">01.webp</code>,{' '}
                        <code className="bg-gray-100 px-1 rounded">02.webp</code>... 로 저장됩니다.
                      </p>
                      <button
                        onClick={() => fileInputRef.current?.click()}
                        className="text-sm text-primary hover:text-primary-dark transition-colors"
                      >
                        + 더 추가
                      </button>
                    </div>

                    <Reorder.Group
                      axis="y"
                      values={pendingFiles}
                      onReorder={handleReorder}
                      className="space-y-3"
                    >
                      {pendingFiles.map((file, index) => (
                        <PendingFileItem
                          key={file.id}
                          file={file}
                          index={index}
                          startNumber={startNumber}
                          photoType={photoType}
                          members={members}
                          pendingFiles={pendingFiles}
                          onPreview={setPreviewPhoto}
                          onDelete={setPendingDeleteId}
                          onUpdateFile={updatePendingFile}
                          onToggleMember={toggleMember}
                          onChangeGroupType={changeGroupType}
                          onMoveToPosition={moveToPosition}
                        />
                      ))}
                    </Reorder.Group>
                  </div>
                )}
              </div>

              {/* 일괄 편집 도구 */}
              {pendingFiles.length > 0 && photoType === 'concept' && (
                <BulkEditPanel
                  bulkEdit={bulkEdit}
                  setBulkEdit={setBulkEdit}
                  startNumber={startNumber}
                  pendingFilesCount={pendingFiles.length}
                  members={members}
                  onApply={applyBulkEdit}
                />
              )}
            </div>
          </>
        )}

        {/* 관리 탭 */}
        {activeTab === 'manage' && (
          <div className="bg-white rounded-2xl border border-gray-100 shadow-sm p-6">
            {/* 헤더 + 서브탭 */}
            <div className="flex items-center justify-between mb-4">
              <div className="flex items-center gap-3">
                <FolderOpen className="text-primary" size={24} />
                <div>
                  <h2 className="text-lg font-bold text-gray-900">등록된 미디어</h2>
                  <p className="text-sm text-gray-500">
                    컨셉 포토 {photos.length}장 / 티저 {teasers.length}장
                  </p>
                </div>
              </div>
              {selectedPhotos.length > 0 && (
                <button
                  onClick={() => setDeleteDialog({ show: true, photos: selectedPhotos })}
                  className="px-4 py-2 bg-red-50 text-red-600 rounded-lg hover:bg-red-100 transition-colors flex items-center gap-2"
                >
                  <Trash2 size={18} />
                  {selectedPhotos.length}개 삭제
                </button>
              )}
            </div>

            {/* 서브탭 + 전체 선택 */}
            <div className="flex items-center justify-between mb-6 border-b border-gray-100">
              <div className="flex gap-2">
                <button
                  onClick={() => {
                    setManageSubTab('concept');
                    setSelectedPhotos([]);
                  }}
                  className={`px-4 py-2 font-medium transition-colors relative ${
                    manageSubTab === 'concept' ? 'text-primary' : 'text-gray-500 hover:text-gray-700'
                  }`}
                >
                  컨셉 포토
                  <span className="ml-1.5 text-xs bg-gray-100 px-1.5 py-0.5 rounded">
                    {photos.length}
                  </span>
                  {manageSubTab === 'concept' && (
                    <div className="absolute bottom-0 left-0 right-0 h-0.5 bg-primary" />
                  )}
                </button>
                <button
                  onClick={() => {
                    setManageSubTab('teaser');
                    setSelectedPhotos([]);
                  }}
                  className={`px-4 py-2 font-medium transition-colors relative ${
                    manageSubTab === 'teaser' ? 'text-primary' : 'text-gray-500 hover:text-gray-700'
                  }`}
                >
                  티저 이미지
                  <span className="ml-1.5 text-xs bg-gray-100 px-1.5 py-0.5 rounded">
                    {teasers.length}
                  </span>
                  {manageSubTab === 'teaser' && (
                    <div className="absolute bottom-0 left-0 right-0 h-0.5 bg-primary" />
                  )}
                </button>
              </div>
              <button
                onClick={() => {
                  if (manageSubTab === 'concept') {
                    const allSelected =
                      photos.length > 0 && photos.every((p) => selectedPhotos.includes(p.id));
                    setSelectedPhotos(allSelected ? [] : photos.map((p) => p.id));
                  } else {
                    const allSelected =
                      teasers.length > 0 &&
                      teasers.every((t) => selectedPhotos.includes(`teaser-${t.id}`));
                    setSelectedPhotos(allSelected ? [] : teasers.map((t) => `teaser-${t.id}`));
                  }
                }}
                className="text-sm text-gray-500 hover:text-primary transition-colors"
              >
                {manageSubTab === 'concept'
                  ? photos.length > 0 && photos.every((p) => selectedPhotos.includes(p.id))
                    ? '선택 해제'
                    : '전체 선택'
                  : teasers.length > 0 &&
                      teasers.every((t) => selectedPhotos.includes(`teaser-${t.id}`))
                    ? '선택 해제'
                    : '전체 선택'}
              </button>
            </div>

            {/* 컨셉 포토 그리드 */}
            {manageSubTab === 'concept' && (
              <PhotoGrid
                items={photos}
                selectedItems={selectedPhotos}
                onToggleSelect={(id) => {
                  setSelectedPhotos((prev) =>
                    prev.includes(id) ? prev.filter((i) => i !== id) : [...prev, id]
                  );
                }}
                type="concept"
              />
            )}

            {/* 티저 이미지 그리드 */}
            {manageSubTab === 'teaser' && (
              <PhotoGrid
                items={teasers}
                selectedItems={selectedPhotos}
                onToggleSelect={(id) => {
                  setSelectedPhotos((prev) =>
                    prev.includes(id) ? prev.filter((i) => i !== id) : [...prev, id]
                  );
                }}
                type="teaser"
              />
            )}
          </div>
        )}

        {/* 삭제 확인 다이얼로그 */}
        <AnimatePresence>
          {pendingDeleteId && (
            <motion.div
              initial={{ opacity: 0 }}
              animate={{ opacity: 1 }}
              exit={{ opacity: 0 }}
              className="fixed inset-0 bg-black/50 flex items-center justify-center z-50"
              onClick={() => setPendingDeleteId(null)}
            >
              <motion.div
                initial={{ scale: 0.9, opacity: 0 }}
                animate={{ scale: 1, opacity: 1 }}
                exit={{ scale: 0.9, opacity: 0 }}
                onClick={(e) => e.stopPropagation()}
                className="bg-white rounded-2xl p-6 max-w-sm w-full mx-4 shadow-xl"
              >
                <div className="text-center">
                  <div className="w-12 h-12 bg-red-100 rounded-full flex items-center justify-center mx-auto mb-4">
                    <Trash2 className="text-red-500" size={24} />
                  </div>
                  <h3 className="text-lg font-bold text-gray-900 mb-2">사진을 삭제할까요?</h3>
                  <p className="text-gray-500 text-sm mb-6">이 사진을 목록에서 제거합니다.</p>
                  <div className="flex gap-3">
                    <button
                      onClick={() => setPendingDeleteId(null)}
                      className="flex-1 px-4 py-2 bg-gray-100 text-gray-700 rounded-lg hover:bg-gray-200 transition-colors"
                    >
                      취소
                    </button>
                    <button
                      onClick={confirmDeletePendingFile}
                      className="flex-1 px-4 py-2 bg-red-500 text-white rounded-lg hover:bg-red-600 transition-colors"
                    >
                      삭제
                    </button>
                  </div>
                </div>
              </motion.div>
            </motion.div>
          )}
        </AnimatePresence>

        {/* 업로드 확인 다이얼로그 */}
        <AnimatePresence>
          {uploadConfirmDialog && (
            <motion.div
              initial={{ opacity: 0 }}
              animate={{ opacity: 1 }}
              exit={{ opacity: 0 }}
              className="fixed inset-0 bg-black/50 flex items-center justify-center z-50"
              onClick={() => setUploadConfirmDialog(false)}
            >
              <motion.div
                initial={{ scale: 0.9, opacity: 0 }}
                animate={{ scale: 1, opacity: 1 }}
                exit={{ scale: 0.9, opacity: 0 }}
                onClick={(e) => e.stopPropagation()}
                className="bg-white rounded-2xl p-6 max-w-md w-full mx-4 shadow-xl"
              >
                <div className="text-center">
                  <div className="w-12 h-12 bg-primary/10 rounded-full flex items-center justify-center mx-auto mb-4">
                    <Upload className="text-primary" size={24} />
                  </div>
                  <h3 className="text-lg font-bold text-gray-900 mb-2">사진을 업로드할까요?</h3>
                  <div className="text-gray-500 text-sm mb-6 text-left bg-gray-50 rounded-lg p-4">
                    <div className="flex justify-between mb-1">
                      <span>사진 타입:</span>
                      <span className="font-medium text-gray-700">
                        {photoType === 'concept' ? '컨셉 포토' : '티저 이미지'}
                      </span>
                    </div>
                    <div className="flex justify-between mb-1">
                      <span>파일 개수:</span>
                      <span className="font-medium text-gray-700">{pendingFiles.length}개</span>
                    </div>
                    <div className="flex justify-between">
                      <span>파일명 범위:</span>
                      <span className="font-medium text-gray-700">
                        {String(startNumber).padStart(2, '0')}.webp ~{' '}
                        {String(startNumber + pendingFiles.length - 1).padStart(2, '0')}.webp
                      </span>
                    </div>
                  </div>
                  <div className="flex gap-3">
                    <button
                      onClick={() => setUploadConfirmDialog(false)}
                      className="flex-1 px-4 py-2 bg-gray-100 text-gray-700 rounded-lg hover:bg-gray-200 transition-colors"
                    >
                      취소
                    </button>
                    <button
                      onClick={() => {
                        setUploadConfirmDialog(false);
                        handleUpload();
                      }}
                      className="flex-1 px-4 py-2 bg-primary text-white rounded-lg hover:bg-primary-dark transition-colors"
                    >
                      업로드
                    </button>
                  </div>
                </div>
              </motion.div>
            </motion.div>
          )}
        </AnimatePresence>

        <input
          ref={fileInputRef}
          type="file"
          multiple
          accept={photoType === 'teaser' ? 'image/*,video/mp4' : 'image/*'}
          onChange={handleFileSelect}
          className="hidden"
        />
      </div>
    </AdminLayout>
  );
}

export default AdminAlbumPhotos;
