<script setup lang="ts">
import { useAppConfig } from '@vben/hooks';
import { useAccessStore } from '@vben/stores';
import { Page } from '@vben/common-ui';

import { Button, Card, Empty, Space, Tag, TypographyParagraph, message } from 'ant-design-vue';
import dayjs from 'dayjs';
import { onMounted, ref } from 'vue';

import { getApkPackagesApi } from '#/api/core/apk';
import type { ApkApi } from '#/api/core/apk';

const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD);
const accessStore = useAccessStore();

const loading = ref(false);
const downloadingKey = ref('');
const packages = ref<ApkApi.EnvironmentPackages[]>([]);
const packageTypes: ApkApi.PackageType[] = ['with_sdk', 'without_sdk'];

const envLabelMap: Record<ApkApi.Environment, string> = {
  dev: '开发环境',
  stable: '稳定环境',
  prod: '正式环境',
};

const envDescriptionMap: Record<ApkApi.Environment, string> = {
  dev: '用于日常开发和联调验证。',
  stable: '用于提测、回归和灰度验证。',
  prod: '用于正式对外发布。',
};

const packageTypeLabelMap: Record<ApkApi.PackageType, string> = {
  with_sdk: '包含 SDK',
  without_sdk: '不包含 SDK',
};

const packageTypeDescriptionMap: Record<ApkApi.PackageType, string> = {
  with_sdk: '适合渠道联调、SDK 验证和三方能力测试。',
  without_sdk: '适合纯净包验证、基础功能测试和问题排查。',
};

async function loadPackages() {
  loading.value = true;
  try {
    packages.value = await getApkPackagesApi();
  } catch {
    packages.value = [];
  } finally {
    loading.value = false;
  }
}

function formatSize(size: number) {
  if (!size) {
    return '-';
  }
  if (size < 1024 * 1024) {
    return `${(size / 1024).toFixed(2)} KB`;
  }
  return `${(size / 1024 / 1024).toFixed(2)} MB`;
}

function formatTime(value: string) {
  if (!value) {
    return '-';
  }
  return dayjs(value).format('YYYY-MM-DD HH:mm:ss');
}

function resolveDownloadUrl(item: ApkApi.PackageItem) {
  if (item.downloadPath) {
    return `${apiURL.replace(/\/$/, '')}${item.downloadPath}`;
  }
  return `${apiURL.replace(/\/$/, '')}/apk/download/${item.env}?packageType=${item.packageType}`;
}

function resolveDownloadName(item: ApkApi.PackageItem, disposition: null | string) {
  const fallbackName = item.fileName || `${item.env}.apk`;
  if (!disposition) {
    return fallbackName;
  }

  const utf8Match = disposition.match(/filename\*=UTF-8''([^;]+)/i);
  if (utf8Match?.[1]) {
    return decodeURIComponent(utf8Match[1]);
  }

  const basicMatch = disposition.match(/filename="?([^";]+)"?/i);
  if (basicMatch?.[1]) {
    return decodeURIComponent(basicMatch[1]);
  }

  return fallbackName;
}

async function downloadPackage(item: ApkApi.PackageItem) {
  if (!item.exists) {
    return;
  }

  if (!accessStore.accessToken) {
    message.error('登录状态已失效，请重新登录后再试。');
    return;
  }

  downloadingKey.value = `${item.env}:${item.packageType}`;
  try {
    const response = await fetch(resolveDownloadUrl(item), {
      headers: {
        Authorization: `Bearer ${accessStore.accessToken}`,
      },
    });

    if (!response.ok) {
      throw new Error('下载失败');
    }

    const blob = await response.blob();
    const downloadName = resolveDownloadName(
      item,
      response.headers.get('content-disposition'),
    );
    const downloadUrl = window.URL.createObjectURL(blob);
    const anchor = document.createElement('a');
    anchor.href = downloadUrl;
    anchor.download = downloadName;
    document.body.appendChild(anchor);
    anchor.click();
    anchor.remove();
    window.URL.revokeObjectURL(downloadUrl);
    message.success(`开始下载 ${downloadName}`);
  } catch (error) {
    console.error(error);
    message.error(`${envLabelMap[item.env]} ${packageTypeLabelMap[item.packageType]} APK 下载失败`);
  } finally {
    downloadingKey.value = '';
  }
}

function getVariantItem(
  envPackages: ApkApi.EnvironmentPackages,
  packageType: ApkApi.PackageType,
) {
  return envPackages.variants[packageType];
}

function getDownloadKey(env: ApkApi.Environment, packageType: ApkApi.PackageType) {
  return `${env}:${packageType}`;
}

onMounted(() => {
  loadPackages();
});
</script>

<template>
  <Page auto-content-height>
    <div class="space-y-4 p-4">
      <Card title="客户端下载说明">
        <TypographyParagraph>
          当前页面展示 dev、stable、prod 三套环境下的 SDK 包和非 SDK 包。
          Jenkins 通过后端上传接口更新包后，这里会自动展示最新版本并支持后台下载。
        </TypographyParagraph>
        <Button :loading="loading" type="primary" @click="loadPackages">刷新列表</Button>
      </Card>

      <div v-if="packages.length" class="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
        <Card v-for="envPackages in packages" :key="envPackages.env" :title="envLabelMap[envPackages.env]">
          <Space wrap>
            <Tag color="blue">{{ envPackages.env }}</Tag>
          </Space>

          <TypographyParagraph class="mt-4 text-gray-500">
            {{ envDescriptionMap[envPackages.env] }}
          </TypographyParagraph>

          <div class="mt-4 space-y-4">
            <div
              v-for="packageType in packageTypes"
              :key="getDownloadKey(envPackages.env, packageType)"
              class="rounded-lg border border-gray-200 p-4"
            >
              <div class="flex items-center justify-between gap-2">
                <div class="text-sm font-medium text-gray-900">
                  {{ packageTypeLabelMap[packageType] }}
                </div>
                <Tag :color="getVariantItem(envPackages, packageType)?.exists ? 'green' : 'default'">
                  {{ getVariantItem(envPackages, packageType)?.exists ? '已上传' : '暂无包' }}
                </Tag>
              </div>

              <TypographyParagraph class="mt-3 text-gray-500">
                {{ packageTypeDescriptionMap[packageType] }}
              </TypographyParagraph>

              <div class="space-y-2 text-sm leading-6">
                <div>文件名：{{ getVariantItem(envPackages, packageType)?.fileName || '-' }}</div>
                <div>版本号：{{ getVariantItem(envPackages, packageType)?.version || '-' }}</div>
                <div>文件大小：{{ formatSize(getVariantItem(envPackages, packageType)?.size || 0) }}</div>
                <div>上传时间：{{ formatTime(getVariantItem(envPackages, packageType)?.uploadedAt || '') }}</div>
              </div>

              <div class="mt-4">
                <Button
                  block
                  type="primary"
                  :disabled="!getVariantItem(envPackages, packageType)?.exists"
                  :loading="downloadingKey === getDownloadKey(envPackages.env, packageType)"
                  @click="downloadPackage(getVariantItem(envPackages, packageType) as ApkApi.PackageItem)"
                >
                  下载 APK
                </Button>
              </div>
            </div>
          </div>
        </Card>
      </div>

      <Card v-else>
        <Empty description="暂无可展示的 APK 包信息" />
      </Card>
    </div>
  </Page>
</template>