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

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

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 applications = ref<Application[]>([])

const formData = ref({
  application_id: '',
  version: '',
  description: '',
  update_strategy: 'optional' as 'optional' | 'forced',
  update_method: 'manual' as 'manual' | 'auto',
  min_version: '',
  changelog: '',
  entry_file: '',
  file: null as File | null,
})

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
})

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`
}

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
  }
}

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('只支持ZIP格式文件')
      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('请先选择ZIP文件')
    return
  }

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

    const response = await api.postFormData<UploadResponse>('/dev/versions/upload-zip', formDataObj)
    uploadedData.value = response
    toast.success('文件上传成功')
  }
  catch (error: any) {
    console.error('上传文件失败:', error)
    toast.error(error.message || '上传失败')
  }
  finally {
    uploading.value = false
  }
}

async function handleSubmit() {
  if (!formData.value.application_id) {
    toast.error('请选择应用')
    return
  }
  if (!formData.value.version) {
    toast.error('请输入版本号')
    return
  }
  if (!uploadedData.value) {
    toast.error('请先上传ZIP文件')
    return
  }

  saving.value = true
  try {
    await api.post('/dev/versions', {
      application_id: Number(formData.value.application_id),
      version: formData.value.version,
      description: formData.value.description,
      update_strategy: formData.value.update_strategy,
      update_method: formData.value.update_method,
      min_version: formData.value.min_version,
      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,
    })
    toast.success('版本创建成功')
    router.push('/admin/versions')
  }
  catch (error: any) {
    console.error('创建版本失败:', error)
    toast.error(error.message || '创建失败')
  }
  finally {
    saving.value = false
  }
}

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

<template>
  <BasicPage
    title="创建版本"
    description="为应用创建新的版本，上传ZIP更新包并配置更新策略"
    :breadcrumbs="[
      { title: '版本管理', href: '/admin/versions' },
      { 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" />
                版本配置
              </UiCardTitle>
              <UiCardDescription>填写版本的基本信息和上传更新文件</UiCardDescription>
            </UiCardHeader>
            <UiCardContent class="space-y-6">
              <div class="space-y-2">
                <UiLabel>选择应用 <span class="text-destructive">*</span></UiLabel>
                <UiSelect v-model="formData.application_id" :disabled="saving || loading">
                  <UiSelectTrigger>
                    <UiSelectValue placeholder="选择应用" />
                  </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">
                  版本号 <span class="text-destructive">*</span>
                </UiLabel>
                <UiInput
                  id="version"
                  v-model="formData.version"
                  placeholder="例如: 1.0.0"
                  :disabled="saving"
                />
              </div>

              <div class="space-y-2">
                <UiLabel for="min_version">
                  最低版本
                </UiLabel>
                <UiInput
                  id="min_version"
                  v-model="formData.min_version"
                  placeholder="例如: 0.9.0 (低于此版本需要完整安装)"
                  :disabled="saving"
                />
              </div>

              <div class="space-y-2">
                <UiLabel for="description">
                  版本描述
                </UiLabel>
                <UiInput
                  id="description"
                  v-model="formData.description"
                  placeholder="简短描述此版本的更新内容"
                  :disabled="saving"
                />
              </div>

              <div class="space-y-2">
                <UiLabel>更新文件 (ZIP格式)</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">
                      拖拽ZIP文件到此处或点击上传
                    </p>
                    <UiButton variant="outline" size="sm" :disabled="saving || uploading" @click="fileInputRef?.click()">
                      <FilePlus class="h-4 w-4 mr-2" />
                      选择文件
                    </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" />
                          上传解析
                        </UiButton>
                        <UiButton variant="ghost" size="icon" :disabled="saving" @click="removeFile">
                          <X class="size-4" />
                        </UiButton>
                      </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>文件已上传并解析</span>
                      </div>
                      <div class="text-xs text-muted-foreground space-y-1">
                        <p>文件哈希: {{ uploadedData.file_hash.substring(0, 16) }}...</p>
                        <p>包含 {{ uploadedData.files.length }} 个文件</p>
                      </div>
                    </div>
                  </div>
                </div>
              </div>

              <div v-if="uploadedData && uploadedData.files.length > 0" class="space-y-2">
                <UiLabel>文件列表</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">
                          文件名
                        </th>
                        <th class="text-left p-2 font-medium">
                          路径
                        </th>
                        <th class="text-right p-2 font-medium">
                          大小
                        </th>
                        <th class="text-left p-2 font-medium">
                          类型
                        </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>入口文件</UiLabel>
                <p class="text-sm text-muted-foreground">
                  选择更新完成后要启动的主程序文件（可选）
                </p>
                <UiSelect v-model="formData.entry_file" :disabled="saving">
                  <UiSelectTrigger>
                    <UiSelectValue placeholder="选择入口文件（可选）" />
                  </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">
                    强制更新
                  </UiLabel>
                  <p class="text-sm text-muted-foreground">
                    启用后用户必须更新到此版本才能继续使用
                  </p>
                </div>
                <UiSwitch
                  :checked="formData.update_strategy === 'forced'"
                  :disabled="saving"
                  @update:checked="formData.update_strategy = $event ? 'forced' : 'optional'"
                />
              </div>

              <div class="flex items-center justify-between rounded-lg border p-4">
                <div class="space-y-0.5">
                  <UiLabel class="text-base">
                    自动更新
                  </UiLabel>
                  <p class="text-sm text-muted-foreground">
                    启用后应用将自动下载并安装更新
                  </p>
                </div>
                <UiSwitch
                  :checked="formData.update_method === 'auto'"
                  :disabled="saving"
                  @update:checked="formData.update_method = $event ? 'auto' : 'manual'"
                />
              </div>

              <div class="space-y-2">
                <UiLabel for="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="详细描述此版本的更新内容、修复的问题、新增的功能等..."
                  :disabled="saving"
                />
              </div>
            </UiCardContent>
          </UiCard>
        </div>

        <div class="space-y-6">
          <UiCard>
            <UiCardHeader>
              <UiCardTitle class="flex items-center gap-2">
                <Eye class="size-5" />
                预览
              </UiCardTitle>
            </UiCardHeader>
            <UiCardContent class="space-y-4">
              <div class="space-y-3">
                <div class="flex justify-between text-sm">
                  <span class="text-muted-foreground">所属应用</span>
                  <span>{{ selectedApplication?.name || '-' }}</span>
                </div>
                <div class="flex justify-between text-sm">
                  <span class="text-muted-foreground">版本号</span>
                  <span>{{ formData.version || '-' }}</span>
                </div>
                <div class="flex justify-between text-sm">
                  <span class="text-muted-foreground">最低版本</span>
                  <span>{{ formData.min_version || '-' }}</span>
                </div>
                <div class="flex justify-between text-sm">
                  <span class="text-muted-foreground">版本描述</span>
                  <span class="truncate max-w-[120px]">{{ formData.description || '-' }}</span>
                </div>
                <div class="flex justify-between text-sm">
                  <span class="text-muted-foreground">更新文件</span>
                  <span>{{ formData.file ? formData.file.name : '未上传' }}</span>
                </div>
                <div class="flex justify-between text-sm">
                  <span class="text-muted-foreground">文件数量</span>
                  <span>{{ uploadedData ? uploadedData.files.length : '-' }}</span>
                </div>
                <div class="flex justify-between text-sm">
                  <span class="text-muted-foreground">入口文件</span>
                  <span class="truncate max-w-[120px]">{{ formData.entry_file || '-' }}</span>
                </div>
                <div class="flex justify-between text-sm">
                  <span class="text-muted-foreground">强制更新</span>
                  <span>{{ formData.update_strategy === 'forced' ? '是' : '否' }}</span>
                </div>
                <div class="flex justify-between text-sm">
                  <span class="text-muted-foreground">自动更新</span>
                  <span>{{ formData.update_method === 'auto' ? '是' : '否' }}</span>
                </div>
              </div>

              <div class="border-t pt-4 mt-4">
                <p class="text-sm text-muted-foreground mb-2">
                  更新日志预览
                </p>
                <div class="rounded-lg bg-muted/50 p-3 min-h-[80px]">
                  <p class="text-sm whitespace-pre-wrap">
                    {{ formData.changelog || '暂无更新日志' }}
                  </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" />
                  发布版本
                </UiButton>
                <UiButton
                  variant="outline"
                  class="w-full"
                  @click="router.back()"
                >
                  取消
                </UiButton>
              </div>
            </UiCardContent>
          </UiCard>
        </div>
      </div>
    </div>
  </BasicPage>
</template>
