import { useState, useEffect, useRef, useCallback, useMemo } from 'react';
import { useNavigate, Link, useParams } from 'react-router-dom';
import { motion, AnimatePresence, Reorder } from 'framer-motion';
import { 
    Upload, Trash2, Image, X, Check, Plus,
    Home, ChevronRight, LogOut, ArrowLeft, Grid, List,
    ZoomIn, AlertTriangle, GripVertical, Users, User, Users2,
    Tag, FolderOpen, Save
} from 'lucide-react';
import Toast from '../../../components/Toast';

function AdminAlbumPhotos() {
    const { albumId } = useParams();
    const navigate = useNavigate();
    const fileInputRef = useRef(null);
    const photoListRef = useRef(null); // 사진 목록 영역 ref

    const [album, setAlbum] = useState(null);
    const [photos, setPhotos] = useState([]);
    const [teasers, setTeasers] = useState([]); // 티저 이미지
    const [loading, setLoading] = useState(true);
    const [user, setUser] = useState(null);
    const [toast, setToast] = useState(null);
    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 [members, setMembers] = useState([]); // DB에서 로드

    // 업로드 대기 중인 파일들
    const [pendingFiles, setPendingFiles] = useState([]);
    const [photoType, setPhotoType] = useState('concept'); // 'concept' | 'teaser'
    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); // 삭제 대기 파일 ID
    const [uploadConfirmDialog, setUploadConfirmDialog] = useState(false); // 업로드 확인 다이얼로그
    const [activeTab, setActiveTab] = useState('upload'); // 'upload' | 'manage'
    const [manageSubTab, setManageSubTab] = useState('concept'); // 'concept' | 'teaser'

    // 일괄 편집 도구 상태
    const [bulkEdit, setBulkEdit] = useState({
        range: '',           // 예: "1-5, 8, 10-12"
        groupType: '',       // 'group' | 'solo' | 'unit' | ''(미적용)
        members: [],         // 선택된 멤버들
        conceptName: '',     // 컨셉명
    });

    // 범위 문자열 파싱 (표시 번호 기준, 예: "18-22" → [0, 1, 2, 3, 4])
    const parseRange = (rangeStr, baseNumber = 1) => {
        if (!rangeStr.trim()) return [];
        const indices = new Set();
        const parts = rangeStr.split(',').map(s => s.trim());
        
        for (const part of parts) {
            if (part.includes('-')) {
                const [start, end] = part.split('-').map(n => parseInt(n.trim()));
                if (!isNaN(start) && !isNaN(end)) {
                    for (let i = Math.min(start, end); i <= Math.max(start, end); i++) {
                        // 표시 번호를 0-indexed로 변환
                        const idx = i - baseNumber;
                        if (idx >= 0) indices.add(idx);
                    }
                }
            } else {
                const num = parseInt(part);
                if (!isNaN(num)) {
                    const idx = num - baseNumber;
                    if (idx >= 0) indices.add(idx);
                }
            }
        }
        return Array.from(indices).sort((a, b) => a - b);
    };

    // 일괄 편집 적용
    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 toggleBulkMember = (memberId) => {
        setBulkEdit(prev => ({
            ...prev,
            members: prev.members.includes(memberId)
                ? prev.members.filter(m => m !== memberId)
                : [...prev.members, memberId]
        }));
    };

    // Toast 자동 숨김
    useEffect(() => {
        if (toast) {
            const timer = setTimeout(() => setToast(null), 3000);
            return () => clearTimeout(timer);
        }
    }, [toast]);

    useEffect(() => {
        // 로그인 확인
        const token = localStorage.getItem('adminToken');
        const userData = localStorage.getItem('adminUser');

        if (!token || !userData) {
            navigate('/admin');
            return;
        }

        setUser(JSON.parse(userData));
        fetchAlbumData();
    }, [navigate, albumId]);

    const fetchAlbumData = async () => {
        try {
            const token = localStorage.getItem('adminToken');
            
            // 앨범 정보 로드
            const albumRes = await fetch(`/api/albums/${albumId}`);
            if (!albumRes.ok) throw new Error('앨범을 찾을 수 없습니다');
            const albumData = await albumRes.json();
            setAlbum(albumData);

            // 멤버 목록 로드
            const membersRes = await fetch('/api/members');
            if (membersRes.ok) {
                const membersData = await membersRes.json();
                setMembers(membersData);
            }

            // 기존 컨셉 포토 목록 로드
            const photosRes = await fetch(`/api/admin/albums/${albumId}/photos`, {
                headers: { 'Authorization': `Bearer ${token}` }
            });
            let photosData = [];
            if (photosRes.ok) {
                photosData = await photosRes.json();
                setPhotos(photosData);
            }

            // 티저 이미지 목록 로드
            const teasersRes = await fetch(`/api/admin/albums/${albumId}/teasers`, {
                headers: { 'Authorization': `Bearer ${token}` }
            });
            let teasersData = [];
            if (teasersRes.ok) {
                teasersData = await teasersRes.json();
                setTeasers(teasersData);
            }

            // 시작 번호 자동 설정 (현재 선택된 타입의 마지막 + 1)
            // 컨셉 포토는 컨셉 포토끼리, 티저는 티저끼리 번호 계산
            const maxPhotoOrder = photosData.length > 0 
                ? Math.max(...photosData.map(p => p.sort_order || 0)) 
                : 0;
            const maxTeaserOrder = teasersData.length > 0 
                ? Math.max(...teasersData.map(t => t.sort_order || 0)) 
                : 0;
            
            // 기본값은 컨셉 포토 기준
            setStartNumber(maxPhotoOrder + 1);
            
            setLoading(false);
        } catch (error) {
            console.error('앨범 로드 오류:', error);
            setToast({ message: error.message, type: 'error' });
            setLoading(false);
        }
    };

    // 타입 변경 시 시작 번호 자동 업데이트
    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 handleLogout = () => {
        localStorage.removeItem('adminToken');
        localStorage.removeItem('adminUser');
        navigate('/admin');
    };

    // 파일 선택
    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', // 'group' | 'solo' | 'unit'
            members: [], // 태깅된 멤버들 (단체일 경우 빈 배열)
            conceptName: '', // 개별 컨셉명
        }));
        setPendingFiles(prev => [...prev, ...newFiles]);
    };

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

    // 직접 순서 변경 (입력으로) - 입력값은 startNumber 기준
    const moveToPosition = (fileId, newPosition) => {
        const pos = parseInt(newPosition, 10);
        // 시작 번호보다 작거나 유효하지 않으면 무시
        if (isNaN(pos) || pos < startNumber) return;
        
        setPendingFiles(prev => {
            // 입력값에서 startNumber를 빼서 배열 인덱스 계산
            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 = localStorage.getItem('adminToken');
            
            // FormData 생성
            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);

            // 업로드 진행률 + SSE로 서버 처리 진행률
            const response = await fetch(`/api/admin/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' });
                // 시작 번호는 fetchAlbumData 후 useEffect에서 자동 업데이트됨
            }
            
            // 미리보기 URL 해제
            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);
        const token = localStorage.getItem('adminToken');

        try {
            // 사진 ID와 티저 ID 분리
            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) {
                const res = await fetch(`/api/admin/albums/${albumId}/photos/${photoId}`, {
                    method: 'DELETE',
                    headers: { 'Authorization': `Bearer ${token}` }
                });
                if (!res.ok) {
                    throw new Error('사진 삭제 실패');
                }
            }

            // 티저 삭제
            for (const teaserId of teaserIds) {
                const res = await fetch(`/api/admin/albums/${albumId}/teasers/${teaserId}`, {
                    method: 'DELETE',
                    headers: { 'Authorization': `Bearer ${token}` }
                });
                if (!res.ok) {
                    throw new Error('티저 삭제 실패');
                }
            }

            // UI 상태 업데이트
            setPhotos(prev => prev.filter(p => !photoIds.includes(p.id)));
            setTeasers(prev => prev.filter(t => !teaserIds.includes(t.id)));
            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 (
            <div className="min-h-screen bg-gray-50 flex items-center justify-center">
                <div className="animate-spin rounded-full h-12 w-12 border-4 border-primary border-t-transparent"></div>
            </div>
        );
    }

    return (
        <div className="min-h-screen bg-gray-50">
            {/* Toast */}
            <Toast toast={toast} onClose={() => setToast(null)} />

            {/* 삭제 확인 다이얼로그 */}
            <AnimatePresence>
                {deleteDialog.show && (
                    <motion.div
                        initial={{ opacity: 0 }}
                        animate={{ opacity: 1 }}
                        exit={{ opacity: 0 }}
                        className="fixed inset-0 z-50 flex items-center justify-center bg-black/50"
                        onClick={() => !deleting && setDeleteDialog({ show: false, photos: [] })}
                    >
                        <motion.div
                            initial={{ scale: 0.9, opacity: 0 }}
                            animate={{ scale: 1, opacity: 1 }}
                            exit={{ scale: 0.9, opacity: 0 }}
                            className="bg-white rounded-2xl p-6 max-w-md w-full mx-4 shadow-xl"
                            onClick={(e) => e.stopPropagation()}
                        >
                            <div className="flex items-center gap-3 mb-4">
                                <div className="w-10 h-10 rounded-full bg-red-100 flex items-center justify-center">
                                    <AlertTriangle className="text-red-500" size={20} />
                                </div>
                                <h3 className="text-lg font-bold text-gray-900">사진 삭제</h3>
                            </div>
                            
                            <p className="text-gray-600 mb-6">
                                <span className="font-medium text-gray-900">{deleteDialog.photos.length}개</span>의 사진을 삭제하시겠습니까?
                                <br />
                                <span className="text-sm text-red-500">이 작업은 되돌릴 수 없습니다.</span>
                            </p>
                            
                            <div className="flex justify-end gap-3">
                                <button
                                    onClick={() => setDeleteDialog({ show: false, photos: [] })}
                                    disabled={deleting}
                                    className="px-4 py-2 text-gray-600 hover:text-gray-900 hover:bg-gray-100 rounded-lg transition-colors disabled:opacity-50"
                                >
                                    취소
                                </button>
                                <button
                                    onClick={handleDelete}
                                    disabled={deleting}
                                    className="px-4 py-2 bg-red-500 text-white rounded-lg hover:bg-red-600 transition-colors disabled:opacity-50 flex items-center gap-2"
                                >
                                    {deleting ? (
                                        <>
                                            <span className="w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin" />
                                            삭제 중...
                                        </>
                                    ) : (
                                        <>
                                            <Trash2 size={16} />
                                            삭제
                                        </>
                                    )}
                                </button>
                            </div>
                        </motion.div>
                    </motion.div>
                )}
            </AnimatePresence>

            {/* 이미지 미리보기 */}
            <AnimatePresence>
                {previewPhoto && (
                    <motion.div
                        initial={{ opacity: 0 }}
                        animate={{ opacity: 1 }}
                        exit={{ opacity: 0 }}
                        className="fixed inset-0 z-50 flex items-center justify-center bg-black/90"
                        onClick={() => setPreviewPhoto(null)}
                    >
                        <button
                            onClick={() => setPreviewPhoto(null)}
                            className="absolute top-4 right-4 p-2 text-white/70 hover:text-white transition-colors"
                        >
                            <X size={24} />
                        </button>
                        {previewPhoto.isVideo ? (
                            <motion.video
                                initial={{ scale: 0.9 }}
                                animate={{ scale: 1 }}
                                exit={{ scale: 0.9 }}
                                src={previewPhoto.preview || previewPhoto.url}
                                className="max-w-[90vw] max-h-[90vh] object-contain"
                                onClick={(e) => e.stopPropagation()}
                                controls
                                autoPlay
                            />
                        ) : (
                            <motion.img
                                initial={{ scale: 0.9 }}
                                animate={{ scale: 1 }}
                                exit={{ scale: 0.9 }}
                                src={previewPhoto.preview || previewPhoto.url}
                                alt={previewPhoto.filename}
                                className="max-w-[90vw] max-h-[90vh] object-contain"
                                onClick={(e) => e.stopPropagation()}
                            />
                        )}
                    </motion.div>
                )}
            </AnimatePresence>

            {/* 헤더 */}
            <header className="bg-white shadow-sm border-b border-gray-100">
                <div className="max-w-7xl mx-auto px-6 py-4 flex items-center justify-between">
                    <div className="flex items-center gap-4">
                        <Link to="/admin/dashboard" className="text-2xl font-bold text-primary hover:opacity-80 transition-opacity">
                            fromis_9
                        </Link>
                        <span className="px-3 py-1 bg-primary/10 text-primary text-sm font-medium rounded-full">
                            Admin
                        </span>
                    </div>
                    <div className="flex items-center gap-4">
                        <span className="text-gray-500 text-sm">
                            안녕하세요, <span className="text-gray-900 font-medium">{user?.username}</span>님
                        </span>
                        <button
                            onClick={handleLogout}
                            className="flex items-center gap-2 px-4 py-2 text-gray-500 hover:text-gray-900 hover:bg-gray-100 rounded-lg transition-colors"
                        >
                            <LogOut size={18} />
                            <span>로그아웃</span>
                        </button>
                    </div>
                </div>
            </header>

            {/* 메인 콘텐츠 */}
            <main className="max-w-7xl mx-auto px-6 py-8">
                {/* 브레드크럼 */}
                <motion.div 
                    className="flex items-center gap-2 text-sm text-gray-400 mb-8"
                    initial={{ opacity: 0, x: -10 }}
                    animate={{ opacity: 1, x: 0 }}
                    transition={{ delay: 0.1 }}
                >
                    <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>
                </motion.div>

                {/* 타이틀 + 액션 버튼 */}
                <motion.div 
                    className="flex items-center justify-between mb-8"
                    initial={{ opacity: 0, y: 10 }}
                    animate={{ opacity: 1, y: 0 }}
                    transition={{ delay: 0.15 }}
                >
                    <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' && (
                <>

                {/* 업로드 설정 */}
                <motion.div 
                    className="bg-white rounded-2xl border border-gray-100 shadow-sm p-6 mb-6"
                    initial={{ opacity: 0, y: 10 }}
                    animate={{ opacity: 1, y: 0 }}
                >
                    <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>
                </motion.div>

                {/* 업로드 진행률 */}
                {saving && (
                    <motion.div
                        initial={{ opacity: 0, y: -10 }}
                        animate={{ opacity: 1, y: 0 }}
                        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>
                    </motion.div>
                )}

                {/* 2-column 레이아웃: 사진 목록 + 일괄 편집 패널 */}
                <div ref={photoListRef} className="flex gap-6">
                    {/* 드래그 앤 드롭 영역 + 파일 목록 */}
                    <motion.div
                        onDragEnter={handleDragEnter}
                        onDragOver={handleDragOver}
                        onDragLeave={handleDragLeave}
                        onDrop={handleDrop}
                        initial={{ opacity: 0, y: 20 }}
                        animate={{ opacity: 1, y: 0 }}
                        transition={{ delay: 0.25 }}
                        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) => (
                                    <Reorder.Item
                                        key={file.id}
                                        value={file}
                                        className="bg-gray-50 rounded-xl p-4 cursor-grab active:cursor-grabbing"
                                    >
                                        <div className="flex gap-4 items-center">
                                            {/* 드래그 핸들 + 순서 번호 (직접 입력 가능) */}
                                            <div className="flex items-center gap-2">
                                                <GripVertical size={18} className="text-gray-300" />
                                                <input
                                                    type="text"
                                                    inputMode="numeric"
                                                    defaultValue={String(startNumber + index).padStart(2, '0')}
                                                    key={`order-${file.id}-${index}-${startNumber}`}
                                                    onBlur={(e) => {
                                                        const val = e.target.value.trim();
                                                        // 스크롤 위치 저장
                                                        const scrollY = window.scrollY;
                                                        const currentIndex = pendingFiles.findIndex(f => f.id === file.id);
                                                        const currentOrder = startNumber + currentIndex;
                                                        
                                                        // 값이 변경된 경우에만 이동
                                                        if (val && !isNaN(val) && parseInt(val) !== currentOrder) {
                                                            moveToPosition(file.id, val);
                                                        }
                                                        
                                                        // 현재 위치 기준으로 값 복원
                                                        const newIndex = pendingFiles.findIndex(f => f.id === file.id);
                                                        e.target.value = String(startNumber + newIndex).padStart(2, '0');
                                                        
                                                        // 스크롤 위치 복원
                                                        requestAnimationFrame(() => {
                                                            window.scrollTo(0, scrollY);
                                                        });
                                                    }}
                                                    onKeyDown={(e) => {
                                                        if (e.key === 'Enter') {
                                                            e.target.blur();
                                                        }
                                                    }}
                                                    className="w-10 h-8 bg-primary/10 text-primary rounded-lg text-center text-sm font-bold border-0 focus:outline-none focus:ring-2 focus:ring-primary [appearance:textfield]"
                                                />
                                            </div>

                                            {/* 썸네일 (180px로 확대) */}
                                            {file.isVideo ? (
                                                <div className="relative w-[180px] h-[180px] flex-shrink-0">
                                                    <video
                                                        src={file.preview}
                                                        className="w-full h-full rounded-lg object-cover cursor-pointer hover:opacity-80 transition-opacity select-none"
                                                        onClick={() => setPreviewPhoto(file)}
                                                        muted
                                                    />
                                                    {/* 재생 버튼 오버레이 */}
                                                    <div 
                                                        className="absolute inset-0 flex items-center justify-center bg-black/30 rounded-lg cursor-pointer"
                                                        onClick={() => setPreviewPhoto(file)}
                                                    >
                                                        <div className="w-12 h-12 bg-white/90 rounded-full flex items-center justify-center">
                                                            <div className="w-0 h-0 border-l-[14px] border-l-gray-800 border-y-[8px] border-y-transparent ml-1" />
                                                        </div>
                                                    </div>
                                                </div>
                                            ) : (
                                                <img
                                                    src={file.preview}
                                                    alt={file.filename}
                                                    draggable="false"
                                                    loading="lazy"
                                                    className="w-[180px] h-[180px] rounded-lg object-cover cursor-pointer hover:opacity-80 transition-opacity flex-shrink-0 select-none"
                                                    onClick={() => setPreviewPhoto(file)}
                                                />
                                            )}

                                            {/* 메타 정보 - 고정 높이 */}
                                            <div className="flex-1 space-y-3 h-[200px] overflow-hidden">
                                                {/* 파일명 */}
                                                <p className="text-base font-medium text-gray-900 truncate">{file.filename}</p>

                                                {/* 컨셉 포토일 때만 메타 정보 입력 표시 */}
                                                {photoType === 'concept' && (
                                                    <>
                                                        {/* 단체/솔로/유닛 선택 */}
                                                        <div className="flex items-center gap-2">
                                                            <span className="text-sm text-gray-500 w-16">타입:</span>
                                                            <div className="flex gap-1.5">
                                                                {[
                                                                    { value: 'group', icon: Users, label: '단체' },
                                                                    { value: 'solo', icon: User, label: '개인' },
                                                                    { value: 'unit', icon: Users2, label: '유닛' },
                                                                ].map(({ value, icon: Icon, label }) => (
                                                                    <button
                                                                        key={value}
                                                                        onClick={() => changeGroupType(file.id, value)}
                                                                        className={`flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-sm transition-colors ${
                                                                            file.groupType === value
                                                                                ? 'bg-primary text-white'
                                                                                : 'bg-white text-gray-600 hover:bg-gray-100 border border-gray-200'
                                                                        }`}
                                                                    >
                                                                        <Icon size={14} />
                                                                        {label}
                                                                    </button>
                                                                ))}
                                                            </div>
                                                        </div>

                                                        {/* 멤버 태깅 (단체는 비활성화) */}
                                                        <div className="flex flex-col gap-2 min-h-8">
                                                            <div className="flex items-center gap-2 flex-wrap">
                                                                <span className="text-sm text-gray-500 w-16">멤버:</span>
                                                                {file.groupType === 'group' ? (
                                                                    <span className="text-sm text-gray-400">단체 사진은 멤버 태깅이 필요 없습니다</span>
                                                                ) : (
                                                                    <>
                                                                        {/* 현재 멤버 */}
                                                                        {members.filter(m => !m.is_former).map(member => (
                                                                            <button
                                                                                key={member.id}
                                                                                onClick={() => toggleMember(file.id, member.id)}
                                                                                className={`px-3 py-1 rounded-full text-sm transition-colors ${
                                                                                    file.members.includes(member.id)
                                                                                        ? 'bg-primary text-white border border-primary'
                                                                                        : 'bg-white text-gray-600 hover:bg-gray-100 border border-gray-200'
                                                                                }`}
                                                                            >
                                                                                {member.name}
                                                                            </button>
                                                                        ))}
                                                                    </>
                                                                )}

                                                            </div>
                                                            {/* 전 멤버 (다음 줄) */}
                                                            {file.groupType !== 'group' && members.filter(m => m.is_former).length > 0 && (
                                                                <div className="flex items-center gap-2 flex-wrap">
                                                                    <span className="text-sm text-gray-400 w-16"></span>
                                                                    {members.filter(m => m.is_former).map(member => (
                                                                        <button
                                                                            key={member.id}
                                                                            onClick={() => toggleMember(file.id, member.id)}
                                                                            className={`px-3 py-1 rounded-full text-sm transition-colors ${
                                                                                file.members.includes(member.id)
                                                                                    ? 'bg-gray-500 text-white border border-gray-500'
                                                                                    : 'bg-gray-100 text-gray-400 hover:bg-gray-200 border border-gray-200'
                                                                            }`}
                                                                        >
                                                                            {member.name}
                                                                        </button>
                                                                    ))}
                                                                </div>
                                                            )}
                                                        </div>

                                                        {/* 컨셉/티저 이름 (개별 입력) */}
                                                        <div className="flex items-center gap-2">
                                                            <span className="text-sm text-gray-500 w-16">컨셉명:</span>
                                                            <input
                                                                type="text"
                                                                value={file.conceptName}
                                                                onChange={(e) => updatePendingFile(file.id, 'conceptName', e.target.value)}
                                                                className="flex-1 px-3 py-1.5 text-sm border border-gray-200 rounded-lg focus:outline-none focus:ring-1 focus:ring-primary"
                                                                placeholder="컨셉명을 입력하세요"
                                                            />
                                                        </div>
                                                    </>
                                                )}
                                            </div>

                                            {/* 삭제 버튼 */}
                                            <button
                                                onClick={() => setPendingDeleteId(file.id)}
                                                className="p-2 text-gray-400 hover:text-red-500 hover:bg-red-50 rounded-lg transition-colors self-start"
                                            >
                                                <Trash2 size={18} />
                                            </button>
                                        </div>
                                    </Reorder.Item>
                                ))}
                            </Reorder.Group>
                        </div>
                    )}
                    </motion.div>

                    {/* 일괄 편집 도구 - CSS sticky (네이티브 성능) */}
                    {pendingFiles.length > 0 && photoType === 'concept' && (
                        <div className="w-72 flex-shrink-0">
                            <div className="sticky top-24 bg-white rounded-2xl shadow-lg border border-gray-100 p-5">
                                <h3 className="font-bold text-gray-900 mb-4 flex items-center gap-2">
                                    <Tag size={18} className="text-primary" />
                                일괄 편집
                            </h3>
                            
                            {/* 번호 범위 */}
                            <div className="mb-4">
                                <label className="block text-sm font-medium text-gray-700 mb-1.5">번호 범위</label>
                                <input
                                    type="text"
                                    value={bulkEdit.range}
                                    onChange={(e) => setBulkEdit(prev => ({ ...prev, range: e.target.value }))}
                                    placeholder={`예: ${startNumber}-${startNumber + 4}, ${startNumber + 7}`}
                                    className="w-full px-3 py-2 text-sm border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary"
                                />
                                <p className="text-xs text-gray-400 mt-1">
                                    {startNumber}~{startNumber + pendingFiles.length - 1}번 중 {parseRange(bulkEdit.range, startNumber).filter(i => i < pendingFiles.length).length}개 선택
                                </p>
                            </div>

                            {/* 타입 선택 */}
                            <div className="mb-4">
                                <label className="block text-sm font-medium text-gray-700 mb-1.5">타입</label>
                                <div className="flex gap-1">
                                    {[
                                        { value: 'group', icon: Users, label: '단체' },
                                        { value: 'solo', icon: User, label: '개인' },
                                        { value: 'unit', icon: Users2, label: '유닛' },
                                    ].map(({ value, icon: Icon, label }) => (
                                        <button
                                            key={value}
                                            onClick={() => setBulkEdit(prev => ({ 
                                                ...prev, 
                                                groupType: prev.groupType === value ? '' : value,
                                                members: value === 'group' ? [] : prev.members
                                            }))}
                                            className={`flex-1 py-1.5 px-2 rounded-lg text-xs font-medium transition-colors flex items-center justify-center gap-1 ${
                                                bulkEdit.groupType === value
                                                    ? 'bg-primary text-white'
                                                    : 'bg-gray-100 text-gray-600 hover:bg-gray-200'
                                            }`}
                                        >
                                            <Icon size={14} />
                                            {label}
                                        </button>
                                    ))}
                                </div>
                            </div>

                            {/* 멤버 선택 */}
                            {bulkEdit.groupType !== 'group' && (
                                <div className="mb-4">
                                    <label className="block text-sm font-medium text-gray-700 mb-1.5">
                                        멤버 {bulkEdit.groupType === 'solo' ? '(1명)' : '(다중 선택)'}
                                    </label>
                                    <div className="flex flex-wrap gap-1.5">
                                        {/* 현재 멤버 */}
                                        {members.filter(m => !m.is_former).map(member => (
                                            <button
                                                key={member.id}
                                                onClick={() => {
                                                    if (bulkEdit.groupType === 'solo') {
                                                        setBulkEdit(prev => ({
                                                            ...prev,
                                                            members: prev.members.includes(member.id) ? [] : [member.id]
                                                        }));
                                                    } else {
                                                        toggleBulkMember(member.id);
                                                    }
                                                }}
                                                className={`px-2.5 py-1 rounded-full text-xs font-medium transition-colors ${
                                                    bulkEdit.members.includes(member.id)
                                                        ? 'bg-primary text-white border border-primary'
                                                        : 'bg-gray-100 text-gray-600 hover:bg-gray-200 border border-gray-100'
                                                }`}
                                            >
                                                {member.name}
                                            </button>
                                        ))}
                                        {/* 구분선 */}
                                        {members.filter(m => m.is_former).length > 0 && (
                                            <span className="text-gray-300 mx-1">|</span>
                                        )}
                                        {/* 탈퇴 멤버 */}
                                        {members.filter(m => m.is_former).map(member => (
                                            <button
                                                key={member.id}
                                                onClick={() => {
                                                    if (bulkEdit.groupType === 'solo') {
                                                        setBulkEdit(prev => ({
                                                            ...prev,
                                                            members: prev.members.includes(member.id) ? [] : [member.id]
                                                        }));
                                                    } else {
                                                        toggleBulkMember(member.id);
                                                    }
                                                }}
                                                className={`px-2.5 py-1 rounded-full text-xs font-medium transition-colors ${
                                                    bulkEdit.members.includes(member.id)
                                                        ? 'bg-gray-500 text-white border border-gray-500'
                                                        : 'bg-gray-100 text-gray-400 hover:bg-gray-200 border border-gray-100'
                                                }`}
                                            >
                                                {member.name}
                                            </button>
                                        ))}
                                    </div>
                                </div>
                            )}

                            {/* 컨셉명 */}
                            <div className="mb-4">
                                <label className="block text-sm font-medium text-gray-700 mb-1.5">컨셉명</label>
                                <input
                                    type="text"
                                    value={bulkEdit.conceptName}
                                    onChange={(e) => setBulkEdit(prev => ({ ...prev, conceptName: e.target.value }))}
                                    placeholder="컨셉명 입력"
                                    className="w-full px-3 py-2 text-sm border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary"
                                />
                            </div>

                            {/* 적용 버튼 */}
                            <button
                                onClick={applyBulkEdit}
                                disabled={!bulkEdit.range.trim()}
                                className={`w-full py-2.5 rounded-lg font-medium transition-colors flex items-center justify-center gap-2 ${
                                    bulkEdit.range.trim()
                                        ? 'bg-primary text-white hover:bg-primary/90'
                                        : 'bg-gray-100 text-gray-400 cursor-not-allowed'
                                }`}
                            >
                                <Check size={18} />
                                일괄 적용
                            </button>
                            </div>
                        </div>
                    )}
                </div>
                </>
                )}

                {/* 관리 탭 */}
                {activeTab === 'manage' && (
                    <motion.div
                        initial={{ opacity: 0, y: 10 }}
                        animate={{ opacity: 1, y: 0 }}
                        transition={{ duration: 0.3 }}
                        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' && (
                            <>
                                {photos.length === 0 ? (
                                    <div className="text-center py-16">
                                        <Image className="mx-auto text-gray-300 mb-4" size={48} />
                                        <p className="text-gray-500">등록된 컨셉 포토가 없습니다</p>
                                        <p className="text-gray-400 text-sm mt-1">업로드 탭에서 사진을 추가하세요</p>
                                    </div>
                                ) : (
                                    <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6 gap-3">
                                        {photos.map((photo, index) => (
                                            <motion.div
                                                key={photo.id}
                                                initial={{ opacity: 0, scale: 0.9 }}
                                                animate={{ opacity: 1, scale: 1 }}
                                                transition={{ duration: 0.2, delay: index < 20 ? index * 0.02 : 0 }}
                                                className={`relative group aspect-square rounded-lg overflow-hidden cursor-pointer border-2 transition-all duration-200 ${
                                                    selectedPhotos.includes(photo.id)
                                                        ? 'border-primary ring-2 ring-primary/30 scale-[0.98]'
                                                        : 'border-transparent hover:border-primary/50 hover:shadow-lg'
                                                }`}
                                                onClick={() => {
                                                    setSelectedPhotos(prev =>
                                                        prev.includes(photo.id)
                                                            ? prev.filter(id => id !== photo.id)
                                                            : [...prev, photo.id]
                                                    );
                                                }}
                                            >
                                                <img
                                                    src={photo.thumb_url || photo.medium_url}
                                                    alt={`사진 ${photo.sort_order}`}
                                                    loading="lazy"
                                                    className="w-full h-full object-cover transition-transform duration-200 group-hover:scale-105"
                                                />
                                                {/* 호버 시 반투명 오버레이 */}
                                                <div className="absolute inset-0 bg-primary/10 opacity-0 group-hover:opacity-100 transition-opacity duration-200 pointer-events-none" />
                                                
                                                {/* 체크박스 오버레이 */}
                                                <div className={`absolute top-2 left-2 w-6 h-6 rounded-full border-2 flex items-center justify-center transition-all ${
                                                    selectedPhotos.includes(photo.id)
                                                        ? 'bg-primary border-primary'
                                                        : 'bg-white/80 border-gray-300 opacity-0 group-hover:opacity-100'
                                                }`}>
                                                    {selectedPhotos.includes(photo.id) && (
                                                        <Check size={14} className="text-white" />
                                                    )}
                                                </div>

                                                {/* 순서 번호 뱃지 */}
                                                <div className="absolute top-2 right-2 px-2 py-0.5 bg-black/60 rounded text-white text-xs font-medium">
                                                    {String(photo.sort_order).padStart(2, '0')}
                                                </div>

                                                {/* 하단 정보 */}
                                                <div className="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/70 to-transparent p-2">
                                                    {photo.concept_name && (
                                                        <span className="text-white text-xs font-medium truncate block">
                                                            {photo.concept_name}
                                                        </span>
                                                    )}
                                                </div>
                                            </motion.div>
                                        ))}
                                    </div>
                                )}
                            </>
                        )}

                        {/* 티저 이미지 그리드 */}
                        {manageSubTab === 'teaser' && (
                            <>
                                {teasers.length === 0 ? (
                                    <div className="text-center py-16">
                                        <Image className="mx-auto text-gray-300 mb-4" size={48} />
                                        <p className="text-gray-500">등록된 티저 이미지가 없습니다</p>
                                        <p className="text-gray-400 text-sm mt-1">업로드 탭에서 티저를 추가하세요</p>
                                    </div>
                                ) : (
                                    <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6 gap-3">
                                        {teasers.map((teaser, index) => (
                                            <motion.div
                                                key={teaser.id}
                                                initial={{ opacity: 0, scale: 0.9 }}
                                                animate={{ opacity: 1, scale: 1 }}
                                                transition={{ duration: 0.2, delay: index < 20 ? index * 0.02 : 0 }}
                                                className={`relative group aspect-square rounded-lg overflow-hidden cursor-pointer border-2 transition-all duration-200 ${
                                                    selectedPhotos.includes(`teaser-${teaser.id}`)
                                                        ? 'border-primary ring-2 ring-primary/30 scale-[0.98]'
                                                        : 'border-transparent hover:border-primary/50 hover:shadow-lg'
                                                }`}
                                                onClick={() => {
                                                    const teaserId = `teaser-${teaser.id}`;
                                                    setSelectedPhotos(prev =>
                                                        prev.includes(teaserId)
                                                            ? prev.filter(id => id !== teaserId)
                                                            : [...prev, teaserId]
                                                    );
                                                }}
                                            >
                                                {teaser.media_type === 'video' ? (
                                                    <video
                                                        src={teaser.original_url}
                                                        className="w-full h-full object-cover transition-transform duration-200 group-hover:scale-105"
                                                        muted
                                                        loop
                                                        onMouseEnter={e => e.target.play()}
                                                        onMouseLeave={e => { e.target.pause(); e.target.currentTime = 0; }}
                                                    />
                                                ) : (
                                                    <img
                                                        src={teaser.thumb_url || teaser.medium_url}
                                                        alt={`티저 ${teaser.sort_order}`}
                                                        loading="lazy"
                                                        className="w-full h-full object-cover transition-transform duration-200 group-hover:scale-105"
                                                    />
                                                )}
                                                {/* 호버 시 반투명 오버레이 */}
                                                <div className="absolute inset-0 bg-purple-500/10 opacity-0 group-hover:opacity-100 transition-opacity duration-200 pointer-events-none" />
                                                
                                                {/* 체크박스 오버레이 */}
                                                <div className={`absolute top-2 left-2 w-6 h-6 rounded-full border-2 flex items-center justify-center transition-all ${
                                                    selectedPhotos.includes(`teaser-${teaser.id}`)
                                                        ? 'bg-primary border-primary'
                                                        : 'bg-white/80 border-gray-300 opacity-0 group-hover:opacity-100'
                                                }`}>
                                                    {selectedPhotos.includes(`teaser-${teaser.id}`) && (
                                                        <Check size={14} className="text-white" />
                                                    )}
                                                </div>

                                                {/* 순서 번호 뱃지 */}
                                                <div className="absolute top-2 right-2 px-2 py-0.5 bg-purple-600/80 rounded text-white text-xs font-medium">
                                                    {String(teaser.sort_order).padStart(2, '0')}
                                                </div>
                                            </motion.div>
                                        ))}
                                    </div>
                                )}
                            </>
                        )}
                    </motion.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"
                />
            </main>
        </div>
    );
}

export default AdminAlbumPhotos;
