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

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

import { listGiftBySysOrigin } from '#/api/legacy/gift';
import {
  getSpecifiedGiftWeeklyRankCurrentRank,
  getSpecifiedGiftWeeklyRankConfig,
  pageSpecifiedGiftWeeklyRankConfigs,
  pageSpecifiedGiftWeeklyRankRewardRecords,
  pageSpecifiedGiftWeeklyRankSnapshots,
  retrySpecifiedGiftWeeklyRankRewardRecord,
  saveSpecifiedGiftWeeklyRankConfig,
} from '#/api/legacy/resident-activity';
import ActivityResourceGroupSelectDrawer from '#/views/props/components/activity-resource-group-select-drawer.vue';
import { getAllowedSysOrigins } from '#/views/system/shared';

import {
  Button,
  Card,
  DatePicker,
  Image,
  Input,
  Modal,
  Pagination,
  Select,
  Space,
  Spin,
  Switch,
  Table,
  Tag,
  message,
} from 'antdv-next';

defineOptions({ name: 'ResidentSpecifiedGiftWeeklyRankPage' });

function createGiftSlot(sort: number) {
  return {
    giftCandy: 0,
    giftId: undefined,
    giftName: '',
    giftPhoto: '',
    sort,
  };
}

function createRewardSlot(rank: number) {
  return {
    items: [] as Array<Record<string, any>>,
    rank,
    rewardGroupId: null,
    rewardGroupName: '',
  };
}

function createEmptyForm(sysOrigin = '') {
  return {
    configured: false,
    editable: true,
    enabled: true,
    endAt: '',
    giftConfigs: [createGiftSlot(1), createGiftSlot(2), createGiftSlot(3)],
    id: 0,
    rewardConfigs: [createRewardSlot(1), createRewardSlot(2), createRewardSlot(3)],
    startAt: '',
    status: 'NOT_STARTED',
    sysOrigin,
    timezone: 'Asia/Riyadh',
    updateTime: '',
  };
}

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

const selectedSysOrigin = ref('');

const configLoading = ref(false);
const configTotal = ref(0);
const configList = ref<Array<Record<string, any>>>([]);

const editorOpen = ref(false);
const editorLoading = ref(false);
const saving = ref(false);
const editorGiftLoading = ref(false);
const editorReadonly = ref(false);
const editorTitle = ref('新建周配置');
const groupPickerOpen = ref(false);
const rangeDate = ref<[string, string] | null>(null);

const giftOptions = ref<Array<Record<string, any>>>([]);
const pickerTarget = reactive({ rank: 1 });

const snapshotLoading = ref(false);
const snapshotTotal = ref(0);
const snapshotList = ref<Array<Record<string, any>>>([]);

const rewardLoading = ref(false);
const rewardTotal = ref(0);
const rewardList = ref<Array<Record<string, any>>>([]);

const rankLoading = ref(false);
const rankList = ref<Array<Record<string, any>>>([]);
const rankMeta = reactive<{
  activityStatus: string;
  configId: string;
  cycleKey: string;
  giftConfigs: Array<Record<string, any>>;
  periodEndAt: string;
  periodStartAt: string;
  timezone: string;
}>({
  activityStatus: '',
  configId: '',
  cycleKey: '',
  giftConfigs: [],
  periodEndAt: '',
  periodStartAt: '',
  timezone: 'Asia/Riyadh',
});

const form = reactive<Record<string, any>>(createEmptyForm());

const configQuery = reactive({
  cursor: 1,
  limit: 10,
});

const snapshotQuery = reactive({
  configId: undefined as number | string | undefined,
  cursor: 1,
  cycleKey: '',
  limit: 10,
});

const rewardQuery = reactive({
  configId: undefined as number | string | undefined,
  cursor: 1,
  cycleKey: '',
  limit: 10,
  status: '',
});

const rankQuery = reactive({
  limit: 20,
});

const rewardStatusOptions = [
  { label: '成功', value: 'SUCCESS' },
  { label: '失败', value: 'FAILED' },
  { label: '待发放', value: 'PENDING' },
];

const configStatusTextMap: Record<string, string> = {
  DISABLED: '已关闭',
  ENDED: '已结束',
  NOT_STARTED: '未开始',
  ONGOING: '进行中',
};

const configColumns = [
  { dataIndex: 'period', key: 'period', title: '活动周期', width: 320 },
  { dataIndex: 'status', key: 'status', title: '状态', width: 120 },
  { dataIndex: 'gifts', key: 'gifts', title: '指定礼物', width: 280 },
  { dataIndex: 'rewards', key: 'rewards', title: '奖励组', width: 280 },
  { dataIndex: 'updateTime', key: 'updateTime', title: '更新时间', width: 180 },
  { dataIndex: 'actions', key: 'actions', title: '操作', width: 160 },
];

const snapshotColumns = [
  { dataIndex: 'cycleKey', key: 'cycleKey', title: '周期', width: 140 },
  { dataIndex: 'rank', key: 'rank', title: '名次', width: 90 },
  { dataIndex: 'user', key: 'user', title: '用户', width: 280 },
  { dataIndex: 'scoreGold', key: 'scoreGold', title: '金币积分', width: 140 },
  { dataIndex: 'period', key: 'period', title: '结算区间', width: 320 },
];

const rankColumns = [
  { dataIndex: 'rank', key: 'rank', title: '名次', width: 90 },
  { dataIndex: 'user', key: 'user', title: '用户', width: 280 },
  { dataIndex: 'countryName', key: 'countryName', title: '国家', width: 150 },
  { dataIndex: 'scoreGold', key: 'scoreGold', title: '当前金币积分', width: 160 },
];

const rewardColumns = [
  { dataIndex: 'cycleKey', key: 'cycleKey', title: '周期', width: 140 },
  { dataIndex: 'rank', key: 'rank', title: '名次', width: 90 },
  { dataIndex: 'user', key: 'user', title: '用户', width: 280 },
  { dataIndex: 'rewardGroupName', key: 'rewardGroupName', title: '奖励组', width: 220 },
  { dataIndex: 'scoreGold', key: 'scoreGold', title: '金币积分', width: 140 },
  { dataIndex: 'status', key: 'status', title: '状态', width: 120 },
  { dataIndex: 'retryCount', key: 'retryCount', title: '补发次数', width: 110 },
  { dataIndex: 'sentAt', key: 'sentAt', title: '发奖时间', width: 180 },
  { dataIndex: 'lastError', key: 'lastError', title: '失败原因', width: 260 },
  { dataIndex: 'actions', key: 'actions', title: '操作', width: 120 },
];

const configFilterOptions = computed(() =>
  configList.value.map((item) => ({
    label: `${item.startAt || '-'} ~ ${item.endAt || '-'}`,
    value: item.id,
  })),
);

const editorStatusText = computed(() => configStatusTextMap[String(form.status || '')] || '未配置');

function statusColor(status: string) {
  switch (status) {
    case 'ONGOING':
      return 'success';
    case 'NOT_STARTED':
      return 'processing';
    case 'ENDED':
      return 'default';
    case 'FAILED':
      return 'error';
    case 'SUCCESS':
      return 'success';
    case 'PENDING':
      return 'processing';
    default:
      return 'warning';
  }
}

function avatarBackgroundStyle(url?: string) {
  const avatarUrl = String(url || '').trim();
  return avatarUrl ? { backgroundImage: `url(${JSON.stringify(avatarUrl)})` } : {};
}

function assignForm(next: Record<string, any>) {
  Object.assign(form, createEmptyForm(selectedSysOrigin.value), next);
}

function normalizeConfig(result: Record<string, any> | null | undefined) {
  const value = result ?? {};
  assignForm({
    configured: Boolean(value.configured),
    editable: value.editable !== false,
    enabled: Boolean(value.enabled),
    endAt: String(value.endAt || ''),
    id: Number(value.id || 0),
    startAt: String(value.startAt || ''),
    status: String(value.status || 'NOT_STARTED'),
    sysOrigin: String(value.sysOrigin || selectedSysOrigin.value || ''),
    timezone: String(value.timezone || 'Asia/Riyadh'),
    updateTime: String(value.updateTime || ''),
  });
  rangeDate.value = form.startAt && form.endAt ? [form.startAt, form.endAt] : null;

  const giftRows = Array.isArray(value.giftConfigs) ? [...value.giftConfigs] : [];
  giftRows.sort((left, right) => Number(left.sort || 0) - Number(right.sort || 0));
  form.giftConfigs = [1, 2, 3].map((sort) => {
    const row = giftRows.find((item) => Number(item.sort || 0) === sort) || {};
    return {
      giftCandy: Number(row.giftCandy || 0),
      giftId: row.giftId ?? undefined,
      giftName: String(row.giftName || ''),
      giftPhoto: String(row.giftPhoto || ''),
      sort,
    };
  });

  const rewardRows = Array.isArray(value.rewardConfigs) ? [...value.rewardConfigs] : [];
  rewardRows.sort((left, right) => Number(left.rank || 0) - Number(right.rank || 0));
  form.rewardConfigs = [1, 2, 3].map((rank) => {
    const row = rewardRows.find((item) => Number(item.rank || 0) === rank) || {};
    return {
      items: Array.isArray(row.items) ? row.items : [],
      rank,
      rewardGroupId: row.rewardGroupId ?? null,
      rewardGroupName: String(row.rewardGroupName || ''),
    };
  });
}

function resetEditorForCreate() {
  assignForm(createEmptyForm(selectedSysOrigin.value));
  rangeDate.value = null;
  editorReadonly.value = false;
  editorTitle.value = '新建周配置';
}

async function loadGiftOptions(sysOrigin: string) {
  if (!sysOrigin) {
    giftOptions.value = [];
    return;
  }
  editorGiftLoading.value = true;
  try {
    giftOptions.value = (await listGiftBySysOrigin(sysOrigin)) || [];
  } finally {
    editorGiftLoading.value = false;
  }
}

async function loadConfigList(reset = false) {
  if (!selectedSysOrigin.value) {
    configList.value = [];
    configTotal.value = 0;
    return;
  }
  if (reset) {
    configQuery.cursor = 1;
  }
  configLoading.value = true;
  try {
    const result = await pageSpecifiedGiftWeeklyRankConfigs({
      ...configQuery,
      sysOrigin: selectedSysOrigin.value,
    });
    configList.value = Array.isArray(result.records) ? result.records : [];
    configTotal.value = Number(result.total || 0);
  } finally {
    configLoading.value = false;
  }
}

async function loadConfigDetail(id: number | string) {
  if (!id) {
    return;
  }
  editorLoading.value = true;
  try {
    const result = await getSpecifiedGiftWeeklyRankConfig({
      id,
      sysOrigin: selectedSysOrigin.value,
    });
    normalizeConfig(result);
    await loadGiftOptions(form.sysOrigin);
  } finally {
    editorLoading.value = false;
  }
}

async function loadCurrentRank() {
  if (!selectedSysOrigin.value) {
    rankList.value = [];
    Object.assign(rankMeta, {
      activityStatus: '',
      configId: '',
      cycleKey: '',
      giftConfigs: [],
      periodEndAt: '',
      periodStartAt: '',
      timezone: 'Asia/Riyadh',
    });
    return;
  }
  rankLoading.value = true;
  try {
    const result = await getSpecifiedGiftWeeklyRankCurrentRank({
      limit: rankQuery.limit,
      sysOrigin: selectedSysOrigin.value,
    });
    rankList.value = Array.isArray(result.records) ? result.records : [];
    rankMeta.activityStatus = String(result.activityStatus || '');
    rankMeta.configId = String(result.configId || '');
    rankMeta.cycleKey = String(result.cycleKey || '');
    rankMeta.giftConfigs = Array.isArray(result.giftConfigs) ? result.giftConfigs : [];
    rankMeta.periodEndAt = String(result.periodEndAt || '');
    rankMeta.periodStartAt = String(result.periodStartAt || '');
    rankMeta.timezone = String(result.timezone || 'Asia/Riyadh');
  } finally {
    rankLoading.value = false;
  }
}

async function loadSnapshots(reset = false) {
  if (!selectedSysOrigin.value) {
    snapshotList.value = [];
    snapshotTotal.value = 0;
    return;
  }
  if (reset) {
    snapshotQuery.cursor = 1;
  }
  snapshotLoading.value = true;
  try {
    const result = await pageSpecifiedGiftWeeklyRankSnapshots({
      ...snapshotQuery,
      sysOrigin: selectedSysOrigin.value,
    });
    snapshotList.value = Array.isArray(result.records) ? result.records : [];
    snapshotTotal.value = Number(result.total || 0);
  } finally {
    snapshotLoading.value = false;
  }
}

async function loadRewardRecords(reset = false) {
  if (!selectedSysOrigin.value) {
    rewardList.value = [];
    rewardTotal.value = 0;
    return;
  }
  if (reset) {
    rewardQuery.cursor = 1;
  }
  rewardLoading.value = true;
  try {
    const result = await pageSpecifiedGiftWeeklyRankRewardRecords({
      ...rewardQuery,
      sysOrigin: selectedSysOrigin.value,
    });
    rewardList.value = Array.isArray(result.records) ? result.records : [];
    rewardTotal.value = Number(result.total || 0);
  } finally {
    rewardLoading.value = false;
  }
}

async function reloadPageData() {
  await Promise.all([
    loadConfigList(true),
    loadCurrentRank(),
    loadSnapshots(true),
    loadRewardRecords(true),
  ]);
}

function syncGiftSelection(slot: Record<string, any>, giftId: number | string | undefined) {
  const row = giftOptions.value.find((item) => String(item.id) === String(giftId || ''));
  slot.giftId = giftId || undefined;
  slot.giftName = String(row?.giftName || '');
  slot.giftPhoto = String(row?.giftPhoto || '');
  slot.giftCandy = Number(row?.giftCandy || 0);
}

function getGiftSelectOptions(currentValue: number | string | undefined) {
  return giftOptions.value.map((item) => {
    const selectedCount = form.giftConfigs.filter(
      (slot: Record<string, any>) => String(slot.giftId || '') === String(item.id || ''),
    ).length;
    const sameCurrent = String(currentValue || '') === String(item.id || '');
    return {
      disabled: selectedCount > 0 && !sameCurrent,
      label: `${item.giftName || item.id} (${item.giftCandy || 0})`,
      value: item.id as any,
    };
  });
}

function handleGiftChange(slot: Record<string, any>, value: any) {
  const nextValue = Array.isArray(value) ? value[0] : value;
  syncGiftSelection(slot, nextValue);
}

function handleEditorSysOriginChange(value: any) {
  if (form.id) {
    return;
  }
  form.sysOrigin = String(value || '');
  form.giftConfigs = [createGiftSlot(1), createGiftSlot(2), createGiftSlot(3)];
  void loadGiftOptions(form.sysOrigin);
}

function openRewardPicker(rank: number) {
  if (editorReadonly.value) {
    return;
  }
  pickerTarget.rank = rank;
  groupPickerOpen.value = true;
}

function clearRewardGroup(rank: number) {
  if (editorReadonly.value) {
    return;
  }
  const target = form.rewardConfigs.find((item: Record<string, any>) => Number(item.rank) === rank);
  if (!target) {
    return;
  }
  target.rewardGroupId = null;
  target.rewardGroupName = '';
  target.items = [];
}

function handleRewardGroupSelect(row: Record<string, any>) {
  const target = form.rewardConfigs.find(
    (item: Record<string, any>) => Number(item.rank) === Number(pickerTarget.rank),
  );
  if (!target) {
    groupPickerOpen.value = false;
    return;
  }
  target.rewardGroupId = row.id;
  target.rewardGroupName = row.name;
  target.items = (row.rewardConfigList || []).map((item: Record<string, any>) => ({
    content: item.content || '',
    cover: item.cover || '',
    id: item.id,
    name: item.name || item.badgeName || item.content || item.type || '',
    quantity: Number(item.quantity || 0),
    remark: item.remark || '',
    type: item.type || '',
  }));
  groupPickerOpen.value = false;
}

function validateBeforeSave() {
  if (!form.startAt || !form.endAt) {
    message.warning('请选择活动开始和结束时间');
    return false;
  }
  const selectedGiftIds = form.giftConfigs
    .map((item: Record<string, any>) => item.giftId)
    .filter(Boolean);
  if (selectedGiftIds.length !== 3 || new Set(selectedGiftIds.map(String)).size !== 3) {
    message.warning('请完整且不重复地选择 3 个礼物');
    return false;
  }
  const selectedRewardIds = form.rewardConfigs
    .map((item: Record<string, any>) => item.rewardGroupId)
    .filter(Boolean);
  if (selectedRewardIds.length !== 3) {
    message.warning('请为 Top1、Top2、Top3 都选择奖励组');
    return false;
  }
  return true;
}

async function submitForm() {
  if (editorReadonly.value || !validateBeforeSave()) {
    return;
  }
  saving.value = true;
  try {
    await saveSpecifiedGiftWeeklyRankConfig({
      enabled: Boolean(form.enabled),
      endAt: form.endAt,
      giftConfigs: (form.giftConfigs || []).map((item: Record<string, any>) => ({
        giftCandy: Number(item.giftCandy || 0),
        giftId: item.giftId || 0,
        giftName: String(item.giftName || ''),
        giftPhoto: String(item.giftPhoto || ''),
        sort: Number(item.sort || 0),
      })),
      id: form.id || 0,
      rewardConfigs: (form.rewardConfigs || []).map((item: Record<string, any>) => ({
        rank: Number(item.rank || 0),
        rewardGroupId: item.rewardGroupId || 0,
        rewardGroupName: String(item.rewardGroupName || ''),
      })),
      startAt: form.startAt,
      sysOrigin: String(form.sysOrigin || '').trim(),
      timezone: String(form.timezone || '').trim(),
    });
    message.success('保存成功');
    editorOpen.value = false;
    await reloadPageData();
  } finally {
    saving.value = false;
  }
}

function openCreateModal() {
  resetEditorForCreate();
  editorOpen.value = true;
  void loadGiftOptions(form.sysOrigin);
}

async function openConfigModal(record: Record<string, any>, readOnly = !record.editable) {
  editorTitle.value = readOnly ? '查看周配置' : '编辑周配置';
  editorReadonly.value = readOnly;
  editorOpen.value = true;
  await loadConfigDetail(record.id || 0);
}

function handleConfigPageChange(page: number, pageSize: number) {
  configQuery.cursor = page;
  configQuery.limit = pageSize;
  void loadConfigList();
}

function handleSnapshotPageChange(page: number, pageSize: number) {
  snapshotQuery.cursor = page;
  snapshotQuery.limit = pageSize;
  void loadSnapshots();
}

function handleRewardPageChange(page: number, pageSize: number) {
  rewardQuery.cursor = page;
  rewardQuery.limit = pageSize;
  void loadRewardRecords();
}

async function handleRetry(record: Record<string, any>) {
  Modal.confirm({
    async onOk() {
      await retrySpecifiedGiftWeeklyRankRewardRecord(record.id);
      message.success('补发任务已执行');
      await loadRewardRecords(false);
    },
    title: `确认补发 ${record.userNickname || record.userId} 的奖励？`,
  });
}

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

watch(
  selectedSysOrigin,
  (value) => {
    if (!value) {
      return;
    }
    resetEditorForCreate();
    void reloadPageData();
  },
  { immediate: true },
);

watch(
  rangeDate,
  (value) => {
    form.startAt = String(value?.[0] || '');
    form.endAt = String(value?.[1] || '');
  },
  { deep: true },
);

watch(
  configList,
  (list) => {
    const configIds = new Set(list.map((item) => String(item.id || '')));
    if (snapshotQuery.configId && !configIds.has(String(snapshotQuery.configId))) {
      snapshotQuery.configId = undefined;
    }
    if (rewardQuery.configId && !configIds.has(String(rewardQuery.configId))) {
      rewardQuery.configId = undefined;
    }
  },
  { deep: true },
);
</script>

<template>
  <Page auto-content-height>
    <Card :bordered="false" title="活动配置">
      <Space class="toolbar" wrap>
        <Select
          v-model:value="selectedSysOrigin"
          :options="sysOriginOptions"
          option-filter-prop="label"
          option-label-prop="label"
          placeholder="请选择系统"
          show-search
          style="width: 180px"
        />
        <Tag color="processing">当前周无配置可补建，已开始配置只读</Tag>
        <Button type="primary" @click="openCreateModal">新建周配置</Button>
      </Space>

      <Table
        :columns="configColumns"
        :data-source="configList"
        :loading="configLoading"
        :pagination="false"
        row-key="id"
        :scroll="{ x: 1280 }"
      >
        <template #bodyCell="{ column, record }">
          <template v-if="column.key === 'period'">
            <div class="period-cell">
              <div>{{ record.startAt || '-' }} ~ {{ record.endAt || '-' }}</div>
              <div class="sub-text">{{ record.timezone || 'Asia/Riyadh' }}</div>
            </div>
          </template>
          <template v-else-if="column.key === 'status'">
            <Space direction="vertical" size="small">
              <Tag :color="statusColor(record.status)">
                {{ configStatusTextMap[String(record.status || '')] || record.status || '-' }}
              </Tag>
              <span class="sub-text">{{ record.editable ? '可编辑' : '只读' }}</span>
            </Space>
          </template>
          <template v-else-if="column.key === 'gifts'">
            <div class="tag-stack">
              <Tag
                v-for="item in record.giftConfigs || []"
                :key="`${record.id}-${item.giftId}`"
                color="gold"
              >
                {{ item.giftName || item.giftId }}
              </Tag>
            </div>
          </template>
          <template v-else-if="column.key === 'rewards'">
            <div class="tag-stack">
              <Tag
                v-for="item in record.rewardConfigs || []"
                :key="`${record.id}-${item.rank}`"
                color="green"
              >
                Top{{ item.rank }} {{ item.rewardGroupName || item.rewardGroupId || '-' }}
              </Tag>
            </div>
          </template>
          <template v-else-if="column.key === 'actions'">
            <Space>
              <Button
                size="small"
                type="primary"
                @click="openConfigModal(record, !record.editable)"
              >
                {{ record.editable ? '编辑' : '查看' }}
              </Button>
            </Space>
          </template>
        </template>
      </Table>

      <div v-if="configTotal > 0" class="pager">
        <Pagination
          :current="configQuery.cursor"
          :page-size="configQuery.limit"
          :total="configTotal"
          show-size-changer
          @change="handleConfigPageChange"
          @showSizeChange="handleConfigPageChange"
        />
      </div>
    </Card>

    <Card :bordered="false" class="mt-16" title="当前排行榜">
      <Space class="toolbar" wrap>
        <Tag :color="statusColor(rankMeta.activityStatus)">
          {{ configStatusTextMap[rankMeta.activityStatus] || rankMeta.activityStatus || '未配置' }}
        </Tag>
        <Tag color="processing">{{ rankMeta.cycleKey || '-' }}</Tag>
        <Tag>{{ rankMeta.timezone || '-' }}</Tag>
        <span class="sub-text">
          {{ rankMeta.periodStartAt || '-' }} ~ {{ rankMeta.periodEndAt || '-' }}
        </span>
        <div class="tag-stack">
          <Tag
            v-for="item in rankMeta.giftConfigs"
            :key="`${rankMeta.configId}-${item.giftId}`"
            color="gold"
          >
            {{ item.giftName || item.giftId }}
          </Tag>
        </div>
        <Select
          v-model:value="rankQuery.limit"
          :options="[
            { label: 'Top 20', value: 20 },
            { label: 'Top 50', value: 50 },
            { label: 'Top 100', value: 100 },
          ]"
          style="width: 120px"
          @change="loadCurrentRank"
        />
        <Button :loading="rankLoading" type="primary" @click="loadCurrentRank">
          刷新排行
        </Button>
      </Space>

      <Table
        :columns="rankColumns"
        :data-source="rankList"
        :loading="rankLoading"
        :pagination="false"
        row-key="userId"
        :scroll="{ x: 680 }"
      >
        <template #bodyCell="{ column, record }">
          <template v-if="column.key === 'user'">
            <div class="user-cell">
              <div
                v-if="record.userAvatar"
                class="avatar"
                :style="avatarBackgroundStyle(record.userAvatar)"
              />
              <div v-else class="avatar placeholder">U</div>
              <div class="user-meta">
                <div>{{ record.userNickname || '-' }}</div>
                <div class="sub-text">
                  {{ record.account || record.userId }}
                  <span v-if="record.countryCode"> · {{ record.countryCode }}</span>
                </div>
              </div>
            </div>
          </template>
          <template v-else-if="column.key === 'countryName'">
            {{ record.countryName || record.countryCode || '-' }}
          </template>
        </template>
      </Table>
    </Card>

    <Card :bordered="false" class="mt-16" title="上周快照">
      <Space class="toolbar" wrap>
        <Select
          v-model:value="snapshotQuery.configId"
          allow-clear
          :options="configFilterOptions"
          placeholder="按活动周期筛选"
          style="width: 260px"
        />
        <Input
          v-model:value="snapshotQuery.cycleKey"
          allow-clear
          placeholder="周期Key，例如 20260414"
          style="width: 220px"
        />
        <Button :loading="snapshotLoading" type="primary" @click="loadSnapshots(true)">
          搜索
        </Button>
      </Space>

      <Table
        :columns="snapshotColumns"
        :data-source="snapshotList"
        :loading="snapshotLoading"
        :pagination="false"
        row-key="id"
        :scroll="{ x: 980 }"
      >
        <template #bodyCell="{ column, record }">
          <template v-if="column.key === 'user'">
            <div class="user-cell">
              <div
                v-if="record.userAvatar"
                class="avatar"
                :style="avatarBackgroundStyle(record.userAvatar)"
              />
              <div v-else class="avatar placeholder">U</div>
              <div class="user-meta">
                <div>{{ record.userNickname || '-' }}</div>
                <div class="sub-text">
                  {{ record.account || record.userId }}
                  <span v-if="record.countryCode"> · {{ record.countryCode }}</span>
                </div>
              </div>
            </div>
          </template>
          <template v-else-if="column.key === 'period'">
            {{ record.periodStartAt || '-' }} ~ {{ record.periodEndAt || '-' }}
          </template>
        </template>
      </Table>

      <div v-if="snapshotTotal > 0" class="pager">
        <Pagination
          :current="snapshotQuery.cursor"
          :page-size="snapshotQuery.limit"
          :total="snapshotTotal"
          show-size-changer
          @change="handleSnapshotPageChange"
          @showSizeChange="handleSnapshotPageChange"
        />
      </div>
    </Card>

    <Card :bordered="false" class="mt-16" title="发奖记录">
      <Space class="toolbar" wrap>
        <Select
          v-model:value="rewardQuery.configId"
          allow-clear
          :options="configFilterOptions"
          placeholder="按活动周期筛选"
          style="width: 260px"
        />
        <Input
          v-model:value="rewardQuery.cycleKey"
          allow-clear
          placeholder="周期Key，例如 20260414"
          style="width: 220px"
        />
        <Select
          v-model:value="rewardQuery.status"
          allow-clear
          :options="rewardStatusOptions"
          placeholder="请选择状态"
          style="width: 140px"
        />
        <Button :loading="rewardLoading" type="primary" @click="loadRewardRecords(true)">
          搜索
        </Button>
      </Space>

      <Table
        :columns="rewardColumns"
        :data-source="rewardList"
        :loading="rewardLoading"
        :pagination="false"
        row-key="id"
        :scroll="{ x: 1560 }"
      >
        <template #bodyCell="{ column, record }">
          <template v-if="column.key === 'user'">
            <div class="user-cell">
              <div
                v-if="record.userAvatar"
                class="avatar"
                :style="avatarBackgroundStyle(record.userAvatar)"
              />
              <div v-else class="avatar placeholder">U</div>
              <div class="user-meta">
                <div>{{ record.userNickname || '-' }}</div>
                <div class="sub-text">
                  {{ record.account || record.userId }}
                  <span v-if="record.countryCode"> · {{ record.countryCode }}</span>
                </div>
              </div>
            </div>
          </template>
          <template v-else-if="column.key === 'status'">
            <Tag :color="statusColor(record.status)">
              {{ record.status }}
            </Tag>
          </template>
          <template v-else-if="column.key === 'lastError'">
            <span class="error-text">{{ record.lastError || '-' }}</span>
          </template>
          <template v-else-if="column.key === 'actions'">
            <Button
              :disabled="record.status !== 'FAILED'"
              size="small"
              type="primary"
              @click="handleRetry(record)"
            >
              补发
            </Button>
          </template>
        </template>
      </Table>

      <div v-if="rewardTotal > 0" class="pager">
        <Pagination
          :current="rewardQuery.cursor"
          :page-size="rewardQuery.limit"
          :total="rewardTotal"
          show-size-changer
          @change="handleRewardPageChange"
          @showSizeChange="handleRewardPageChange"
        />
      </div>
    </Card>

    <Modal
      :destroy-on-close="false"
      :footer="null"
      :open="editorOpen"
      :title="editorTitle"
      width="960px"
      @cancel="editorOpen = false"
    >
      <Spin :spinning="editorLoading || editorGiftLoading">
        <div class="editor-top">
          <Space wrap>
            <Tag :color="statusColor(form.status)">{{ editorStatusText }}</Tag>
            <Tag v-if="form.updateTime">更新于 {{ form.updateTime }}</Tag>
            <Tag :color="editorReadonly ? 'default' : 'processing'">
              {{ editorReadonly ? '当前为只读配置' : '当前为可编辑配置' }}
            </Tag>
          </Space>
        </div>

        <div class="section">
          <div class="field-label">系统</div>
          <Select
            :disabled="editorReadonly || Boolean(form.id)"
            :options="sysOriginOptions"
            :value="form.sysOrigin"
            option-filter-prop="label"
            option-label-prop="label"
            show-search
            style="width: 220px"
            @update:value="handleEditorSysOriginChange"
          />
        </div>

        <div class="section">
          <div class="field-label">活动开关</div>
          <Switch v-model:checked="form.enabled" :disabled="editorReadonly" />
        </div>

        <div class="section">
          <div class="field-label">活动时间</div>
          <DatePicker.RangePicker
            v-model:value="rangeDate"
            :disabled="editorReadonly"
            show-time
            style="width: 420px"
            value-format="YYYY-MM-DD HH:mm:ss"
          />
        </div>

        <div class="section">
          <div class="field-label">活动时区</div>
          <Input v-model:value="form.timezone" :disabled="editorReadonly" style="width: 240px" />
        </div>

        <div class="section block">
          <div class="field-label">指定礼物</div>
          <div class="slot-list">
            <div
              v-for="slot in form.giftConfigs"
              :key="slot.sort"
              class="slot-row"
            >
              <div class="slot-title">礼物 {{ slot.sort }}</div>
              <Select
                :disabled="editorReadonly"
                :options="getGiftSelectOptions(slot.giftId)"
                :value="slot.giftId"
                placeholder="请选择礼物"
                show-search
                style="width: 320px"
                @update:value="handleGiftChange(slot, $event)"
              />
              <div class="slot-preview">
                <Image
                  v-if="slot.giftPhoto"
                  :preview="false"
                  :src="slot.giftPhoto"
                  class="thumb"
                />
                <div v-else class="thumb placeholder">G</div>
                <div class="slot-meta">
                  <div class="slot-name">{{ slot.giftName || '未选择礼物' }}</div>
                  <div class="slot-sub">{{ slot.giftCandy || 0 }} 金币</div>
                </div>
              </div>
            </div>
          </div>
        </div>

        <div class="section block">
          <div class="field-label">奖励组</div>
          <div class="slot-list">
            <div
              v-for="slot in form.rewardConfigs"
              :key="slot.rank"
              class="reward-row"
            >
              <div class="reward-head">
                <div class="slot-title">Top{{ slot.rank }}</div>
                <Space wrap>
                  <Button
                    :disabled="editorReadonly"
                    type="primary"
                    @click="openRewardPicker(slot.rank)"
                  >
                    {{ slot.rewardGroupId ? '更换奖励组' : '选择奖励组' }}
                  </Button>
                  <Button
                    v-if="slot.rewardGroupId && !editorReadonly"
                    danger
                    type="link"
                    @click="clearRewardGroup(slot.rank)"
                  >
                    清空
                  </Button>
                  <span class="reward-name">
                    {{ slot.rewardGroupName || '未选择奖励组' }}
                  </span>
                </Space>
              </div>

              <div class="reward-items">
                <div
                  v-for="item in slot.items"
                  :key="`${slot.rank}-${item.id}`"
                  class="reward-item"
                >
                  <Image
                    v-if="item.cover"
                    :preview="false"
                    :src="item.cover"
                    class="thumb"
                  />
                  <div v-else class="thumb placeholder">R</div>
                  <div class="reward-item-meta">
                    <div class="reward-item-name">{{ item.name || item.content || item.type }}</div>
                    <div class="reward-item-sub">
                      {{ item.quantity ? `${item.quantity}天/个` : item.type || '-' }}
                    </div>
                  </div>
                </div>
                <div v-if="!slot.items?.length" class="empty-preview">
                  保存后会按奖励组详情回显预览
                </div>
              </div>
            </div>
          </div>
        </div>

        <Space class="actions" wrap>
          <Button @click="editorOpen = false">关闭</Button>
          <Button v-if="!editorReadonly" :loading="saving" type="primary" @click="submitForm">
            保存配置
          </Button>
        </Space>
      </Spin>
    </Modal>

    <ActivityResourceGroupSelectDrawer
      :open="groupPickerOpen"
      :sys-origin="form.sysOrigin"
      @close="groupPickerOpen = false"
      @select="handleRewardGroupSelect"
    />
  </Page>
</template>

<style scoped>
.toolbar {
  margin-bottom: 20px;
}

.editor-top {
  margin-bottom: 20px;
}

.section {
  align-items: center;
  display: flex;
  gap: 16px;
  margin-bottom: 20px;
}

.section.block {
  align-items: flex-start;
}

.field-label {
  color: rgb(15 23 42);
  flex: 0 0 120px;
  font-weight: 600;
  line-height: 32px;
}

.sub-text {
  color: rgb(100 116 139);
}

.slot-list {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 16px;
}

.slot-row,
.reward-row {
  border: 1px solid rgb(226 232 240);
  border-radius: 8px;
  padding: 16px;
}

.slot-title {
  color: rgb(15 23 42);
  font-weight: 600;
  min-width: 68px;
}

.slot-row {
  align-items: center;
  display: flex;
  gap: 16px;
}

.slot-preview,
.user-cell {
  align-items: center;
  display: flex;
  gap: 12px;
}

.slot-meta,
.user-meta,
.reward-item-meta,
.period-cell {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.slot-name,
.reward-name,
.reward-item-name {
  color: rgb(15 23 42);
}

.slot-sub,
.reward-item-sub {
  color: rgb(100 116 139);
  font-size: 12px;
}

.thumb {
  border-radius: 8px;
  height: 48px;
  object-fit: cover;
  width: 48px;
}

.avatar {
  background-position: center;
  background-repeat: no-repeat;
  background-size: cover;
  border-radius: 999px;
  flex: 0 0 40px;
  height: 40px;
  width: 40px;
}

.placeholder {
  align-items: center;
  background: rgb(241 245 249);
  color: rgb(100 116 139);
  display: flex;
  font-weight: 600;
  justify-content: center;
}

.reward-head {
  align-items: center;
  display: flex;
  gap: 16px;
  justify-content: space-between;
  margin-bottom: 12px;
}

.reward-items {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

.reward-item {
  align-items: center;
  border: 1px solid rgb(226 232 240);
  border-radius: 8px;
  display: flex;
  gap: 12px;
  max-width: 320px;
  min-width: 220px;
  padding: 10px 12px;
}

.empty-preview {
  color: rgb(148 163 184);
  padding: 8px 0;
}

.actions {
  margin-top: 8px;
}

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

.mt-16 {
  margin-top: 16px;
}

.error-text {
  color: rgb(220 38 38);
}

.tag-stack {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
</style>
