<script setup lang="ts">
import { CheckCircle, Eye, FileArchive, FilePlus, GitBranch, Loader2, Rocket, Upload, UploadCloud, X } from 'lucide-vue-next'
import { computed, onMounted, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { useRoute, useRouter } from 'vue-router'
import { toast } from 'vue-sonner'

import { BasicPage } from '@/components/global-layout'
import api from '@/services/api'

const { t } = useI18n()

interface Application {
  id: number
  name: string
}

interface VersionFileInfo {
  file_path: string
  file_name: string
  file_size: number
  file_hash: string
  file_type: string
}

interface UploadResponse {
  file_path: string
  file_size: number
  file_hash: string
  files: VersionFileInfo[]
}

const route = useRoute()
const router = useRouter()

const loading = ref(false)
const saving = ref(false)
const uploading = ref(false)
const uploadProgress = ref(0)
const uploadSpeed = ref('')
const applications = ref<Application[]>([])
const baseVersions = ref<{ id: number, version: string }[]>([])
const loadingBaseVersions = ref(false)

const formData = ref({
  application_id: '',
  version: '',
  description: '',
  update_strategy: 'optional' as 'optional' | 'forced',
  update_type: 'full' as 'full' | 'patch',
  update_method: 'auto' as 'auto' | 'manual',
  custom_download_url: '',
  changelog: '',
  entry_file: '',
  file: null as File | null,
  base_version_id: '' as string,
})

const uploadedData = ref<UploadResponse | null>(null)
const fileInputRef = ref<HTMLInputElement | null>(null)

const selectedApplication = computed(() => {
  return applications.value.find(app => String(app.id) === formData.value.application_id)
})

const executableFiles = computed(() => {
  if (!uploadedData.value)
    return []
  return uploadedData.value.files.filter(f => f.file_type === 'executable')
})

const fileSize = computed(() => {
  if (formData.value.file) {
    const size = formData.value.file.size
    return formatFileSize(size)
  }
  return null
})

const isForcedUpdate = computed({
  get: () => formData.value.update_strategy === 'forced',
  set: (val: boolean) => {
    formData.value.update_strategy = val ? 'forced' : 'optional'
  },
})

function formatFileSize(size: number): string {
  if (size < 1024)
    return `${size} B`
  if (size < 1024 * 1024)
    return `${(size / 1024).toFixed(2)} KB`
  return `${(size / (1024 * 1024)).toFixed(2)} MB`
}

const typeLabel = computed(() => {
  const map: Record<string, string> = {
    full: t('admin.versions.types.full'),
    patch: t('admin.versions.types.patch'),
  }
  return map[formData.value.update_type] || formData.value.update_type
})

const methodLabel = computed(() => {
  const map: Record<string, string> = {
    auto: t('admin.versions.methods.auto'),
    manual: t('admin.versions.methods.manual'),
  }
  return map[formData.value.update_method] || formData.value.update_method
})

async function fetchApplications() {
  loading.value = true
  try {
    const data = await api.get<{ applications: Application[] }>('/dev/applications')
    applications.value = data?.applications || []
    const appParam = route.query.app as string
    if (appParam) {
      formData.value.application_id = appParam
    }
  }
  catch (error) {
    console.error('获取应用列表失败:', error)
  }
  finally {
    loading.value = false
  }
}

async function fetchBaseVersions(appId: string) {
  if (!appId) {
    baseVersions.value = []
    return
  }
  loadingBaseVersions.value = true
  try {
    const data = await api.get<{ versions: { id: number, version: string, update_type: string }[] }>(
      `/dev/versions?application_id=${appId}&update_type=full&page_size=100`
    )
    // 只筛选全量版本
    const versions = data?.versions || []
    baseVersions.value = versions.filter(v => v.update_type === 'full')
  }
  catch (error) {
    console.error('获取基础版本列表失败:', error)
    baseVersions.value = []
  }
  finally {
    loadingBaseVersions.value = false
  }
}

// 监听应用变化
watch(
  () => formData.value.application_id,
  (newAppId) => {
    if (newAppId && formData.value.update_type === 'patch') {
      fetchBaseVersions(newAppId)
    } else if (!newAppId) {
      // 只有当应用被清空时才清空基础版本
      baseVersions.value = []
      formData.value.base_version_id = ''
    }
  },
  { immediate: true }
)

// 监听更新类型变化
watch(
  () => formData.value.update_type,
  (newType) => {
    if (newType === 'patch' && formData.value.application_id) {
      fetchBaseVersions(formData.value.application_id)
    } else if (newType !== 'patch') {
      baseVersions.value = []
      formData.value.base_version_id = ''
    }
  },
  { immediate: true }
)

function handleFileSelect(event: Event) {
  const target = event.target as HTMLInputElement
  if (target.files && target.files.length > 0) {
    const file = target.files[0]
    if (!file.name.toLowerCase().endsWith('.zip')) {
      toast.error(t('admin.versions.createForm.zipOnly'))
      return
    }
    formData.value.file = file
    uploadedData.value = null
  }
}

function removeFile() {
  formData.value.file = null
  uploadedData.value = null
  if (fileInputRef.value) {
    fileInputRef.value.value = ''
  }
}

async function uploadZipFile() {
  if (!formData.value.file) {
    toast.error(t('admin.versions.createForm.selectZipFirst'))
    return
  }

  uploading.value = true
  uploadProgress.value = 0
  uploadSpeed.value = ''
  try {
    const formDataObj = new FormData()
    formDataObj.append('file', formData.value.file)

    const response = await api.postFormDataWithProgress<UploadResponse>(
      '/dev/versions/upload-zip',
      formDataObj,
      (progress, speed) => {
        uploadProgress.value = progress
        uploadSpeed.value = speed
      }
    )
    uploadedData.value = response
    toast.success(t('admin.versions.createForm.uploadSuccess'))
  }
  catch (error: any) {
    console.error('上传文件失败:', error)
    toast.error(error.message || t('admin.versions.createForm.uploadFailed'))
  }
  finally {
    uploading.value = false
    uploadProgress.value = 0
    uploadSpeed.value = ''
  }
}

async function handleSubmit() {
  if (!formData.value.application_id) {
    toast.error(t('admin.versions.createForm.selectAppRequired'))
    return
  }
  if (!formData.value.version) {
    toast.error(t('admin.versions.createForm.versionRequired'))
    return
  }
  if (!uploadedData.value) {
    toast.error(t('admin.versions.createForm.uploadZipRequired'))
    return
  }

  saving.value = true
  try {
    const payload: Record<string, any> = {
      application_id: Number(formData.value.application_id),
      version: formData.value.version,
      description: formData.value.description,
      update_strategy: formData.value.update_strategy,
      update_type: formData.value.update_type,
      update_method: formData.value.update_method,
      custom_download_url: formData.value.custom_download_url,
      changelog: formData.value.changelog,
      entry_file: formData.value.entry_file,
      file_path: uploadedData.value.file_path,
      file_size: uploadedData.value.file_size,
      file_hash: uploadedData.value.file_hash,
      files: uploadedData.value.files || [],
    }
    // 如果是补丁版本，添加基础版本ID
    if (formData.value.update_type === 'patch' && formData.value.base_version_id) {
      payload.base_version_id = Number(formData.value.base_version_id)
    }
    await api.post('/dev/versions', payload)
    toast.success(t('admin.versions.createForm.createSuccess'))
    router.push('/admin/versions')
  }
  catch (error: any) {
    console.error('创建版本失败:', error)
    toast.error(error.message || t('admin.versions.createForm.createFailed'))
  }
  finally {
    saving.value = false
  }
}

onMounted(() => {
  fetchApplications()
})
</script>

<template>
  <BasicPage
    :title="t('admin.versions.createForm.title')"
    :description="t('admin.versions.createForm.description')"
    :breadcrumbs="[
      { title: t('admin.versions.title'), href: '/admin/versions' },
      { title: t('admin.versions.createForm.title') },
    ]"
    sticky
  >
    <div class="space-y-6">
      <div class="grid gap-6 lg:grid-cols-3">
        <div class="lg:col-span-2 space-y-6">
          <UiCard>
            <UiCardHeader>
              <UiCardTitle class="flex items-center gap-2">
                <GitBranch class="size-5" />
                {{ t('admin.versions.createForm.versionConfig') }}
              </UiCardTitle>
              <UiCardDescription>{{ t('admin.versions.createForm.versionConfigDesc') }}</UiCardDescription>
            </UiCardHeader>
            <UiCardContent class="space-y-6">
              <div class="space-y-2">
                <UiLabel>{{ t('admin.versions.createForm.selectApp') }} <span class="text-destructive">*</span></UiLabel>
                <UiSelect v-model="formData.application_id" :disabled="saving || loading">
                  <UiSelectTrigger>
                    <UiSelectValue :placeholder="t('admin.versions.createForm.selectAppPlaceholder')" />
                  </UiSelectTrigger>
                  <UiSelectContent>
                    <UiSelectItem
                      v-for="app in applications"
                      :key="app.id"
                      :value="String(app.id)"
                    >
                      {{ app.name }}
                    </UiSelectItem>
                  </UiSelectContent>
                </UiSelect>
              </div>

              <div class="space-y-2">
                <UiLabel for="version">
                  {{ t('admin.versions.createForm.versionNumber') }} <span class="text-destructive">*</span>
                </UiLabel>
                <UiInput
                  id="version"
                  v-model="formData.version"
                  :placeholder="t('admin.versions.createForm.versionPlaceholder')"
                  :disabled="saving"
                />
              </div>

              <div class="space-y-2">
                <UiLabel for="description">
                  {{ t('admin.versions.createForm.versionDesc') }}
                </UiLabel>
                <UiInput
                  id="description"
                  v-model="formData.description"
                  :placeholder="t('admin.versions.createForm.versionDescPlaceholder')"
                  :disabled="saving"
                />
              </div>

              <div class="space-y-2">
                <UiLabel>{{ t('admin.versions.createForm.updateFile') }}</UiLabel>
                <div class="border-2 border-dashed rounded-lg p-4">
                  <input
                    ref="fileInputRef"
                    type="file"
                    accept=".zip"
                    class="hidden"
                    @change="handleFileSelect"
                  >
                  <div v-if="!formData.file" class="text-center">
                    <UploadCloud class="size-10 mx-auto text-muted-foreground mb-2" />
                    <p class="text-sm text-muted-foreground mb-2">
                      {{ t('admin.versions.createForm.dragOrClick') }}
                    </p>
                    <UiButton variant="outline" size="sm" :disabled="saving || uploading" @click="fileInputRef?.click()">
                      <FilePlus class="h-4 w-4 mr-2" />
                      {{ t('admin.versions.createForm.selectFile') }}
                    </UiButton>
                  </div>
                  <div v-else class="space-y-3">
                    <div class="flex items-center justify-between">
                      <div class="flex items-center gap-3">
                        <FileArchive class="size-8 text-primary" />
                        <div>
                          <p class="text-sm font-medium">
                            {{ formData.file.name }}
                          </p>
                          <p class="text-xs text-muted-foreground">
                            {{ fileSize }}
                          </p>
                        </div>
                      </div>
                      <div class="flex items-center gap-2">
                        <UiButton
                          v-if="!uploadedData"
                          size="sm"
                          :disabled="uploading"
                          @click="uploadZipFile"
                        >
                          <Loader2 v-if="uploading" class="h-4 w-4 mr-2 animate-spin" />
                          <Upload v-else class="h-4 w-4 mr-2" />
                          {{ uploading ? `${uploadProgress}%` : t('admin.versions.createForm.uploadAndParse') }}
                        </UiButton>
                        <UiButton variant="ghost" size="icon" :disabled="saving" @click="removeFile">
                          <X class="size-4" />
                        </UiButton>
                      </div>
                    </div>
                    <!-- 上传进度条 -->
                    <div v-if="uploading" class="space-y-1">
                      <div class="w-full bg-muted rounded-full h-2 overflow-hidden">
                        <div
                          class="bg-primary h-full transition-all duration-300 ease-out"
                          :style="{ width: `${uploadProgress}%` }"
                        />
                      </div>
                      <div class="flex justify-between text-xs text-muted-foreground">
                        <span>{{ t('admin.versions.createForm.uploading') }}</span>
                        <span class="font-medium">{{ uploadSpeed }}</span>
                      </div>
                    </div>
                    <div v-if="uploadedData" class="rounded-lg bg-muted/50 p-3">
                      <div class="flex items-center gap-2 text-sm text-green-600 mb-2">
                        <CheckCircle class="size-4" />
                        <span>{{ t('admin.versions.createForm.fileUploaded') }}</span>
                      </div>
                      <div class="text-xs text-muted-foreground space-y-1">
                        <p>{{ t('admin.versions.createForm.fileHash') }}: {{ uploadedData.file_hash.substring(0, 16) }}...</p>
                        <p>{{ t('admin.versions.createForm.containsFiles', { count: uploadedData.files.length }) }}</p>
                      </div>
                    </div>
                  </div>
                </div>
              </div>

              <div v-if="uploadedData && uploadedData.files.length > 0" class="space-y-2">
                <UiLabel>{{ t('admin.versions.createForm.fileList') }}</UiLabel>
                <div class="border rounded-lg max-h-[300px] overflow-auto">
                  <table class="w-full text-sm">
                    <thead class="bg-muted/50 sticky top-0">
                      <tr>
                        <th class="text-left p-2 font-medium">
                          {{ t('admin.versions.createForm.fileName') }}
                        </th>
                        <th class="text-left p-2 font-medium">
                          {{ t('admin.versions.createForm.filePath') }}
                        </th>
                        <th class="text-right p-2 font-medium">
                          {{ t('admin.versions.createForm.fileSize') }}
                        </th>
                        <th class="text-left p-2 font-medium">
                          {{ t('admin.versions.createForm.fileType') }}
                        </th>
                      </tr>
                    </thead>
                    <tbody>
                      <tr
                        v-for="(file, index) in uploadedData.files"
                        :key="index"
                        class="border-t"
                      >
                        <td class="p-2 truncate max-w-[150px]">
                          {{ file.file_name }}
                        </td>
                        <td class="p-2 truncate max-w-[200px] text-muted-foreground">
                          {{ file.file_path }}
                        </td>
                        <td class="p-2 text-right text-muted-foreground">
                          {{ formatFileSize(file.file_size) }}
                        </td>
                        <td class="p-2">
                          <span class="px-2 py-0.5 rounded text-xs bg-muted">
                            {{ file.file_type }}
                          </span>
                        </td>
                      </tr>
                    </tbody>
                  </table>
                </div>
              </div>

              <div v-if="executableFiles.length > 0" class="space-y-2">
                <UiLabel>{{ t('admin.versions.createForm.entryFile') }}</UiLabel>
                <p class="text-sm text-muted-foreground">
                  {{ t('admin.versions.createForm.entryFileDesc') }}
                </p>
                <UiSelect v-model="formData.entry_file" :disabled="saving">
                  <UiSelectTrigger>
                    <UiSelectValue :placeholder="t('admin.versions.createForm.entryFilePlaceholder')" />
                  </UiSelectTrigger>
                  <UiSelectContent>
                    <UiSelectItem
                      v-for="file in executableFiles"
                      :key="file.file_path"
                      :value="file.file_path"
                    >
                      {{ file.file_name }} ({{ formatFileSize(file.file_size) }})
                    </UiSelectItem>
                  </UiSelectContent>
                </UiSelect>
              </div>

              <div class="flex items-center justify-between rounded-lg border p-4">
                <div class="space-y-0.5">
                  <UiLabel class="text-base">
                    {{ t('admin.versions.createForm.forcedUpdate') }}
                  </UiLabel>
                  <p class="text-sm text-muted-foreground">
                    {{ t('admin.versions.createForm.forcedUpdateDesc') }}
                  </p>
                </div>
                <UiSwitch
                  v-model="isForcedUpdate"
                  :disabled="saving"
                />
              </div>

              <div class="space-y-2">
                <UiLabel>{{ t('admin.versions.createForm.updateType') }}</UiLabel>
                <UiSelect v-model="formData.update_type" :disabled="saving">
                  <UiSelectTrigger>
                    <UiSelectValue />
                  </UiSelectTrigger>
                  <UiSelectContent>
                    <UiSelectItem value="full">
                      {{ t('admin.versions.types.full') }}
                    </UiSelectItem>
                    <UiSelectItem value="patch">
                      {{ t('admin.versions.types.patch') }}
                    </UiSelectItem>
                  </UiSelectContent>
                </UiSelect>
              </div>

              <!-- 基础版本选择（仅补丁类型） -->
              <div v-if="formData.update_type === 'patch'" class="space-y-2">
                <UiLabel>{{ t('admin.versions.createForm.baseVersion') }}</UiLabel>
                <p class="text-sm text-muted-foreground">
                  {{ t('admin.versions.createForm.baseVersionDesc') }}
                </p>
                <UiSelect v-model="formData.base_version_id" :disabled="saving || loadingBaseVersions">
                  <UiSelectTrigger>
                    <UiSelectValue :placeholder="t('admin.versions.createForm.baseVersionPlaceholder')" />
                  </UiSelectTrigger>
                  <UiSelectContent>
                    <UiSelectItem
                      v-for="v in baseVersions"
                      :key="v.id"
                      :value="String(v.id)"
                    >
                      {{ v.version }}
                    </UiSelectItem>
                  </UiSelectContent>
                </UiSelect>
                <p v-if="baseVersions.length === 0 && !loadingBaseVersions" class="text-sm text-destructive">
                  {{ t('admin.versions.createForm.noBaseVersion') }}
                </p>
              </div>

              <div class="space-y-2">
                <UiLabel>{{ t('admin.versions.createForm.updateMethod') }}</UiLabel>
                <UiSelect v-model="formData.update_method" :disabled="saving">
                  <UiSelectTrigger>
                    <UiSelectValue />
                  </UiSelectTrigger>
                  <UiSelectContent>
                    <UiSelectItem value="auto">
                      {{ t('admin.versions.methods.auto') }}
                    </UiSelectItem>
                    <UiSelectItem value="manual">
                      {{ t('admin.versions.methods.manual') }}
                    </UiSelectItem>
                  </UiSelectContent>
                </UiSelect>
              </div>

              <div v-if="formData.update_method === 'manual'" class="space-y-2">
                <UiLabel>{{ t('admin.versions.createForm.customDownloadUrl') }}</UiLabel>
                <p class="text-sm text-muted-foreground">
                  {{ t('admin.versions.createForm.customDownloadUrlDesc') }}
                </p>
                <UiInput
                  v-model="formData.custom_download_url"
                  :placeholder="t('admin.versions.createForm.customDownloadUrlPlaceholder')"
                  :disabled="saving"
                />
              </div>

              <div class="space-y-2">
                <UiLabel for="changelog">
                  {{ t('admin.versions.createForm.changelog') }}
                </UiLabel>
                <textarea
                  id="changelog"
                  v-model="formData.changelog"
                  class="flex min-h-[120px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
                  :placeholder="t('admin.versions.createForm.changelogPlaceholder')"
                  :disabled="saving"
                />
              </div>
            </UiCardContent>
          </UiCard>
        </div>

        <div class="space-y-6">
          <UiCard>
            <UiCardHeader>
              <UiCardTitle class="flex items-center gap-2">
                <Eye class="size-5" />
                {{ t('admin.versions.createForm.preview') }}
              </UiCardTitle>
            </UiCardHeader>
            <UiCardContent class="space-y-4">
              <div class="space-y-3">
                <div class="flex justify-between text-sm">
                  <span class="text-muted-foreground">{{ t('admin.versions.createForm.previewApp') }}</span>
                  <span>{{ selectedApplication?.name || '-' }}</span>
                </div>
                <div class="flex justify-between text-sm">
                  <span class="text-muted-foreground">{{ t('admin.versions.createForm.previewVersion') }}</span>
                  <span>{{ formData.version || '-' }}</span>
                </div>
                <div class="flex justify-between text-sm">
                  <span class="text-muted-foreground">{{ t('admin.versions.createForm.previewDesc') }}</span>
                  <span class="truncate max-w-[120px]">{{ formData.description || '-' }}</span>
                </div>
                <div class="flex justify-between text-sm">
                  <span class="text-muted-foreground">{{ t('admin.versions.createForm.previewFile') }}</span>
                  <span>{{ formData.file ? formData.file.name : t('admin.versions.createForm.notUploaded') }}</span>
                </div>
                <div class="flex justify-between text-sm">
                  <span class="text-muted-foreground">{{ t('admin.versions.createForm.previewFileCount') }}</span>
                  <span>{{ uploadedData ? uploadedData.files.length : '-' }}</span>
                </div>
                <div class="flex justify-between text-sm">
                  <span class="text-muted-foreground">{{ t('admin.versions.createForm.previewEntryFile') }}</span>
                  <span class="truncate max-w-[120px]">{{ formData.entry_file || '-' }}</span>
                </div>
                <div class="flex justify-between text-sm">
                  <span class="text-muted-foreground">{{ t('admin.versions.createForm.previewForcedUpdate') }}</span>
                  <span>{{ formData.update_strategy === 'forced' ? t('common.yes') : t('common.no') }}</span>
                </div>
                <div class="flex justify-between text-sm">
                  <span class="text-muted-foreground">{{ t('admin.versions.createForm.previewUpdateType') }}</span>
                  <span>{{ typeLabel }}</span>
                </div>
                <div class="flex justify-between text-sm">
                  <span class="text-muted-foreground">{{ t('admin.versions.createForm.previewUpdateMethod') }}</span>
                  <span>{{ methodLabel }}</span>
                </div>
                <div v-if="formData.update_method === 'manual'" class="flex justify-between text-sm">
                  <span class="text-muted-foreground">{{ t('admin.versions.createForm.previewCustomDownloadUrl') }}</span>
                  <span class="truncate max-w-[120px]">{{ formData.custom_download_url || t('admin.versions.createForm.useDefault') }}</span>
                </div>
              </div>

              <div class="border-t pt-4 mt-4">
                <p class="text-sm text-muted-foreground mb-2">
                  {{ t('admin.versions.createForm.changelogPreview') }}
                </p>
                <div class="rounded-lg bg-muted/50 p-3 min-h-[80px]">
                  <p class="text-sm whitespace-pre-wrap">
                    {{ formData.changelog || t('admin.versions.createForm.noChangelog') }}
                  </p>
                </div>
              </div>
            </UiCardContent>
          </UiCard>

          <UiCard>
            <UiCardContent class="pt-6">
              <div class="flex flex-col gap-3">
                <UiButton
                  class="w-full"
                  size="lg"
                  :disabled="saving || !formData.application_id || !formData.version || !uploadedData"
                  @click="handleSubmit"
                >
                  <Loader2 v-if="saving" class="mr-2 h-4 w-4 animate-spin" />
                  <Rocket v-else class="mr-2 h-4 w-4" />
                  {{ t('admin.versions.createForm.publishVersion') }}
                </UiButton>
                <UiButton
                  variant="outline"
                  class="w-full"
                  @click="router.back()"
                >
                  {{ t('common.cancel') }}
                </UiButton>
              </div>
            </UiCardContent>
          </UiCard>
        </div>
      </div>
    </div>
  </BasicPage>
</template>
