<template>
  <div class="media-manager">
    <h1>Media Manager</h1>
    <p class="subtitle">Manage anime openings and backgrounds</p>

    <!-- Content Type Switch -->
    <div class="type-switch">
      <button
        class="switch-btn"
        :class="{ active: contentType === 'openings' }"
        @click="contentType = 'openings'"
      >
        <span class="switch-icon">🎵</span>
        <span>Openings</span>
        <span class="switch-count">{{ openingsTotal }}</span>
      </button>
      <button
        class="switch-btn"
        :class="{ active: contentType === 'backgrounds' }"
        @click="contentType = 'backgrounds'"
      >
        <span class="switch-icon">🎬</span>
        <span>Backgrounds</span>
        <span class="switch-count">{{ backgroundsTotal }}</span>
      </button>
    </div>

    <!-- Search Bar -->
    <div class="search-bar">
      <input
        type="text"
        v-model="searchQuery"
        :placeholder="contentType === 'openings' ? 'Search by anime name...' : 'Search by name...'"
        class="search-input"
      />
      <select v-if="contentType === 'backgrounds'" v-model="filterDifficulty" class="filter-select">
        <option value="">All Difficulties</option>
        <option value="easy">Easy</option>
        <option value="medium">Medium</option>
        <option value="hard">Hard</option>
      </select>
      <button v-if="contentType === 'openings'" class="btn-add-opening" @click="openCreateModal">
        + Add Opening
      </button>
    </div>

    <!-- Loading State -->
    <div v-if="loading" class="loading-state">
      <div class="spinner"></div>
      <span>Loading {{ contentType }}...</span>
    </div>

    <!-- Openings Grid -->
    <div v-else-if="contentType === 'openings'" class="content-grid">
      <div v-if="openings.length === 0" class="empty-state">
        <span class="empty-icon">🎵</span>
        <p>No openings found</p>
      </div>
      <div
        v-for="opening in openings"
        :key="opening.id"
        class="content-card opening-card"
        @click="openOpeningDetail(opening)"
      >
        <div class="card-poster">
          <img
            v-if="getDefaultPoster(opening)"
            :src="'/api/media/posters/' + getDefaultPoster(opening)"
            :alt="opening.anime_name"
            @error="handleImageError"
          />
          <div v-else class="no-poster">
            <span>🎵</span>
          </div>
        </div>
        <div class="card-content">
          <h3 class="card-title">{{ opening.anime_name }}</h3>
          <div class="card-meta">
            <span class="op-badge">{{ opening.op_number }}</span>
            <span v-if="opening.song_name" class="song-name">{{ opening.song_name }}</span>
          </div>
          <div class="card-stats">
            <span class="stat">{{ opening.posters.length }} poster(s)</span>
            <span class="stat" :class="{ 'never-used': !opening.last_usage }">
              {{ opening.last_usage ? formatDate(opening.last_usage) : 'Never used' }}
            </span>
          </div>
        </div>
      </div>
    </div>

    <!-- Backgrounds Grid -->
    <div v-else class="content-grid">
      <div v-if="backgrounds.length === 0" class="empty-state">
        <span class="empty-icon">🎬</span>
        <p>No backgrounds found</p>
      </div>
      <div
        v-for="bg in backgrounds"
        :key="bg.id"
        class="content-card background-card"
        :class="'difficulty-' + bg.difficulty"
        @click="openBackgroundDetail(bg)"
      >
        <div class="card-video-preview">
          <video
            :src="'/api/media/backgrounds/' + bg.video_file"
            muted
            loop
            @mouseenter="$event.target.play()"
            @mouseleave="$event.target.pause(); $event.target.currentTime = 0"
          ></video>
          <span class="difficulty-badge" :class="bg.difficulty">{{ bg.difficulty.toUpperCase() }}</span>
        </div>
        <div class="card-content">
          <h3 class="card-title">{{ bg.name }}</h3>
          <div class="card-meta">
            <span class="file-name">{{ bg.video_file }}</span>
          </div>
          <div class="card-stats">
            <span class="stat">Created: {{ formatDate(bg.created_at) }}</span>
          </div>
        </div>
      </div>
    </div>

    <!-- Opening Detail Modal -->
    <div v-if="showOpeningModal" class="modal-overlay" @click.self="closeOpeningModal">
      <div class="detail-modal opening-detail">
        <button class="modal-close" @click="closeOpeningModal">&times;</button>

        <div class="detail-header">
          <h2>{{ selectedOpening.anime_name }}</h2>
          <span class="op-badge large">{{ selectedOpening.op_number }}</span>
        </div>

        <div class="detail-content">
          <!-- Audio Player Section -->
          <div class="detail-section">
            <h3>Audio</h3>
            <div class="audio-player-container">
              <audio
                ref="audioPlayer"
                :src="'/api/media/audio/' + selectedOpening.audio_file"
                controls
                class="audio-player"
              ></audio>
              <div class="audio-info">
                <span class="file-label">File:</span>
                <span class="file-value">{{ selectedOpening.audio_file }}</span>
              </div>
              <button class="btn-delete-file" @click="confirmDeleteAudio">
                <span>🗑️</span> Delete Audio File
              </button>
            </div>
          </div>

          <!-- Posters Section -->
          <div class="detail-section">
            <h3>Posters ({{ selectedOpening.posters.length }})</h3>
            <div v-if="selectedOpening.posters.length === 0" class="no-posters">
              No posters attached to this opening
            </div>
            <div v-else class="posters-grid">
              <div
                v-for="poster in selectedOpening.posters"
                :key="poster.id"
                class="poster-card"
                :class="{ 'is-default': poster.is_default }"
              >
                <img
                  :src="'/api/media/posters/' + poster.poster_file"
                  :alt="poster.poster_file"
                  @error="handleImageError"
                />
                <div class="poster-overlay">
                  <span v-if="poster.is_default" class="default-label">Default</span>
                  <div class="poster-file">{{ poster.poster_file }}</div>
                  <div class="poster-actions">
                    <button
                      v-if="!poster.is_default"
                      class="btn-poster-action"
                      @click.stop="setDefaultPoster(poster)"
                      title="Set as default"
                    >⭐</button>
                    <button
                      class="btn-poster-action delete"
                      @click.stop="confirmDeletePoster(poster)"
                      title="Delete poster"
                    >🗑️</button>
                  </div>
                </div>
              </div>
            </div>
          </div>

          <!-- Info Section -->
          <div class="detail-section">
            <h3>Information</h3>
            <div class="info-grid">
              <div class="info-item">
                <span class="info-label">Anime Name</span>
                <span class="info-value">{{ selectedOpening.anime_name }}</span>
              </div>
              <div class="info-item">
                <span class="info-label">Opening Number</span>
                <span class="info-value">{{ selectedOpening.op_number }}</span>
              </div>
              <div class="info-item">
                <span class="info-label">Song Name</span>
                <span class="info-value">{{ selectedOpening.song_name || 'Not specified' }}</span>
              </div>
              <div class="info-item">
                <span class="info-label">Audio File</span>
                <span class="info-value">{{ selectedOpening.audio_file }}</span>
              </div>
              <div class="info-item">
                <span class="info-label">Created</span>
                <span class="info-value">{{ formatDateTime(selectedOpening.created_at) }}</span>
              </div>
              <div class="info-item">
                <span class="info-label">Updated</span>
                <span class="info-value">{{ formatDateTime(selectedOpening.updated_at) }}</span>
              </div>
              <div class="info-item">
                <span class="info-label">Last Used</span>
                <span class="info-value" :class="{ 'never-used': !selectedOpening.last_usage }">
                  {{ selectedOpening.last_usage ? formatDateTime(selectedOpening.last_usage) : 'Never' }}
                </span>
              </div>
              <div class="info-item">
                <span class="info-label">Posters Count</span>
                <span class="info-value">{{ selectedOpening.posters.length }}</span>
              </div>
            </div>
          </div>
        </div>

        <div class="detail-footer">
          <button class="btn-delete-opening" @click="confirmDeleteOpening">
            Delete Opening
          </button>
        </div>
      </div>
    </div>

    <!-- Background Detail Modal -->
    <div v-if="showBackgroundModal" class="modal-overlay" @click.self="closeBackgroundModal">
      <div class="detail-modal background-detail">
        <button class="modal-close" @click="closeBackgroundModal">&times;</button>

        <div class="detail-header">
          <h2>{{ selectedBackground.name }}</h2>
          <span class="difficulty-badge large" :class="selectedBackground.difficulty">
            {{ selectedBackground.difficulty.toUpperCase() }}
          </span>
        </div>

        <div class="detail-content">
          <!-- Video Preview Section -->
          <div class="detail-section">
            <h3>Video Preview</h3>
            <div class="video-preview-container">
              <video
                :src="'/api/media/backgrounds/' + selectedBackground.video_file"
                controls
                loop
                class="video-preview"
              ></video>
              <div class="video-info">
                <span class="file-label">File:</span>
                <span class="file-value">{{ selectedBackground.video_file }}</span>
              </div>
            </div>
          </div>

          <!-- Info Section -->
          <div class="detail-section">
            <h3>Information</h3>
            <div class="info-grid">
              <div class="info-item">
                <span class="info-label">Name</span>
                <span class="info-value">{{ selectedBackground.name }}</span>
              </div>
              <div class="info-item">
                <span class="info-label">Video File</span>
                <span class="info-value">{{ selectedBackground.video_file }}</span>
              </div>
              <div class="info-item">
                <span class="info-label">Difficulty</span>
                <span class="info-value difficulty-value" :class="selectedBackground.difficulty">
                  {{ selectedBackground.difficulty }}
                </span>
              </div>
              <div class="info-item">
                <span class="info-label">Created</span>
                <span class="info-value">{{ formatDateTime(selectedBackground.created_at) }}</span>
              </div>
              <div class="info-item">
                <span class="info-label">Updated</span>
                <span class="info-value">{{ formatDateTime(selectedBackground.updated_at) }}</span>
              </div>
            </div>
          </div>
        </div>

        <div class="detail-footer">
          <button class="btn-delete-opening" @click="confirmDeleteBackground">
            Delete Background
          </button>
        </div>
      </div>
    </div>

    <!-- Create Opening Modal -->
    <div v-if="showCreateModal" class="modal-overlay" @click.self="closeCreateModal">
      <div class="detail-modal create-modal">
        <button class="modal-close" @click="closeCreateModal">&times;</button>

        <div class="detail-header">
          <h2>Add New Opening</h2>
        </div>

        <div class="detail-content">
          <!-- Basic Info -->
          <div class="detail-section">
            <h3>Basic Information</h3>
            <div class="form-grid">
              <div class="form-group">
                <label>Anime Name *</label>
                <input type="text" v-model="createForm.anime_name" placeholder="e.g., One Piece" />
              </div>
              <div class="form-group">
                <label>Opening Number *</label>
                <input type="text" v-model="createForm.op_number" placeholder="e.g., OP1, ED2" />
              </div>
              <div class="form-group full-width">
                <label>Song Name</label>
                <input type="text" v-model="createForm.song_name" placeholder="e.g., We Are!" />
              </div>
            </div>
          </div>

          <!-- Audio Upload -->
          <div class="detail-section">
            <h3>Audio File *</h3>
            <div class="upload-zone" :class="{ 'has-file': createForm.audioFile }">
              <input
                type="file"
                accept=".mp3,.wav,.ogg,.m4a"
                @change="handleAudioUpload"
                ref="audioInput"
                class="file-input-hidden"
              />
              <div v-if="!createForm.audioFile" class="upload-placeholder" @click="$refs.audioInput.click()">
                <span class="upload-icon">🎵</span>
                <span class="upload-text">Click to upload audio file</span>
                <span class="upload-hint">MP3, WAV, OGG, M4A</span>
              </div>
              <div v-else class="uploaded-file">
                <div class="uploaded-file-info">
                  <span class="file-icon">🎵</span>
                  <div class="file-details">
                    <span class="file-name">{{ createForm.audioFile.name }}</span>
                    <span class="file-size">{{ formatFileSize(createForm.audioFile.size) }}</span>
                  </div>
                  <button class="btn-remove-file" @click="removeAudioFile">×</button>
                </div>
                <audio v-if="audioPreviewUrl" :src="audioPreviewUrl" controls class="preview-player"></audio>
              </div>
            </div>
          </div>

          <!-- Poster Uploads -->
          <div class="detail-section">
            <h3>Posters (optional)</h3>
            <div class="poster-uploads">
              <!-- TikTok Format -->
              <div class="poster-upload-block">
                <label class="poster-label">
                  <span class="format-badge tiktok">TikTok / Shorts</span>
                  <span class="format-hint">9:16 vertical format (1080x1920)</span>
                </label>
                <div class="upload-zone poster-zone" :class="{ 'has-file': createForm.posterTiktok }">
                  <input
                    type="file"
                    accept=".jpg,.jpeg,.png,.webp"
                    @change="handlePosterTiktokUpload"
                    ref="posterTiktokInput"
                    class="file-input-hidden"
                  />
                  <div v-if="!createForm.posterTiktok" class="upload-placeholder" @click="$refs.posterTiktokInput.click()">
                    <span class="upload-icon">🖼️</span>
                    <span class="upload-text">Upload TikTok poster</span>
                  </div>
                  <div v-else class="poster-preview-container">
                    <img :src="posterTiktokPreviewUrl" class="poster-preview-img" />
                    <div class="poster-preview-overlay">
                      <span class="preview-file-name">{{ createForm.posterTiktok.name }}</span>
                      <button class="btn-remove-poster" @click="removePosterTiktok">×</button>
                    </div>
                  </div>
                </div>
              </div>

              <!-- Full Size Format -->
              <div class="poster-upload-block">
                <label class="poster-label">
                  <span class="format-badge fullsize">Full Size / YouTube</span>
                  <span class="format-hint">16:9 horizontal format (1920x1080)</span>
                </label>
                <div class="upload-zone poster-zone" :class="{ 'has-file': createForm.posterFullsize }">
                  <input
                    type="file"
                    accept=".jpg,.jpeg,.png,.webp"
                    @change="handlePosterFullsizeUpload"
                    ref="posterFullsizeInput"
                    class="file-input-hidden"
                  />
                  <div v-if="!createForm.posterFullsize" class="upload-placeholder" @click="$refs.posterFullsizeInput.click()">
                    <span class="upload-icon">🖼️</span>
                    <span class="upload-text">Upload Full Size poster</span>
                  </div>
                  <div v-else class="poster-preview-container">
                    <img :src="posterFullsizePreviewUrl" class="poster-preview-img horizontal" />
                    <div class="poster-preview-overlay">
                      <span class="preview-file-name">{{ createForm.posterFullsize.name }}</span>
                      <button class="btn-remove-poster" @click="removePosterFullsize">×</button>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>

        <div class="detail-footer create-footer">
          <div v-if="uploadProgress > 0 && uploadProgress < 100" class="upload-progress">
            <div class="progress-bar-small">
              <div class="progress-fill-small" :style="{ width: uploadProgress + '%' }"></div>
            </div>
            <span class="progress-text-small">Uploading... {{ uploadProgress }}%</span>
          </div>
          <button class="btn-cancel" @click="closeCreateModal" :disabled="saving">Cancel</button>
          <button
            class="btn-create"
            @click="createOpening"
            :disabled="!canCreate || saving"
          >
            {{ saving ? 'Creating...' : 'Create Opening' }}
          </button>
        </div>
      </div>
    </div>

    <!-- Confirmation Modal -->
    <div v-if="showConfirmModal" class="modal-overlay" @click.self="showConfirmModal = false">
      <div class="confirm-modal">
        <h3>{{ confirmTitle }}</h3>
        <p>{{ confirmMessage }}</p>
        <div class="confirm-actions">
          <button class="btn-cancel" @click="showConfirmModal = false">Cancel</button>
          <button class="btn-confirm-delete" @click="executeConfirmedAction">Delete</button>
        </div>
      </div>
    </div>

    <!-- Toast Notifications -->
    <div class="toast-container">
      <div v-for="(t, index) in toasts" :key="index" class="toast" :class="t.type">
        {{ t.message }}
      </div>
    </div>
  </div>
</template>

<script>
import { ref, reactive, computed, watch, onMounted } from 'vue'

export default {
  name: 'MediaManager',
  setup() {
    // Content type switch
    const contentType = ref('openings')

    // Data
    const openings = ref([])
    const backgrounds = ref([])
    const openingsTotal = ref(0)
    const backgroundsTotal = ref(0)
    const loading = ref(true)
    const saving = ref(false)
    const searchQuery = ref('')
    const filterDifficulty = ref('')

    // S3 Content for file selection
    const s3Content = reactive({
      audio_files: [],
      posters: [],
      background_videos: []
    })

    // Modals
    const showOpeningModal = ref(false)
    const showBackgroundModal = ref(false)
    const showCreateModal = ref(false)
    const selectedOpening = ref(null)
    const selectedBackground = ref(null)

    // Create form
    const createForm = reactive({
      anime_name: '',
      op_number: '',
      song_name: '',
      audioFile: null,
      posterTiktok: null,
      posterFullsize: null
    })

    // File preview URLs
    const audioPreviewUrl = ref(null)
    const posterTiktokPreviewUrl = ref(null)
    const posterFullsizePreviewUrl = ref(null)
    const uploadProgress = ref(0)

    const canCreate = computed(() => {
      return createForm.anime_name && createForm.op_number && createForm.audioFile
    })

    // File size formatter
    const formatFileSize = (bytes) => {
      if (bytes === 0) return '0 Bytes'
      const k = 1024
      const sizes = ['Bytes', 'KB', 'MB', 'GB']
      const i = Math.floor(Math.log(bytes) / Math.log(k))
      return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
    }

    // File upload handlers
    const handleAudioUpload = (event) => {
      const file = event.target.files[0]
      if (file) {
        createForm.audioFile = file
        audioPreviewUrl.value = URL.createObjectURL(file)
      }
    }

    const handlePosterTiktokUpload = (event) => {
      const file = event.target.files[0]
      if (file) {
        createForm.posterTiktok = file
        posterTiktokPreviewUrl.value = URL.createObjectURL(file)
      }
    }

    const handlePosterFullsizeUpload = (event) => {
      const file = event.target.files[0]
      if (file) {
        createForm.posterFullsize = file
        posterFullsizePreviewUrl.value = URL.createObjectURL(file)
      }
    }

    const removeAudioFile = () => {
      createForm.audioFile = null
      if (audioPreviewUrl.value) {
        URL.revokeObjectURL(audioPreviewUrl.value)
        audioPreviewUrl.value = null
      }
    }

    const removePosterTiktok = () => {
      createForm.posterTiktok = null
      if (posterTiktokPreviewUrl.value) {
        URL.revokeObjectURL(posterTiktokPreviewUrl.value)
        posterTiktokPreviewUrl.value = null
      }
    }

    const removePosterFullsize = () => {
      createForm.posterFullsize = null
      if (posterFullsizePreviewUrl.value) {
        URL.revokeObjectURL(posterFullsizePreviewUrl.value)
        posterFullsizePreviewUrl.value = null
      }
    }

    // Confirmation modal
    const showConfirmModal = ref(false)
    const confirmTitle = ref('')
    const confirmMessage = ref('')
    const confirmAction = ref(null)

    // Toast notifications
    const toasts = ref([])

    // Audio player ref
    const audioPlayer = ref(null)

    const showToast = (message, type = 'success') => {
      const toast = { message, type }
      toasts.value.push(toast)
      setTimeout(() => {
        const idx = toasts.value.indexOf(toast)
        if (idx > -1) toasts.value.splice(idx, 1)
      }, 3000)
    }

    const fetchOpenings = async () => {
      loading.value = true
      try {
        const params = new URLSearchParams()
        if (searchQuery.value) params.append('search', searchQuery.value)

        const response = await fetch(`/api/api/openings?${params}`)
        const data = await response.json()
        openings.value = data.openings
        openingsTotal.value = data.total
      } catch (e) {
        showToast('Failed to fetch openings', 'error')
      } finally {
        loading.value = false
      }
    }

    const fetchBackgrounds = async () => {
      loading.value = true
      try {
        const params = new URLSearchParams()
        if (searchQuery.value) params.append('search', searchQuery.value)
        if (filterDifficulty.value) params.append('difficulty', filterDifficulty.value)

        const response = await fetch(`/api/api/backgrounds?${params}`)
        const data = await response.json()
        backgrounds.value = data.backgrounds
        backgroundsTotal.value = data.total
      } catch (e) {
        showToast('Failed to fetch backgrounds', 'error')
      } finally {
        loading.value = false
      }
    }

    const fetchData = async () => {
      if (contentType.value === 'openings') {
        await fetchOpenings()
      } else {
        await fetchBackgrounds()
      }
    }

    const fetchAllCounts = async () => {
      try {
        const [openingsRes, backgroundsRes] = await Promise.all([
          fetch('/api/api/openings?limit=1'),
          fetch('/api/api/backgrounds?limit=1')
        ])
        const openingsData = await openingsRes.json()
        const backgroundsData = await backgroundsRes.json()
        openingsTotal.value = openingsData.total
        backgroundsTotal.value = backgroundsData.total
      } catch (e) {
        console.error('Failed to fetch counts:', e)
      }
    }

    const fetchS3Content = async () => {
      try {
        const response = await fetch('/api/content')
        const data = await response.json()
        s3Content.audio_files = data.audio_files || []
        s3Content.posters = data.posters || []
        s3Content.background_videos = data.background_videos || []
      } catch (e) {
        console.error('Failed to fetch S3 content:', e)
      }
    }

    // Create Opening
    const openCreateModal = () => {
      createForm.anime_name = ''
      createForm.op_number = ''
      createForm.song_name = ''
      createForm.audioFile = null
      createForm.posterTiktok = null
      createForm.posterFullsize = null
      audioPreviewUrl.value = null
      posterTiktokPreviewUrl.value = null
      posterFullsizePreviewUrl.value = null
      uploadProgress.value = 0
      showCreateModal.value = true
    }

    const closeCreateModal = () => {
      // Clean up preview URLs
      if (audioPreviewUrl.value) URL.revokeObjectURL(audioPreviewUrl.value)
      if (posterTiktokPreviewUrl.value) URL.revokeObjectURL(posterTiktokPreviewUrl.value)
      if (posterFullsizePreviewUrl.value) URL.revokeObjectURL(posterFullsizePreviewUrl.value)
      showCreateModal.value = false
    }

    const createOpening = async () => {
      if (!canCreate.value) {
        showToast('Please fill all required fields', 'error')
        return
      }

      saving.value = true
      uploadProgress.value = 10

      try {
        const uploadedPosters = []

        // 1. Upload audio file to S3
        uploadProgress.value = 20
        const audioFormData = new FormData()
        audioFormData.append('files', createForm.audioFile)

        const audioResponse = await fetch('/api/upload/audio', {
          method: 'POST',
          body: audioFormData
        })

        if (!audioResponse.ok) {
          throw new Error('Failed to upload audio file')
        }

        const audioResult = await audioResponse.json()
        if (!audioResult.results[0]?.success) {
          throw new Error(audioResult.results[0]?.error || 'Failed to upload audio')
        }

        const audioFileName = createForm.audioFile.name
        uploadProgress.value = 40

        // 2. Upload TikTok poster if provided
        if (createForm.posterTiktok) {
          const posterFormData = new FormData()
          // Add prefix to distinguish format
          const tiktokFileName = `tiktok_${createForm.posterTiktok.name}`
          const tiktokFile = new File([createForm.posterTiktok], tiktokFileName, { type: createForm.posterTiktok.type })
          posterFormData.append('files', tiktokFile)

          const posterResponse = await fetch('/api/upload/posters', {
            method: 'POST',
            body: posterFormData
          })

          if (posterResponse.ok) {
            const posterResult = await posterResponse.json()
            if (posterResult.results[0]?.success) {
              uploadedPosters.push(tiktokFileName)
            }
          }
        }
        uploadProgress.value = 60

        // 3. Upload Full Size poster if provided
        if (createForm.posterFullsize) {
          const posterFormData = new FormData()
          // Add prefix to distinguish format
          const fullsizeFileName = `fullsize_${createForm.posterFullsize.name}`
          const fullsizeFile = new File([createForm.posterFullsize], fullsizeFileName, { type: createForm.posterFullsize.type })
          posterFormData.append('files', fullsizeFile)

          const posterResponse = await fetch('/api/upload/posters', {
            method: 'POST',
            body: posterFormData
          })

          if (posterResponse.ok) {
            const posterResult = await posterResponse.json()
            if (posterResult.results[0]?.success) {
              uploadedPosters.push(fullsizeFileName)
            }
          }
        }
        uploadProgress.value = 80

        // 4. Create opening record in DB
        const payload = {
          anime_name: createForm.anime_name,
          op_number: createForm.op_number,
          song_name: createForm.song_name || null,
          audio_file: audioFileName,
          poster_files: uploadedPosters
        }

        const response = await fetch('/api/api/openings', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(payload)
        })

        if (!response.ok) {
          throw new Error('Failed to create opening record')
        }

        uploadProgress.value = 100
        showToast('Opening created successfully')
        closeCreateModal()
        await fetchOpenings()
        await fetchAllCounts()
      } catch (e) {
        showToast(e.message || 'Failed to create opening', 'error')
      } finally {
        saving.value = false
        uploadProgress.value = 0
      }
    }

    const getDefaultPoster = (opening) => {
      const defaultPoster = opening.posters.find(p => p.is_default)
      if (defaultPoster) return defaultPoster.poster_file
      if (opening.posters.length > 0) return opening.posters[0].poster_file
      return null
    }

    const handleImageError = (e) => {
      e.target.src = 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"><rect fill="%23333" width="100" height="100"/><text x="50%" y="50%" fill="%23666" text-anchor="middle" dy=".3em">No Image</text></svg>'
    }

    const formatDate = (dateString) => {
      if (!dateString) return ''
      const date = new Date(dateString)
      const now = new Date()
      const diffMs = now - date
      const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24))

      if (diffDays === 0) {
        const diffHours = Math.floor(diffMs / (1000 * 60 * 60))
        if (diffHours === 0) {
          const diffMins = Math.floor(diffMs / (1000 * 60))
          return diffMins <= 1 ? 'just now' : `${diffMins}m ago`
        }
        return `${diffHours}h ago`
      }
      if (diffDays === 1) return 'yesterday'
      if (diffDays < 7) return `${diffDays}d ago`

      return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' })
    }

    const formatDateTime = (dateString) => {
      if (!dateString) return ''
      return new Date(dateString).toLocaleString('en-US', {
        year: 'numeric',
        month: 'short',
        day: 'numeric',
        hour: '2-digit',
        minute: '2-digit'
      })
    }

    // Opening Detail
    const openOpeningDetail = (opening) => {
      selectedOpening.value = { ...opening }
      showOpeningModal.value = true
    }

    const closeOpeningModal = () => {
      if (audioPlayer.value) {
        audioPlayer.value.pause()
      }
      showOpeningModal.value = false
      selectedOpening.value = null
    }

    const setDefaultPoster = async (poster) => {
      try {
        await fetch(`/api/api/openings/${selectedOpening.value.id}/posters/${poster.id}/set-default`, {
          method: 'POST'
        })
        showToast('Default poster updated')

        // Update local state
        selectedOpening.value.posters.forEach(p => {
          p.is_default = p.id === poster.id
        })
        await fetchOpenings()
      } catch (e) {
        showToast('Failed to set default poster', 'error')
      }
    }

    const confirmDeleteAudio = () => {
      confirmTitle.value = 'Delete Audio File'
      confirmMessage.value = `This will delete the audio file "${selectedOpening.value.audio_file}" from S3 and remove this opening from the database. This action cannot be undone.`
      confirmAction.value = async () => {
        try {
          // Delete audio from S3
          await fetch(`/api/media/audio/${selectedOpening.value.audio_file}`, {
            method: 'DELETE'
          })

          // Delete opening from DB
          await fetch(`/api/api/openings/${selectedOpening.value.id}`, {
            method: 'DELETE'
          })

          showToast('Opening and audio file deleted')
          closeOpeningModal()
          await fetchOpenings()
          await fetchAllCounts()
        } catch (e) {
          showToast('Failed to delete', 'error')
        }
      }
      showConfirmModal.value = true
    }

    const confirmDeletePoster = (poster) => {
      confirmTitle.value = 'Delete Poster'
      confirmMessage.value = `This will delete the poster "${poster.poster_file}" from S3 and remove it from this opening. This action cannot be undone.`
      confirmAction.value = async () => {
        try {
          // Delete poster from S3
          await fetch(`/api/media/posters/${poster.poster_file}`, {
            method: 'DELETE'
          })

          // Remove poster from opening in DB
          await fetch(`/api/api/openings/${selectedOpening.value.id}/posters/${poster.id}`, {
            method: 'DELETE'
          })

          showToast('Poster deleted')

          // Update local state
          selectedOpening.value.posters = selectedOpening.value.posters.filter(p => p.id !== poster.id)
          await fetchOpenings()
        } catch (e) {
          showToast('Failed to delete poster', 'error')
        }
      }
      showConfirmModal.value = true
    }

    const confirmDeleteOpening = () => {
      const opening = selectedOpening.value
      const posterCount = opening.posters.length
      confirmTitle.value = 'Delete Opening Completely'
      confirmMessage.value = `This will PERMANENTLY delete:\n- Opening "${opening.anime_name} - ${opening.op_number}" from database\n- Audio file "${opening.audio_file}" from S3\n- ${posterCount} poster(s) from S3\n\nThis action cannot be undone!`
      confirmAction.value = async () => {
        try {
          // Delete all posters from S3
          for (const poster of opening.posters) {
            await fetch(`/api/media/posters/${poster.poster_file}`, {
              method: 'DELETE'
            })
          }

          // Delete audio from S3
          await fetch(`/api/media/audio/${opening.audio_file}`, {
            method: 'DELETE'
          })

          // Delete opening from DB (this also removes poster records)
          await fetch(`/api/api/openings/${opening.id}`, {
            method: 'DELETE'
          })

          showToast('Opening and all files deleted')
          closeOpeningModal()
          await fetchOpenings()
          await fetchAllCounts()
        } catch (e) {
          showToast('Failed to delete opening', 'error')
        }
      }
      showConfirmModal.value = true
    }

    // Background Detail
    const openBackgroundDetail = (bg) => {
      selectedBackground.value = { ...bg }
      showBackgroundModal.value = true
    }

    const closeBackgroundModal = () => {
      showBackgroundModal.value = false
      selectedBackground.value = null
    }

    const confirmDeleteBackground = () => {
      confirmTitle.value = 'Delete Background'
      confirmMessage.value = `This will delete the background "${selectedBackground.value.name}" from the database. The video file will NOT be deleted from S3. Continue?`
      confirmAction.value = async () => {
        try {
          await fetch(`/api/api/backgrounds/${selectedBackground.value.id}`, {
            method: 'DELETE'
          })

          showToast('Background deleted')
          closeBackgroundModal()
          await fetchBackgrounds()
          await fetchAllCounts()
        } catch (e) {
          showToast('Failed to delete background', 'error')
        }
      }
      showConfirmModal.value = true
    }

    const executeConfirmedAction = async () => {
      if (confirmAction.value) {
        await confirmAction.value()
      }
      showConfirmModal.value = false
      confirmAction.value = null
    }

    // Watchers
    let searchTimeout
    watch([searchQuery, filterDifficulty], () => {
      clearTimeout(searchTimeout)
      searchTimeout = setTimeout(fetchData, 300)
    })

    watch(contentType, () => {
      searchQuery.value = ''
      filterDifficulty.value = ''
      fetchData()
    })

    onMounted(() => {
      fetchOpenings()
      fetchAllCounts()
    })

    return {
      // State
      contentType,
      openings,
      backgrounds,
      openingsTotal,
      backgroundsTotal,
      loading,
      saving,
      searchQuery,
      filterDifficulty,
      toasts,
      audioPlayer,
      s3Content,

      // Create Modal
      showCreateModal,
      createForm,
      canCreate,
      openCreateModal,
      closeCreateModal,
      createOpening,
      audioPreviewUrl,
      posterTiktokPreviewUrl,
      posterFullsizePreviewUrl,
      uploadProgress,
      formatFileSize,
      handleAudioUpload,
      handlePosterTiktokUpload,
      handlePosterFullsizeUpload,
      removeAudioFile,
      removePosterTiktok,
      removePosterFullsize,

      // Opening Modal
      showOpeningModal,
      selectedOpening,
      openOpeningDetail,
      closeOpeningModal,
      setDefaultPoster,
      confirmDeleteAudio,
      confirmDeletePoster,
      confirmDeleteOpening,

      // Background Modal
      showBackgroundModal,
      selectedBackground,
      openBackgroundDetail,
      closeBackgroundModal,
      confirmDeleteBackground,

      // Confirmation Modal
      showConfirmModal,
      confirmTitle,
      confirmMessage,
      executeConfirmedAction,

      // Helpers
      getDefaultPoster,
      handleImageError,
      formatDate,
      formatDateTime
    }
  }
}
</script>

<style scoped>
.media-manager {
  padding: 2rem;
  max-width: 1400px;
  margin: 0 auto;
}

.media-manager h1 {
  text-align: center;
  font-size: 2.5rem;
  margin-bottom: 0.5rem;
  background: linear-gradient(90deg, #00d4ff, #7b2cbf);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

.subtitle {
  text-align: center;
  color: #888;
  margin-bottom: 2rem;
}

/* Type Switch */
.type-switch {
  display: flex;
  justify-content: center;
  gap: 1rem;
  margin-bottom: 2rem;
}

.switch-btn {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 1rem 2rem;
  border: 2px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.05);
  color: #888;
  font-size: 1rem;
  cursor: pointer;
  transition: all 0.3s ease;
}

.switch-btn:hover {
  border-color: rgba(0, 212, 255, 0.3);
  background: rgba(255, 255, 255, 0.08);
}

.switch-btn.active {
  border-color: #00d4ff;
  background: rgba(0, 212, 255, 0.1);
  color: #fff;
}

.switch-icon {
  font-size: 1.5rem;
}

.switch-count {
  background: rgba(0, 212, 255, 0.2);
  color: #00d4ff;
  padding: 0.25rem 0.75rem;
  border-radius: 20px;
  font-size: 0.85rem;
  font-weight: 600;
}

/* Search Bar */
.search-bar {
  display: flex;
  gap: 1rem;
  margin-bottom: 2rem;
  justify-content: center;
}

.search-input {
  width: 100%;
  max-width: 400px;
  padding: 0.75rem 1rem;
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.3);
  color: #fff;
  font-size: 1rem;
}

.search-input:focus {
  outline: none;
  border-color: #00d4ff;
}

.filter-select {
  padding: 0.75rem 1rem;
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.3);
  color: #fff;
  font-size: 1rem;
  min-width: 150px;
}

/* Loading State */
.loading-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  padding: 4rem;
  color: #888;
}

.spinner {
  width: 40px;
  height: 40px;
  border: 3px solid rgba(0, 212, 255, 0.3);
  border-top-color: #00d4ff;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

/* Empty State */
.empty-state {
  text-align: center;
  padding: 4rem;
  color: #666;
}

.empty-icon {
  font-size: 4rem;
  display: block;
  margin-bottom: 1rem;
}

/* Content Grid */
.content-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 1.5rem;
}

/* Content Cards */
.content-card {
  background: rgba(255, 255, 255, 0.05);
  border-radius: 16px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.1);
  cursor: pointer;
  transition: all 0.3s ease;
}

.content-card:hover {
  border-color: #00d4ff;
  transform: translateY(-4px);
}

.card-poster {
  height: 180px;
  background: rgba(0, 0, 0, 0.3);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.card-poster img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.no-poster {
  color: #444;
  font-size: 3rem;
}

.card-video-preview {
  height: 160px;
  position: relative;
  background: #000;
}

.card-video-preview video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.card-content {
  padding: 1rem;
}

.card-title {
  font-size: 1.1rem;
  color: #fff;
  margin-bottom: 0.5rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.card-meta {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
  flex-wrap: wrap;
}

.op-badge {
  background: linear-gradient(90deg, #00d4ff, #7b2cbf);
  color: #fff;
  padding: 0.2rem 0.6rem;
  border-radius: 4px;
  font-size: 0.75rem;
  font-weight: 600;
}

.op-badge.large {
  font-size: 0.9rem;
  padding: 0.3rem 0.8rem;
}

.song-name {
  color: #888;
  font-size: 0.85rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.file-name {
  color: #666;
  font-size: 0.75rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.card-stats {
  display: flex;
  justify-content: space-between;
  font-size: 0.75rem;
  color: #666;
  margin-top: 0.5rem;
  padding-top: 0.5rem;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.stat.never-used {
  font-style: italic;
}

/* Difficulty Badges */
.difficulty-badge {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  padding: 0.25rem 0.75rem;
  border-radius: 20px;
  font-size: 0.7rem;
  font-weight: 600;
}

.difficulty-badge.large {
  position: static;
  font-size: 0.85rem;
  padding: 0.3rem 1rem;
}

.difficulty-badge.easy, .difficulty-value.easy {
  background: rgba(0, 255, 136, 0.2);
  color: #00ff88;
}

.difficulty-badge.medium, .difficulty-value.medium {
  background: rgba(255, 170, 0, 0.2);
  color: #ffaa00;
}

.difficulty-badge.hard, .difficulty-value.hard {
  background: rgba(255, 68, 68, 0.2);
  color: #ff4444;
}

.background-card.difficulty-easy { border-color: rgba(0, 255, 136, 0.3); }
.background-card.difficulty-medium { border-color: rgba(255, 170, 0, 0.3); }
.background-card.difficulty-hard { border-color: rgba(255, 68, 68, 0.3); }

/* Modal Overlay */
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.85);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  padding: 1rem;
}

/* Detail Modal */
.detail-modal {
  background: #1a1a2e;
  border-radius: 20px;
  width: 100%;
  max-width: 800px;
  max-height: 90vh;
  overflow-y: auto;
  position: relative;
  border: 1px solid rgba(255, 255, 255, 0.1);
}

.modal-close {
  position: absolute;
  top: 1rem;
  right: 1rem;
  background: rgba(255, 255, 255, 0.1);
  border: none;
  color: #fff;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  font-size: 1.5rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10;
}

.modal-close:hover {
  background: rgba(255, 255, 255, 0.2);
}

.detail-header {
  padding: 2rem 2rem 1rem;
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
}

.detail-header h2 {
  font-size: 1.75rem;
  color: #fff;
  margin: 0;
}

.detail-content {
  padding: 0 2rem;
}

.detail-section {
  margin-bottom: 2rem;
}

.detail-section h3 {
  color: #00d4ff;
  font-size: 1rem;
  margin-bottom: 1rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

/* Audio Player */
.audio-player-container {
  background: rgba(0, 0, 0, 0.3);
  padding: 1.5rem;
  border-radius: 12px;
}

.audio-player {
  width: 100%;
  margin-bottom: 1rem;
}

.audio-info {
  display: flex;
  gap: 0.5rem;
  margin-bottom: 1rem;
  font-size: 0.9rem;
}

.file-label {
  color: #888;
}

.file-value {
  color: #fff;
  word-break: break-all;
}

.btn-delete-file {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 1rem;
  background: rgba(255, 68, 68, 0.2);
  border: 1px solid rgba(255, 68, 68, 0.3);
  border-radius: 8px;
  color: #ff4444;
  cursor: pointer;
  font-size: 0.85rem;
  transition: all 0.2s ease;
}

.btn-delete-file:hover {
  background: rgba(255, 68, 68, 0.3);
}

/* Posters Grid */
.no-posters {
  color: #666;
  text-align: center;
  padding: 2rem;
  background: rgba(0, 0, 0, 0.2);
  border-radius: 8px;
}

.posters-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 1rem;
}

.poster-card {
  position: relative;
  border-radius: 12px;
  overflow: hidden;
  border: 2px solid transparent;
  transition: all 0.3s ease;
}

.poster-card.is-default {
  border-color: #00d4ff;
}

.poster-card img {
  width: 100%;
  aspect-ratio: 3/4;
  object-fit: cover;
  display: block;
}

.poster-overlay {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  background: linear-gradient(transparent, rgba(0, 0, 0, 0.9));
  padding: 2rem 0.75rem 0.75rem;
}

.default-label {
  position: absolute;
  top: 0.5rem;
  left: 0.5rem;
  background: #00d4ff;
  color: #000;
  padding: 0.15rem 0.5rem;
  border-radius: 4px;
  font-size: 0.65rem;
  font-weight: 600;
}

.poster-file {
  font-size: 0.7rem;
  color: #aaa;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-bottom: 0.5rem;
}

.poster-actions {
  display: flex;
  gap: 0.5rem;
}

.btn-poster-action {
  padding: 0.4rem;
  border: none;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.1);
  cursor: pointer;
  font-size: 0.9rem;
  transition: all 0.2s ease;
}

.btn-poster-action:hover {
  background: rgba(255, 255, 255, 0.2);
}

.btn-poster-action.delete {
  background: rgba(255, 68, 68, 0.2);
}

.btn-poster-action.delete:hover {
  background: rgba(255, 68, 68, 0.3);
}

/* Video Preview */
.video-preview-container {
  background: rgba(0, 0, 0, 0.3);
  padding: 1.5rem;
  border-radius: 12px;
}

.video-preview {
  width: 100%;
  max-height: 300px;
  border-radius: 8px;
  margin-bottom: 1rem;
}

.video-info {
  display: flex;
  gap: 0.5rem;
  font-size: 0.9rem;
}

/* Info Grid */
.info-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1rem;
}

.info-item {
  background: rgba(0, 0, 0, 0.2);
  padding: 1rem;
  border-radius: 8px;
}

.info-label {
  display: block;
  color: #888;
  font-size: 0.75rem;
  margin-bottom: 0.25rem;
  text-transform: uppercase;
}

.info-value {
  color: #fff;
  font-size: 0.95rem;
  word-break: break-all;
}

.info-value.never-used {
  color: #666;
  font-style: italic;
}

.difficulty-value {
  padding: 0.2rem 0.5rem;
  border-radius: 4px;
  text-transform: capitalize;
}

/* Detail Footer */
.detail-footer {
  padding: 1.5rem 2rem 2rem;
  display: flex;
  justify-content: flex-end;
}

.btn-delete-opening {
  padding: 0.75rem 1.5rem;
  background: rgba(255, 68, 68, 0.2);
  border: 1px solid rgba(255, 68, 68, 0.3);
  border-radius: 8px;
  color: #ff4444;
  cursor: pointer;
  font-size: 0.9rem;
  font-weight: 500;
  transition: all 0.2s ease;
}

.btn-delete-opening:hover {
  background: rgba(255, 68, 68, 0.3);
}

/* Confirmation Modal */
.confirm-modal {
  background: #1a1a2e;
  border-radius: 16px;
  padding: 2rem;
  max-width: 400px;
  width: 90%;
  text-align: center;
  border: 1px solid rgba(255, 255, 255, 0.1);
}

.confirm-modal h3 {
  color: #ff4444;
  margin-bottom: 1rem;
}

.confirm-modal p {
  color: #aaa;
  margin-bottom: 1.5rem;
  line-height: 1.5;
}

.confirm-actions {
  display: flex;
  gap: 1rem;
  justify-content: center;
}

.btn-cancel {
  padding: 0.75rem 1.5rem;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 8px;
  color: #fff;
  cursor: pointer;
  font-weight: 500;
}

.btn-cancel:hover {
  background: rgba(255, 255, 255, 0.2);
}

.btn-confirm-delete {
  padding: 0.75rem 1.5rem;
  background: #ff4444;
  border: none;
  border-radius: 8px;
  color: #fff;
  cursor: pointer;
  font-weight: 500;
}

.btn-confirm-delete:hover {
  background: #ff2222;
}

/* Toast */
.toast-container {
  position: fixed;
  bottom: 2rem;
  right: 2rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  z-index: 1001;
}

.toast {
  padding: 1rem 1.5rem;
  border-radius: 8px;
  color: #fff;
  font-weight: 500;
  animation: slideIn 0.3s ease;
}

.toast.success {
  background: linear-gradient(90deg, #00d4ff, #00a8cc);
}

.toast.error {
  background: linear-gradient(90deg, #ff4444, #cc2222);
}

@keyframes slideIn {
  from { transform: translateX(100%); opacity: 0; }
  to { transform: translateX(0); opacity: 1; }
}

/* Add Opening Button */
.btn-add-opening {
  padding: 0.75rem 1.5rem;
  background: linear-gradient(90deg, #00d4ff, #7b2cbf);
  border: none;
  border-radius: 8px;
  color: #fff;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.3s ease;
  white-space: nowrap;
}

.btn-add-opening:hover {
  opacity: 0.9;
  transform: translateY(-1px);
}

/* Create Modal */
.create-modal {
  max-width: 700px;
}

.form-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1rem;
}

.form-group {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.form-group.full-width {
  grid-column: span 2;
}

.form-group label {
  color: #888;
  font-size: 0.85rem;
}

.form-group input {
  padding: 0.75rem;
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.3);
  color: #fff;
  font-size: 0.95rem;
}

.form-group input:focus {
  outline: none;
  border-color: #00d4ff;
}

.file-selection {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.file-select {
  width: 100%;
  padding: 0.75rem;
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.3);
  color: #fff;
  font-size: 0.95rem;
}

.file-select:focus {
  outline: none;
  border-color: #00d4ff;
}

.audio-preview {
  background: rgba(0, 0, 0, 0.2);
  padding: 1rem;
  border-radius: 8px;
}

.preview-player {
  width: 100%;
}

.section-hint {
  color: #666;
  font-size: 0.85rem;
  margin-bottom: 1rem;
}

.poster-selection-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 0.75rem;
  max-height: 300px;
  overflow-y: auto;
  padding: 0.5rem;
}

.poster-select-item {
  position: relative;
  cursor: pointer;
  border: 2px solid transparent;
  border-radius: 8px;
  overflow: hidden;
  transition: all 0.2s ease;
}

.poster-select-item input {
  display: none;
}

.poster-select-item img {
  width: 100%;
  aspect-ratio: 3/4;
  object-fit: cover;
  display: block;
}

.poster-select-item:hover {
  border-color: rgba(0, 212, 255, 0.5);
}

.poster-select-item.selected {
  border-color: #00d4ff;
}

.poster-select-name {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  background: rgba(0, 0, 0, 0.8);
  padding: 0.25rem 0.5rem;
  font-size: 0.65rem;
  color: #aaa;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.poster-check-icon {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  width: 24px;
  height: 24px;
  background: #00d4ff;
  color: #000;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.8rem;
  font-weight: bold;
  opacity: 0;
  transform: scale(0.5);
  transition: all 0.2s ease;
}

.poster-select-item.selected .poster-check-icon {
  opacity: 1;
  transform: scale(1);
}

.create-footer {
  justify-content: flex-end;
  gap: 1rem;
}

.btn-create {
  padding: 0.75rem 2rem;
  background: linear-gradient(90deg, #00d4ff, #7b2cbf);
  border: none;
  border-radius: 8px;
  color: #fff;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.3s ease;
}

.btn-create:hover:not(:disabled) {
  opacity: 0.9;
}

.btn-create:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Upload Zone */
.upload-zone {
  border: 2px dashed rgba(255, 255, 255, 0.2);
  border-radius: 12px;
  background: rgba(0, 0, 0, 0.2);
  transition: all 0.3s ease;
}

.upload-zone:hover {
  border-color: rgba(0, 212, 255, 0.5);
  background: rgba(0, 0, 0, 0.3);
}

.upload-zone.has-file {
  border-style: solid;
  border-color: #00d4ff;
}

.file-input-hidden {
  display: none;
}

.upload-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 2rem;
  cursor: pointer;
  gap: 0.5rem;
}

.upload-icon {
  font-size: 2.5rem;
}

.upload-text {
  color: #aaa;
  font-size: 0.95rem;
}

.upload-hint {
  color: #666;
  font-size: 0.8rem;
}

.uploaded-file {
  padding: 1rem;
}

.uploaded-file-info {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1rem;
}

.file-icon {
  font-size: 2rem;
}

.file-details {
  flex: 1;
  min-width: 0;
}

.file-details .file-name {
  display: block;
  color: #fff;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.file-details .file-size {
  color: #888;
  font-size: 0.8rem;
}

.btn-remove-file {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: none;
  background: rgba(255, 68, 68, 0.2);
  color: #ff4444;
  font-size: 1.2rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.btn-remove-file:hover {
  background: rgba(255, 68, 68, 0.3);
}

/* Poster Uploads */
.poster-uploads {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.5rem;
}

.poster-upload-block {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.poster-label {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.format-badge {
  display: inline-block;
  padding: 0.3rem 0.75rem;
  border-radius: 6px;
  font-size: 0.8rem;
  font-weight: 600;
  width: fit-content;
}

.format-badge.tiktok {
  background: linear-gradient(90deg, #ff0050, #00f2ea);
  color: #fff;
}

.format-badge.fullsize {
  background: linear-gradient(90deg, #ff0000, #cc0000);
  color: #fff;
}

.format-hint {
  color: #666;
  font-size: 0.75rem;
}

.poster-zone {
  min-height: 180px;
}

.poster-zone .upload-placeholder {
  min-height: 160px;
}

.poster-preview-container {
  position: relative;
  padding: 0.5rem;
}

.poster-preview-img {
  width: 100%;
  max-height: 200px;
  object-fit: contain;
  border-radius: 8px;
}

.poster-preview-img.horizontal {
  max-height: 150px;
}

.poster-preview-overlay {
  position: absolute;
  bottom: 0.5rem;
  left: 0.5rem;
  right: 0.5rem;
  background: rgba(0, 0, 0, 0.8);
  padding: 0.5rem;
  border-radius: 0 0 8px 8px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.preview-file-name {
  color: #aaa;
  font-size: 0.75rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 1;
}

.btn-remove-poster {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: none;
  background: rgba(255, 68, 68, 0.3);
  color: #ff4444;
  font-size: 1rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  margin-left: 0.5rem;
}

.btn-remove-poster:hover {
  background: rgba(255, 68, 68, 0.5);
}

/* Upload Progress */
.upload-progress {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex: 1;
}

.progress-bar-small {
  flex: 1;
  height: 6px;
  background: rgba(255, 255, 255, 0.1);
  border-radius: 3px;
  overflow: hidden;
}

.progress-fill-small {
  height: 100%;
  background: linear-gradient(90deg, #00d4ff, #7b2cbf);
  transition: width 0.3s ease;
}

.progress-text-small {
  color: #00d4ff;
  font-size: 0.8rem;
  white-space: nowrap;
}

/* Confirm modal whitespace */
.confirm-modal p {
  white-space: pre-line;
}

/* Responsive */
@media (max-width: 768px) {
  .media-manager {
    padding: 1rem;
  }

  .type-switch {
    flex-direction: column;
    align-items: center;
  }

  .switch-btn {
    width: 100%;
    max-width: 300px;
    justify-content: center;
  }

  .search-bar {
    flex-direction: column;
    align-items: center;
  }

  .search-input {
    max-width: 100%;
  }

  .content-grid {
    grid-template-columns: 1fr;
  }

  .detail-modal {
    max-width: 100%;
    margin: 0.5rem;
  }

  .detail-header {
    padding: 1.5rem 1.5rem 1rem;
  }

  .detail-content {
    padding: 0 1.5rem;
  }

  .detail-footer {
    padding: 1.5rem;
  }

  .posters-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .info-grid {
    grid-template-columns: 1fr;
  }

  .form-grid {
    grid-template-columns: 1fr;
  }

  .form-group.full-width {
    grid-column: span 1;
  }

  .poster-selection-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .create-footer {
    flex-direction: column;
  }

  .btn-add-opening {
    width: 100%;
    margin-top: 0.5rem;
  }

  .poster-uploads {
    grid-template-columns: 1fr;
  }

  .upload-progress {
    width: 100%;
    margin-bottom: 0.5rem;
  }
}
</style>
