<script lang="ts" setup>
import { computed, reactive, ref, watch } from 'vue';

import { Page } from '@vben/common-ui';
import { useAccessStore } from '@vben/stores';

import {
  activateBaishunProviderProfile,
  fetchBaishunCatalog,
  getBaishunProviderConfig,
  importBaishunCatalog,
  pageBaishunCatalog,
  saveBaishunProviderConfig,
} from '#/api/legacy/baishun-game';
import { getAllowedSysOrigins } from '#/views/system/shared';

import {
  Button,
  Card,
  Form,
  FormItem,
  Image,
  Input,
  InputNumber,
  Pagination,
  Select,
  Table,
  Tag,
  message,
} from 'antdv-next';

defineOptions({ name: 'OperateBaishunConfig' });

function createProviderForm(sysOrigin = '') {
  return {
    sysOrigin,
    profile: 'PROD',
    platformBaseUrl: '',
    appId: undefined as any,
    appName: '',
    appChannel: '',
    appKey: '',
    gsp: 101 as any,
    launchCodeTtlSeconds: 300 as any,
    ssTokenTtlSeconds: 86400 as any,
  };
}

const accessStore = useAccessStore();
const sysOriginOptions = computed(() => {
  const options = getAllowedSysOrigins(accessStore.accessCodes || []);
  return options.length > 0 ? options : getAllowedSysOrigins([]);
});

const profileOptions = [
  { label: '正式环境', value: 'PROD' },
  { label: '测试环境', value: 'TEST' },
];

const contextQuery = reactive({ profile: 'PROD', sysOrigin: '' });
const providerForm = reactive(createProviderForm());
const catalogQuery = reactive<Record<string, any>>({
  cursor: 1,
  keyword: '',
  limit: 20,
});

const providerLoading = ref(false);
const providerSaving = ref(false);
const catalogLoading = ref(false);
const catalogFetching = ref(false);
const catalogImporting = ref(false);
const profileActivating = ref(false);
const totalCatalog = ref(0);
const catalogList = ref<Array<Record<string, any>>>([]);
const selectedCatalogKeys = ref<Array<number>>([]);
const activeProfile = ref('PROD');

const isCurrentProfileActive = computed(
  () => activeProfile.value === contextQuery.profile,
);
const activeProfileLabel = computed(
  () =>
    profileOptions.find((item) => item.value === activeProfile.value)?.label ||
    activeProfile.value,
);

const catalogColumns = [
  { dataIndex: 'cover', key: 'cover', title: '封面', width: 90 },
  { dataIndex: 'name', key: 'name', title: '名称', width: 180 },
  { dataIndex: 'gameId', key: 'gameId', title: '内部ID', width: 150 },
  { dataIndex: 'vendorGameId', key: 'vendorGameId', title: '百顺ID', width: 120 },
  { dataIndex: 'status', key: 'status', title: '目录状态', width: 110 },
  { dataIndex: 'packageVersion', key: 'packageVersion', title: '包版本', width: 110 },
  { dataIndex: 'gsp', key: 'gsp', title: 'GSP', width: 90 },
  { dataIndex: 'added', key: 'added', title: '统一游戏列表', width: 120 },
  { dataIndex: 'downloadUrl', key: 'downloadUrl', title: '入口地址', width: 360 },
  { dataIndex: 'updateTime', key: 'updateTime', title: '更新时间', width: 180 },
];

const catalogRowSelection = computed(() => ({
  selectedRowKeys: selectedCatalogKeys.value,
  onChange: (keys: Array<number | string>) => {
    selectedCatalogKeys.value = keys.map((item) => Number(item));
  },
  getCheckboxProps: (record: Record<string, any>) => ({
    disabled: Boolean(record.added),
  }),
}));

watch(
  sysOriginOptions,
  (options) => {
    if (!contextQuery.sysOrigin) {
      contextQuery.sysOrigin = String(options[0]?.value || '');
    }
  },
  { immediate: true },
);

watch(
  () => [contextQuery.sysOrigin, contextQuery.profile],
  ([sysOrigin, profile]) => {
    if (!sysOrigin || !profile) {
      return;
    }
    Object.assign(providerForm, createProviderForm(sysOrigin), {
      profile,
      sysOrigin,
    });
    selectedCatalogKeys.value = [];
    void Promise.all([loadProviderConfig(), loadCatalog(true)]);
  },
  { immediate: true },
);

function applyProviderForm(record: Record<string, any>) {
  activeProfile.value = String(record.activeProfile || activeProfile.value || 'PROD');
  Object.assign(providerForm, createProviderForm(contextQuery.sysOrigin), {
    ...record,
    profile: contextQuery.profile,
    sysOrigin: contextQuery.sysOrigin,
    appId: Number(record.appId || 0) || undefined,
    gsp: Number(record.gsp || 101) || 101,
    launchCodeTtlSeconds: Number(record.launchCodeTtlSeconds || 300) || 300,
    ssTokenTtlSeconds: Number(record.ssTokenTtlSeconds || 86400) || 86400,
  });
}

async function loadProviderConfig() {
  if (!contextQuery.sysOrigin) {
    return;
  }
  providerLoading.value = true;
  try {
    const result = await getBaishunProviderConfig({
      profile: contextQuery.profile,
      sysOrigin: contextQuery.sysOrigin,
    });
    applyProviderForm(result || {});
  } finally {
    providerLoading.value = false;
  }
}

async function persistProviderConfig(showSuccess = true) {
  if (
    !contextQuery.sysOrigin ||
    !providerForm.platformBaseUrl ||
    !providerForm.appId ||
    !providerForm.appChannel ||
    !providerForm.appKey
  ) {
    message.warning('请补全百顺平台地址、AppId、AppChannel、AppKey');
    return false;
  }
  providerSaving.value = true;
  try {
    const result = await saveBaishunProviderConfig({
      ...providerForm,
      profile: contextQuery.profile,
      sysOrigin: contextQuery.sysOrigin,
      appId: Number(providerForm.appId || 0),
      gsp: Number(providerForm.gsp || 101),
      launchCodeTtlSeconds: Number(providerForm.launchCodeTtlSeconds || 300),
      ssTokenTtlSeconds: Number(providerForm.ssTokenTtlSeconds || 86400),
    });
    applyProviderForm(result || providerForm);
    if (showSuccess) {
      message.success('百顺配置已保存');
    }
    return true;
  } catch {
    return false;
  } finally {
    providerSaving.value = false;
  }
}

async function loadCatalog(reset = false) {
  if (!contextQuery.sysOrigin) {
    return;
  }
  if (reset) {
    catalogQuery.cursor = 1;
  }
  catalogLoading.value = true;
  try {
    const result = await pageBaishunCatalog({
      ...catalogQuery,
      profile: contextQuery.profile,
      sysOrigin: contextQuery.sysOrigin,
    });
    catalogList.value = Array.isArray(result.records) ? result.records : [];
    totalCatalog.value = Number(result.total || 0);
  } finally {
    catalogLoading.value = false;
  }
}

function handleCatalogSearch() {
  void loadCatalog(true);
}

function handleCatalogPageChange(page: number, pageSize: number) {
  catalogQuery.cursor = page;
  catalogQuery.limit = pageSize;
  void loadCatalog();
}

async function handleSaveProviderConfig() {
  await persistProviderConfig(true);
}

async function handleActivateProfile() {
  if (!(await persistProviderConfig(false))) {
    return;
  }
  profileActivating.value = true;
  try {
    const result = await activateBaishunProviderProfile({
      profile: contextQuery.profile,
      sysOrigin: contextQuery.sysOrigin,
    });
    applyProviderForm(result || providerForm);
    message.success(`已切换到${activeProfileLabel.value}`);
    await loadCatalog(true);
  } finally {
    profileActivating.value = false;
  }
}

async function handleFetchCatalog() {
  if (!(await persistProviderConfig(false))) {
    return;
  }
  catalogFetching.value = true;
  try {
    const result = await fetchBaishunCatalog({
      profile: contextQuery.profile,
      sysOrigin: contextQuery.sysOrigin,
    });
    message.success(
      `获取完成：新增 ${Number(result.inserted || 0)}，更新 ${Number(result.updated || 0)}，跳过 ${Number(result.skipped || 0)}`,
    );
    await loadCatalog(true);
  } finally {
    catalogFetching.value = false;
  }
}

async function handleImportSelected() {
  if (!contextQuery.sysOrigin) {
    return;
  }
  if (selectedCatalogKeys.value.length === 0) {
    message.warning('请选择要添加到统一游戏列表的百顺游戏');
    return;
  }
  catalogImporting.value = true;
  try {
    const result = await importBaishunCatalog({
      profile: contextQuery.profile,
      sysOrigin: contextQuery.sysOrigin,
      vendorGameIds: selectedCatalogKeys.value,
    });
    selectedCatalogKeys.value = [];
    message.success(
      `添加完成：新增 ${Number(result.imported || 0)}，已存在 ${Number(result.existing || 0)}`,
    );
    await loadCatalog(true);
  } finally {
    catalogImporting.value = false;
  }
}
</script>

<template>
  <Page title="百顺配置">
    <Card :loading="providerLoading" title="百顺接入配置">
      <Form layout="vertical">
        <div class="form-grid provider-grid">
          <FormItem label="系统">
            <SysOriginSelect
              v-model:value="contextQuery.sysOrigin"
              :options="sysOriginOptions"
            />
          </FormItem>
          <FormItem label="配置环境" extra="app 侧只读取当前启用环境的配置和游戏列表。">
            <Select
              v-model:value="contextQuery.profile"
              :options="profileOptions"
              option-label-prop="label"
            />
          </FormItem>
          <FormItem
            label="平台地址"
            extra="填写百顺平台接口地址，例如 https://game-cn-test.jieyou.shop；不要填 Lucky Gift 域名。"
          >
            <Input
              v-model:value="providerForm.platformBaseUrl"
              placeholder="https://game-cn-test.jieyou.shop"
            />
          </FormItem>
          <FormItem label="AppId">
            <InputNumber
              v-model:value="providerForm.appId"
              :min="1"
              style="width: 100%"
            />
          </FormItem>
          <FormItem label="AppName">
            <Input v-model:value="providerForm.appName" placeholder="可选" />
          </FormItem>
          <FormItem label="AppChannel">
            <Input
              v-model:value="providerForm.appChannel"
              placeholder="yumiparty"
            />
          </FormItem>
          <FormItem label="AppKey">
            <Input
              v-model:value="providerForm.appKey"
              placeholder="请输入百顺密钥"
              type="password"
            />
          </FormItem>
          <FormItem label="默认 GSP">
            <InputNumber
              v-model:value="providerForm.gsp"
              :min="1"
              style="width: 100%"
            />
          </FormItem>
          <FormItem label="LaunchCode TTL(秒)">
            <InputNumber
              v-model:value="providerForm.launchCodeTtlSeconds"
              :min="1"
              style="width: 100%"
            />
          </FormItem>
          <FormItem label="SsToken TTL(秒)">
            <InputNumber
              v-model:value="providerForm.ssTokenTtlSeconds"
              :min="1"
              style="width: 100%"
            />
          </FormItem>
        </div>
        <div class="toolbar">
          <Button
            type="primary"
            :loading="providerSaving"
            @click="handleSaveProviderConfig"
          >
            保存配置
          </Button>
          <Button
            :disabled="isCurrentProfileActive"
            :loading="profileActivating"
            @click="handleActivateProfile"
          >
            启用此环境
          </Button>
          <Button :loading="catalogFetching" @click="handleFetchCatalog">
            获取百顺游戏列表
          </Button>
          <Tag :color="isCurrentProfileActive ? 'success' : 'warning'">
            当前启用：{{ activeProfileLabel }}
          </Tag>
          <span class="hint">
            正式和测试环境各自保存配置、目录和已添加游戏；切换启用环境后，Go app 游戏列表同步切换。
          </span>
        </div>
      </Form>
    </Card>

    <Card class="content-card" title="百顺目录">
      <div class="toolbar">
        <Input
          v-model:value="catalogQuery.keyword"
          placeholder="搜索目录名称 / 内部ID / 百顺ID"
          style="width: 260px"
          @pressEnter="handleCatalogSearch"
        />
        <Button :loading="catalogLoading" type="primary" @click="handleCatalogSearch">
          搜索
        </Button>
        <Button :loading="catalogFetching" @click="handleFetchCatalog">
          重新获取目录
        </Button>
        <Button
          type="primary"
          :loading="catalogImporting"
          @click="handleImportSelected"
        >
          添加已选游戏
        </Button>
      </div>

      <Table
        :columns="catalogColumns"
        :data-source="catalogList"
        :loading="catalogLoading"
        :pagination="false"
        row-key="vendorGameId"
        :row-selection="catalogRowSelection"
        :scroll="{ x: 1700 }"
      >
        <template #bodyCell="{ column, record }">
          <template v-if="column.key === 'cover'">
            <Image v-if="record.cover" :src="record.cover" class="cover" />
            <span v-else>-</span>
          </template>
          <template v-else-if="column.key === 'status'">
            <Tag :color="record.status === 'ENABLED' ? 'success' : 'default'">
              {{ record.status || '-' }}
            </Tag>
          </template>
          <template v-else-if="column.key === 'added'">
            <Tag :color="record.added ? 'success' : 'default'">
              {{ record.added ? '已进入统一游戏列表' : '未添加' }}
            </Tag>
          </template>
          <template v-else-if="column.key === 'downloadUrl'">
            <a
              v-if="record.downloadUrl"
              :href="record.downloadUrl"
              class="link-cell"
              rel="noreferrer"
              target="_blank"
            >
              {{ record.downloadUrl }}
            </a>
            <span v-else>-</span>
          </template>
        </template>
      </Table>

      <div v-if="totalCatalog > 0" class="pager">
        <Pagination
          :current="catalogQuery.cursor"
          :page-size="catalogQuery.limit"
          :total="totalCatalog"
          show-size-changer
          @change="handleCatalogPageChange"
          @showSizeChange="handleCatalogPageChange"
        />
      </div>
    </Card>
  </Page>
</template>

<style scoped>
.content-card {
  margin-top: 16px;
}

.toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 16px;
}

.pager {
  display: flex;
  justify-content: flex-end;
  margin-top: 16px;
}

.cover {
  width: 50px;
  height: 50px;
  object-fit: cover;
  border-radius: 6px;
}

.form-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 16px;
}

.provider-grid {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.hint {
  color: rgb(100 116 139);
  line-height: 32px;
}

.link-cell {
  display: inline-block;
  max-width: 340px;
  overflow: hidden;
  color: rgb(37 99 235);
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (max-width: 1200px) {
  .provider-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 900px) {
  .form-grid,
  .provider-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}
</style>
