<script setup lang="ts">
import { computed, watch } from 'vue'
import { invoke } from '@tauri-apps/api/core'
import { Loader2, List, Link } from 'lucide-vue-next'
import { useQueueStore } from '../stores/queue'
import { useSettingsStore } from '../stores/settings'
import { useAnalysisStore } from '../stores/analysis'
import AppSelect from '../components/ui/AppSelect.vue'
import type { AnalysisMetadata, PlaylistMetadata, VideoMetadata } from '../types/media'
import { isPlaylistMetadata } from '../types/media'
import {
  countSelectedEntries,
  detectMixUrl,
  normalizeBatchLinks,
  stripPlaylistContext,
  toSelectableEntries
} from '../utils/analysis'

const queueStore = useQueueStore()
const settingsStore = useSettingsStore()
const analysisStore = useAnalysisStore()

const qualityOptions = [
  { label: '最佳画质', value: 'best' },
  { label: '1080p', value: '1080' },
  { label: '720p', value: '720' },
  { label: '480p', value: '480' },
]

const videoFormatOptions = [
  { label: '原格式', value: 'original' },
  { label: 'MP4', value: 'mp4' },
  { label: 'WebM', value: 'webm' },
  { label: 'Matroska (MKV)', value: 'mkv' },
  { label: 'FLV', value: 'flv' },
  { label: 'AVI', value: 'avi' },
]

const audioFormatOptions = [
  { label: '原格式', value: 'original' },
  { label: 'MP3', value: 'mp3' },
  { label: 'M4A', value: 'm4a' },
  { label: 'AAC', value: 'aac' },
  { label: 'Opus', value: 'opus' },
  { label: 'Vorbis', value: 'vorbis' },
  { label: 'WAV', value: 'wav' },
  { label: 'FLAC', value: 'flac' },
]

const playlistMetadata = computed<PlaylistMetadata | null>(() => {
  return isPlaylistMetadata(analysisStore.metadata) ? analysisStore.metadata : null
})

const singleMetadata = computed<VideoMetadata | null>(() => {
  return analysisStore.metadata && !isPlaylistMetadata(analysisStore.metadata)
    ? analysisStore.metadata
    : null
})

const selectedCount = computed(() => countSelectedEntries(playlistMetadata.value))

watch(() => settingsStore.settings.download_path, (newPath) => {
  if (newPath && !analysisStore.options.output_path) {
    analysisStore.options.output_path = newPath
  }
}, { immediate: true })

watch(() => analysisStore.url, (newUrl) => {
  analysisStore.isMix = !!newUrl && detectMixUrl(newUrl)
  if (!analysisStore.isMix) {
    analysisStore.scanMix = false
  }
})

watch(() => analysisStore.options.is_audio_only, () => {
  analysisStore.options.output_format = 'original'
})

async function processThumbnail(url: string | undefined | null): Promise<string | undefined> {
  if (!url) return undefined

  if (url.includes('instagram.com') || url.includes('fbcdn.net') || url.includes('cdninstagram.com')) {
    try {
      return await invoke<string>('fetch_image', { url })
    } catch (error) {
      console.warn('Thumbnail fetch failed, falling back to URL', error)
      return url
    }
  }

  return url
}

async function processMetadataThumbnails(metadata: AnalysisMetadata) {
  if (isPlaylistMetadata(metadata)) {
    await Promise.all(metadata.entries.map(async (entry) => {
      if (entry.thumbnail) {
        entry.thumbnail = await processThumbnail(entry.thumbnail) ?? entry.thumbnail
      }
    }))
    return
  }

  if (metadata.thumbnail) {
    metadata.thumbnail = await processThumbnail(metadata.thumbnail) ?? metadata.thumbnail
  }
}

async function analyzeBatchLinks() {
  const validLinks = normalizeBatchLinks(analysisStore.url)

  if (validLinks.length === 0) {
    throw new Error('未找到有效的单个视频链接（已忽略纯播放列表链接）。')
  }

  const results: VideoMetadata[] = []

  for (const link of validLinks) {
    try {
      const res = await invoke<AnalysisMetadata>('fetch_metadata', { url: link, parseMixPlaylist: false })
      if (!isPlaylistMetadata(res)) {
        results.push(res)
      }
    } catch (error) {
      console.warn(`Failed to parse ${link}`, error)
    }
  }

  if (results.length === 0) {
    throw new Error('所有链接解析失败或均为播放列表。')
  }

  await Promise.all(results.map(result => processMetadataThumbnails(result)))

  analysisStore.metadata = {
    id: `batch_download_${Date.now()}`,
    title: `批量解析结果 (${results.length} 个视频)`,
    entries: toSelectableEntries(results)
  }
}

async function analyzeSingleLink() {
  let urlToScan = analysisStore.url
  let parseMix = false

  if (analysisStore.isMix) {
    if (analysisStore.scanMix) {
      parseMix = true
    } else {
      urlToScan = stripPlaylistContext(urlToScan)
    }
  }

  const res = await invoke<AnalysisMetadata>('fetch_metadata', { url: urlToScan, parseMixPlaylist: parseMix })
  await processMetadataThumbnails(res)

  if (isPlaylistMetadata(res)) {
    res.entries = toSelectableEntries(res.entries)
  }

  analysisStore.metadata = res
}

async function analyze() {
  if (!analysisStore.url) return

  analysisStore.loading = true
  analysisStore.error = ''
  analysisStore.metadata = null

  try {
    if (analysisStore.isBatchMode) {
      await analyzeBatchLinks()
    } else {
      await analyzeSingleLink()
    }
  } catch (error: unknown) {
    analysisStore.error = error instanceof Error ? error.message : String(error)
  } finally {
    analysisStore.loading = false
  }
}

async function startDownload() {
  if (!analysisStore.metadata) return

  if (!analysisStore.options.output_path) {
    analysisStore.options.output_path = settingsStore.settings.download_path
  }

  analysisStore.options.cookies_path = settingsStore.settings.cookies_path || ''

  try {
    if (playlistMetadata.value) {
      const selectedEntries = playlistMetadata.value.entries.filter(entry => entry.selected)

      if (selectedEntries.length === 0) {
        analysisStore.error = '请至少选择一个要下载的视频。'
        return
      }

      for (const entry of selectedEntries) {
        const videoUrl = entry.url || `https://www.youtube.com/watch?v=${entry.id}`
        const id = await invoke<string>('start_download', {
          url: videoUrl,
          options: analysisStore.options,
          metadata: entry
        })

        queueStore.addTask({
          id,
          title: entry.title,
          thumbnail: entry.thumbnail,
          progress: 0,
          speed: '等待中...',
          status: 'pending'
        })
      }
    } else if (singleMetadata.value) {
      const urlToDownload = analysisStore.isMix && !analysisStore.scanMix
        ? stripPlaylistContext(analysisStore.url)
        : analysisStore.url

      const id = await invoke<string>('start_download', {
        url: urlToDownload,
        options: analysisStore.options,
        metadata: singleMetadata.value
      })

      queueStore.addTask({
        id,
        title: singleMetadata.value.title,
        thumbnail: singleMetadata.value.thumbnail,
        progress: 0,
        speed: '等待中...',
        status: 'pending'
      })
    }

    analysisStore.reset()
  } catch (error: unknown) {
    analysisStore.error = `下载启动失败： ${error instanceof Error ? error.message : String(error)}`
  }
}
</script>

<template>
  <div class="max-w-5xl mx-auto p-8">
    <header class="mb-8">
      <h1 class="text-3xl font-bold text-zinc-900 dark:text-white">新建下载</h1>
    </header>

    <div class="bg-white dark:bg-zinc-900 p-6 rounded-2xl shadow-sm border border-gray-200 dark:border-zinc-800 mb-8">
      <div class="flex flex-col gap-3">
        <div class="flex justify-end mb-1">
          <button
            @click="analysisStore.isBatchMode = !analysisStore.isBatchMode"
            class="text-xs font-medium flex items-center gap-1.5 px-3 py-1.5 rounded-lg transition-colors"
            :class="analysisStore.isBatchMode ? 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400' : 'bg-gray-100 text-gray-600 dark:bg-zinc-800 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-zinc-700'"
          >
            <List v-if="analysisStore.isBatchMode" class="w-3.5 h-3.5" />
            <Link v-else class="w-3.5 h-3.5" />
            {{ analysisStore.isBatchMode ? '单链接模式' : '批量输入模式' }}
          </button>
        </div>

        <div class="flex gap-4 items-start">
          <div class="flex-1 relative">
            <textarea
              v-if="analysisStore.isBatchMode"
              v-model="analysisStore.url"
              placeholder="每行输入一个链接..."
              rows="5"
              class="w-full bg-gray-50 dark:bg-zinc-800 border-none rounded-xl px-4 py-3 text-zinc-900 dark:text-white focus:ring-2 focus:ring-blue-500 outline-none resize-none font-mono text-sm leading-relaxed"
            ></textarea>
            <input
              v-else
              v-model="analysisStore.url"
              type="text"
              placeholder="https://..."
              class="w-full bg-gray-50 dark:bg-zinc-800 border-none rounded-xl px-4 py-3 text-zinc-900 dark:text-white focus:ring-2 focus:ring-blue-500 outline-none"
              @keyup.enter="analyze"
            />
          </div>

          <button
            @click="analyze"
            :disabled="analysisStore.loading"
            class="bg-blue-600 hover:bg-blue-700 text-white px-6 py-3 rounded-xl font-medium transition-colors disabled:opacity-50 flex items-center gap-2 shrink-0 h-[48px]"
          >
            <Loader2 v-if="analysisStore.loading" class="animate-spin w-5 h-5" />
            <span v-else>解析</span>
          </button>
        </div>
      </div>

      <div v-if="!analysisStore.isBatchMode && analysisStore.isMix" class="mt-4 flex items-center gap-3">
        <button
          @click="analysisStore.scanMix = !analysisStore.scanMix"
          class="w-12 h-6 rounded-full relative transition-colors duration-200 ease-in-out flex-shrink-0"
          :class="analysisStore.scanMix ? 'bg-blue-600' : 'bg-gray-300 dark:bg-zinc-600'"
        >
          <span
            class="absolute top-1 left-1 w-4 h-4 bg-white rounded-full transition-transform duration-200"
            :class="analysisStore.scanMix ? 'translate-x-6' : 'translate-x-0'"
          />
        </button>
        <span class="text-sm font-medium text-zinc-700 dark:text-gray-300">解析播放列表 (前20项)</span>
      </div>

      <p v-if="analysisStore.error" class="mt-3 text-red-500 text-sm">{{ analysisStore.error }}</p>
    </div>

    <div v-if="analysisStore.metadata" class="bg-white dark:bg-zinc-900 rounded-2xl shadow-sm border border-gray-200 dark:border-zinc-800 overflow-hidden mb-8">
      <div v-if="playlistMetadata" class="p-6 border-b border-gray-200 dark:border-zinc-800">
        <div class="flex items-start justify-between mb-4">
          <div>
            <h2 class="text-xl font-bold text-zinc-900 dark:text-white">{{ playlistMetadata.title }}</h2>
            <p class="text-blue-500 mt-1 font-medium">{{ playlistMetadata.entries.length }} 个视频</p>
          </div>
        </div>

        <div class="flex flex-col md:flex-row items-center justify-between gap-4 bg-gray-50 dark:bg-zinc-800/50 p-4 rounded-xl">
          <div class="flex items-center gap-2 w-full md:w-auto">
            <button @click="analysisStore.setAllEntries(true)" class="text-base font-medium px-3 py-1.5 rounded-lg bg-white dark:bg-zinc-700 hover:bg-gray-100 dark:hover:bg-zinc-600 text-zinc-700 dark:text-gray-200 border border-gray-200 dark:border-zinc-600 transition-colors shadow-sm">全选</button>
            <button @click="analysisStore.setAllEntries(false)" class="text-base font-medium px-3 py-1.5 rounded-lg bg-white dark:bg-zinc-700 hover:bg-gray-100 dark:hover:bg-zinc-600 text-zinc-700 dark:text-gray-200 border border-gray-200 dark:border-zinc-600 transition-colors shadow-sm">取消全选</button>
            <button @click="analysisStore.invertSelection()" class="text-base font-medium px-3 py-1.5 rounded-lg bg-white dark:bg-zinc-700 hover:bg-gray-100 dark:hover:bg-zinc-600 text-zinc-700 dark:text-gray-200 border border-gray-200 dark:border-zinc-600 transition-colors shadow-sm">反选</button>
          </div>

          <div class="flex items-center gap-6 w-full md:w-auto justify-end">
            <div class="flex items-center gap-x-4 p-3 bg-gray-50 dark:bg-zinc-800 rounded-xl">
              <span class="font-medium text-base text-zinc-700 dark:text-gray-300">仅音频</span>
              <button
                @click="analysisStore.options.is_audio_only = !analysisStore.options.is_audio_only"
                class="w-12 h-6 rounded-full relative transition-colors duration-200 ease-in-out"
                :class="analysisStore.options.is_audio_only ? 'bg-blue-600' : 'bg-gray-300 dark:bg-zinc-600'"
              >
                <span
                  class="absolute top-1 left-1 w-4 h-4 bg-white rounded-full transition-transform duration-200"
                  :class="analysisStore.options.is_audio_only ? 'translate-x-6' : 'translate-x-0'"
                />
              </button>
            </div>

            <div class="flex items-center gap-3">
              <div class="w-44">
                <AppSelect
                  v-model="analysisStore.options.quality"
                  :options="qualityOptions"
                  :disabled="analysisStore.options.is_audio_only"
                />
              </div>
            </div>

            <div class="flex items-center gap-3">
              <div class="w-48">
                <AppSelect
                  v-model="analysisStore.options.output_format"
                  :options="analysisStore.options.is_audio_only ? audioFormatOptions : videoFormatOptions"
                />
              </div>
            </div>
          </div>
        </div>
      </div>

      <div v-if="playlistMetadata" class="max-h-[500px] overflow-y-auto p-2 space-y-2 bg-gray-50/50 dark:bg-black/20">
        <div
          v-for="entry in playlistMetadata.entries"
          :key="entry.id"
          class="flex items-center gap-4 p-3 rounded-xl hover:bg-white dark:hover:bg-zinc-800 transition-colors border border-transparent hover:border-gray-200 dark:hover:border-zinc-700 group"
          :class="entry.selected ? 'opacity-100' : 'opacity-60 grayscale'"
        >
          <button
            @click="entry.selected = !entry.selected"
            class="w-6 h-6 rounded-lg border-2 flex items-center justify-center transition-colors shrink-0"
            :class="entry.selected ? 'bg-blue-600 border-blue-600 text-white' : 'border-gray-300 dark:border-zinc-600 hover:border-blue-400'"
          >
            <svg v-if="entry.selected" xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" viewBox="0 0 20 20" fill="currentColor">
              <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
            </svg>
          </button>

          <img :src="entry.thumbnail || '/placeholder.png'" class="w-24 h-14 object-cover rounded-lg bg-gray-200 dark:bg-zinc-700 shrink-0" />

          <div class="flex-1 min-w-0">
            <h4 class="font-medium text-zinc-900 dark:text-white truncate text-sm" :title="entry.title">{{ entry.title }}</h4>
            <p class="text-xs text-gray-500 dark:text-gray-400 mt-0.5">
              {{ entry.duration ? Math.floor(entry.duration / 60) + ':' + String(Math.floor(entry.duration % 60)).padStart(2, '0') : '' }}
              <span v-if="entry.uploader" class="mx-1">•</span> {{ entry.uploader }}
            </p>
          </div>
        </div>
      </div>

      <div v-else-if="singleMetadata" class="p-6 flex flex-col md:flex-row gap-6">
        <img :src="singleMetadata.thumbnail || '/placeholder.png'" class="w-full md:w-64 aspect-video object-cover rounded-lg bg-gray-100 dark:bg-zinc-800" />

        <div class="flex-1">
          <h2 class="text-xl font-bold text-zinc-900 dark:text-white line-clamp-2">{{ singleMetadata.title }}</h2>
          <p v-if="singleMetadata.uploader" class="text-gray-500 dark:text-gray-400 mt-1">{{ singleMetadata.uploader }}</p>

          <div class="grid grid-cols-1 md:grid-cols-3 gap-4 mt-6">
            <div class="flex items-center justify-between p-3 bg-gray-50 dark:bg-zinc-800 rounded-xl">
              <span class="font-medium text-base">仅音频</span>
              <button
                @click="analysisStore.options.is_audio_only = !analysisStore.options.is_audio_only"
                class="w-12 h-6 rounded-full relative transition-colors duration-200 ease-in-out"
                :class="analysisStore.options.is_audio_only ? 'bg-blue-600' : 'bg-gray-300 dark:bg-zinc-600'"
              >
                <span
                  class="absolute top-1 left-1 w-4 h-4 bg-white rounded-full transition-transform duration-200"
                  :class="analysisStore.options.is_audio_only ? 'translate-x-6' : 'translate-x-0'"
                />
              </button>
            </div>

            <div class="relative">
              <AppSelect
                v-model="analysisStore.options.quality"
                :options="qualityOptions"
                :disabled="analysisStore.options.is_audio_only"
              />
            </div>

            <div class="relative">
              <AppSelect
                v-model="analysisStore.options.output_format"
                :options="analysisStore.options.is_audio_only ? audioFormatOptions : videoFormatOptions"
              />
            </div>
          </div>
        </div>
      </div>

      <div class="px-6 py-4 bg-gray-50 dark:bg-zinc-800/50 border-t border-gray-200 dark:border-zinc-800 flex justify-end">
        <button
          @click="startDownload"
          class="bg-blue-600 hover:bg-blue-700 text-white px-8 py-3 rounded-xl font-bold transition-colors shadow-lg shadow-blue-600/20"
        >
          立即下载 {{ selectedCount > 0 ? `(${selectedCount})` : '' }}
        </button>
      </div>
    </div>

    <div v-if="queueStore.tasks.length > 0">
      <h3 class="text-lg font-bold mb-4">进行中的任务</h3>
      <div class="space-y-3">
        <div v-for="task in queueStore.tasks.slice().reverse()" :key="task.id" class="bg-white dark:bg-zinc-900 p-4 rounded-xl border border-gray-200 dark:border-zinc-800 flex items-center gap-4">
          <img :src="task.thumbnail || '/placeholder.png'" class="w-16 h-16 object-cover rounded-lg bg-gray-100 dark:bg-zinc-800" />
          <div class="flex-1 min-w-0">
            <div class="flex justify-between mb-1">
              <h4 class="font-medium truncate pr-4">{{ task.title }}</h4>
              <span class="text-xs font-mono text-gray-500 whitespace-nowrap">
                {{ task.status === 'finished' ? '已完成' : (task.status === 'error' ? '失败' : task.speed) }}
              </span>
            </div>
            <div class="h-2 bg-gray-100 dark:bg-zinc-800 rounded-full overflow-hidden">
              <div
                class="h-full transition-all duration-300"
                :style="{ width: `${task.progress}%` }"
                :class="task.status === 'error' ? 'bg-red-500' : (task.status === 'finished' ? 'bg-green-500' : 'bg-blue-600')"
              />
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
