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

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

import type { Dayjs } from 'dayjs';
import dayjs from 'dayjs';

import {
  getResidentSmashGoldenEggConfig,
  pageResidentSmashGoldenEggDrawRecords,
  saveResidentSmashGoldenEggConfig,
} from '#/api/legacy/resident-activity';
import PropsSourceSelectDrawer from '#/views/operate/components/props-source-select-drawer.vue';
import { getAllowedSysOrigins } from '#/views/system/shared';

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

defineOptions({ name: 'ResidentSmashGoldenEggPage' });

const { RangePicker } = DatePicker;

const DEFAULT_DRAW_OPTIONS = [
  { label: '抽 1 次', optionKey: 'ONE', priceGold: 500, times: 1 },
  { label: '抽 10 次', optionKey: 'TEN', priceGold: 5000, times: 10 },
  { label: '抽 100 次', optionKey: 'HUNDRED', priceGold: 50_000, times: 100 },
];

type RewardPoolKey = 'newbieRewards' | 'rewards';

let localRowId = 0;

const REWARD_TYPE_OPTIONS = [
  { label: '资源', value: 'RESOURCE' },
  { label: '金币', value: 'GOLD' },
];
const PROBABILITY_TOTAL = 100 * 10_000;

function normalizeRewardTypeValue(value: any) {
  return String(value || 'GOLD').toUpperCase() === 'RESOURCE' ? 'RESOURCE' : 'GOLD';
}

function createRowKey(prefix: string, seed?: number | string) {
  localRowId += 1;
  return `${prefix}-${seed || localRowId}-${localRowId}`;
}

function createDrawOption(seed?: Record<string, any>) {
  const index = Number(seed?.sort || localRowId + 1);
  return {
    calculatedRTPBasisPoints: Number(seed?.calculatedRTPBasisPoints ?? seed?.rtpBasisPoints ?? 0),
    enabled: seed?.enabled !== false,
    id: Number(seed?.id || 0),
    label: String(seed?.label || `抽 ${Number(seed?.times || 1)} 次`),
    optionKey: String(seed?.optionKey || `CUSTOM_${Date.now()}_${localRowId}`),
    priceGold: Number(seed?.priceGold || 500),
    rowKey: createRowKey('egg-option', seed?.id || seed?.optionKey),
    sort: index,
    times: Number(seed?.times || 1),
  };
}

function createReward(seed?: Record<string, any>) {
  const rewardType = normalizeRewardTypeValue(seed?.rewardType);
  return {
    animationUrl: String(seed?.animationUrl || ''),
    coverUrl: String(seed?.coverUrl || ''),
    displayGoldAmount: Number(seed?.displayGoldAmount || seed?.rewardValueGold || 0),
    durationDays: Number(seed?.durationDays || (rewardType === 'RESOURCE' ? 7 : 0)),
    enabled: seed?.enabled !== false,
    goldAmount: Number(seed?.goldAmount || (rewardType === 'GOLD' ? seed?.rewardValueGold || 100 : 0)),
    id: Number(seed?.id || 0),
    probability: Number(seed?.probability || 0),
    poolType: String(seed?.poolType || 'GENERAL'),
    resourceId: seed?.resourceId ?? seed?.rewardGroupId ?? null,
    resourceName: String(seed?.resourceName || seed?.rewardGroupName || ''),
    resourceType: String(seed?.resourceType || (rewardType === 'RESOURCE' ? 'AVATAR_FRAME' : '')),
    resourceUrl: String(seed?.resourceUrl || ''),
    rewardGroupId: seed?.rewardGroupId ?? null,
    rewardGroupName: String(seed?.rewardGroupName || (rewardType === 'GOLD' ? '金币' : '')),
    rewardItems: [],
    rewardType,
    rewardValueGold: Number(seed?.rewardValueGold || seed?.goldAmount || seed?.displayGoldAmount || 100),
    rowKey: createRowKey('egg-reward', seed?.id),
    sort: Number(seed?.sort || localRowId),
  };
}

function createEmptyForm(sysOrigin = '') {
  return {
    configured: false,
    drawOptions: DEFAULT_DRAW_OPTIONS.map((item, index) =>
      createDrawOption({ ...item, sort: index + 1 }),
    ),
    enabled: false,
    id: 0,
    newbieMaxDrawCount: 3,
    newbieMinRechargeAmount: 0,
    newbiePoolEnabled: false,
    newbieRewards: [
      createReward({ poolType: 'NEWBIE' }),
      createReward({ poolType: 'NEWBIE' }),
    ],
    newbieWindowDays: 7,
    rewards: [createReward(), createReward()],
    rtpBasisPoints: 9500,
    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 activeTab = ref('config');
const loading = ref(false);
const saving = ref(false);
const recordLoading = ref(false);
const recordRangeDate = ref<[Dayjs, Dayjs] | null>([
  dayjs().subtract(7, 'day'),
  dayjs(),
]);
const resourcePickerOpen = ref(false);
const pickerPool = ref<RewardPoolKey>('rewards');
const pickerRewardIndex = ref(-1);
const pickerRewardRecord = ref<null | Record<string, any>>(null);

const form = reactive<Record<string, any>>(createEmptyForm());
const recordQuery = reactive<Record<string, any>>({
  cursor: 1,
  limit: 20,
  status: '',
  userId: '',
});
const recordPage = reactive<Record<string, any>>({
  current: 1,
  records: [],
  size: 20,
  total: 0,
});
const recordSummary = reactive<Record<string, any>>({
  endTime: '',
  returnRatioBasisPoints: 0,
  returnRatioPercent: '0.00',
  startTime: '',
  totalPaidGold: 0,
  totalRewardGold: 0,
});

const autoProbabilityMaps = computed<Record<RewardPoolKey, number[]>>(() => ({
  newbieRewards: autoProbabilitiesForPool('newbieRewards'),
  rewards: autoProbabilitiesForPool('rewards'),
}));

const optionColumns = [
  { dataIndex: 'enabled', key: 'enabled', title: '启用', width: 80 },
  { dataIndex: 'sort', key: 'sort', title: '排序', width: 90 },
  { dataIndex: 'label', key: 'label', title: '按钮文案', width: 170 },
  { dataIndex: 'times', key: 'times', title: '次数', width: 130 },
  { dataIndex: 'priceGold', key: 'priceGold', title: '价格', width: 160 },
  { dataIndex: 'calculatedRTPBasisPoints', key: 'calculatedRTPBasisPoints', title: '当前 RTP', width: 110 },
  { dataIndex: 'actions', key: 'actions', title: '操作', width: 90 },
];

const rewardColumns = [
  { dataIndex: 'enabled', key: 'enabled', title: '启用', width: 80 },
  { dataIndex: 'sort', key: 'sort', title: '排序', width: 90 },
  { dataIndex: 'rewardType', key: 'rewardType', title: '类型', width: 120 },
  { dataIndex: 'reward', key: 'reward', title: '奖励与展示素材', width: 720 },
  { dataIndex: 'probability', key: 'probability', title: '自动概率', width: 120 },
  { dataIndex: 'actions', key: 'actions', title: '操作', width: 90 },
];

const recordColumns = [
  { dataIndex: 'drawNo', key: 'drawNo', title: '抽奖单号', width: 190 },
  { dataIndex: 'userId', key: 'userId', title: '用户ID', width: 140 },
  { dataIndex: 'poolType', key: 'poolType', title: '奖池', width: 100 },
  { dataIndex: 'drawTimes', key: 'drawTimes', title: '次数', width: 90 },
  { dataIndex: 'paidGold', key: 'paidGold', title: '消耗金币', width: 120 },
  { dataIndex: 'reward', key: 'reward', title: '中奖奖励', width: 380 },
  { dataIndex: 'probability', key: 'probability', title: '命中概率', width: 110 },
  { dataIndex: 'status', key: 'status', title: '状态', width: 110 },
  { dataIndex: 'createTime', key: 'createTime', title: '时间', width: 180 },
  { dataIndex: 'errorMessage', key: 'errorMessage', title: '失败原因', width: 260 },
];

const rtpPercent = computed({
  get: () => Number((Number(form.rtpBasisPoints || 0) / 100).toFixed(2)),
  set: (value: number) => {
    form.rtpBasisPoints = Math.round(Number(value || 0) * 100);
  },
});

const statusMeta = computed(() => {
  if (!form.configured) {
    return { color: 'processing', text: '未配置' };
  }
  if (form.enabled) {
    return { color: 'success', text: '已启用' };
  }
  return { color: 'default', text: '已关闭' };
});

function normalizeDrawOptions(list: Array<Record<string, any>> | undefined) {
  const source = Array.isArray(list) && list.length > 0
    ? list
    : DEFAULT_DRAW_OPTIONS.map((item, index) => ({ ...item, sort: index + 1 }));
  return source.map((item) => createDrawOption(item));
}

function normalizeRewards(list: Array<Record<string, any>> | undefined, poolType = 'GENERAL') {
  const source = Array.isArray(list) && list.length > 0
    ? list
    : [
        createReward({ poolType }),
        createReward({ poolType }),
      ];
  return source.map((item: Record<string, any>) =>
    createReward({ ...item, poolType }),
  );
}

function applyConfig(result: Record<string, any> | null | undefined) {
  const value = result || {};
  const next = createEmptyForm(
    String(value.sysOrigin || selectedSysOrigin.value || sysOriginOptions.value[0]?.value || ''),
  );
  Object.assign(form, next, {
    configured: Boolean(value.configured),
    enabled: Boolean(value.enabled),
    id: Number(value.id || 0),
    newbieMaxDrawCount: Number(value.newbieMaxDrawCount || next.newbieMaxDrawCount),
    newbieMinRechargeAmount: Number(value.newbieMinRechargeAmount || 0),
    newbiePoolEnabled: Boolean(value.newbiePoolEnabled),
    newbieWindowDays: Number(value.newbieWindowDays || next.newbieWindowDays),
    rtpBasisPoints: Number(value.rtpBasisPoints || next.rtpBasisPoints),
    sysOrigin: String(value.sysOrigin || next.sysOrigin),
    timezone: String(value.timezone || 'Asia/Riyadh'),
    updateTime: String(value.updateTime || ''),
  });
  form.drawOptions = normalizeDrawOptions(value.drawOptions);
  form.rewards = normalizeRewards(value.rewards, 'GENERAL');
  form.newbieRewards = normalizeRewards(value.newbieRewards, 'NEWBIE');
}

async function loadConfig() {
  if (!selectedSysOrigin.value) {
    return;
  }
  loading.value = true;
  try {
    const result = await getResidentSmashGoldenEggConfig(selectedSysOrigin.value);
    applyConfig(result);
  } finally {
    loading.value = false;
  }
}

function normalizeRecordPage(result: Record<string, any> | null | undefined) {
  const value = result || {};
  recordPage.records = Array.isArray(value.records) ? value.records : [];
  recordPage.total = Number(value.total || 0);
  recordPage.current = Number(value.current || 1);
  recordPage.size = Number(value.size || 20);
  Object.assign(recordSummary, {
    endTime: String(value.endTime || ''),
    returnRatioBasisPoints: Number(value.returnRatioBasisPoints || 0),
    returnRatioPercent: String(value.returnRatioPercent || '0.00'),
    startTime: String(value.startTime || ''),
    totalPaidGold: Number(value.totalPaidGold || 0),
    totalRewardGold: Number(value.totalRewardGold || 0),
  });
}

function recordTimeParams() {
  const range = recordRangeDate.value;
  if (!range?.length) {
    return { endTime: '', startTime: '' };
  }
  return {
    endTime: range[1]?.format('YYYY-MM-DD HH:mm:ss') || '',
    startTime: range[0]?.format('YYYY-MM-DD HH:mm:ss') || '',
  };
}

async function loadRecords(reset = false) {
  if (!selectedSysOrigin.value) {
    return;
  }
  if (reset) {
    recordQuery.cursor = 1;
  }
  recordLoading.value = true;
  try {
    const result = await pageResidentSmashGoldenEggDrawRecords({
      ...recordQuery,
      ...recordTimeParams(),
      sysOrigin: selectedSysOrigin.value,
    });
    normalizeRecordPage(result);
  } finally {
    recordLoading.value = false;
  }
}

function firstPresent(record: Record<string, any>, keys: string[]) {
  for (const key of keys) {
    const value = record?.[key];
    if (value !== undefined && value !== null && String(value).trim() !== '') {
      return value;
    }
  }
  return '';
}

function normalizeSelectedResource(row: Record<string, any>, fallbackType = 'AVATAR_FRAME') {
  const resourceId = firstPresent(row, [
    'id',
    'resourceId',
    'sourceId',
    'propsId',
    'propsSourceId',
    'badgeConfigId',
    'giftId',
    'groupId',
  ]);
  return {
    coverUrl: String(
      firstPresent(row, [
        'cover',
        'coverUrl',
        'resourceCover',
        'resourceCoverUrl',
        'giftPhoto',
        'selectUrl',
        'icon',
        'smallIcon',
      ]),
    ),
    resourceId,
    resourceName: String(
      firstPresent(row, [
        'name',
        'resourceName',
        'sourceName',
        'giftName',
        'badgeName',
        'groupName',
        'title',
        'remark',
      ]) || (resourceId ? `资源 ${resourceId}` : ''),
    ),
    resourceType: String(
      firstPresent(row, ['type', 'resourceType', 'propsType']) || fallbackType || 'AVATAR_FRAME',
    ),
    resourceUrl: String(
      firstPresent(row, [
        'sourceUrl',
        'resourceUrl',
        'url',
        'giftSourceUrl',
        'animationUrl',
        'playUrl',
      ]),
    ),
  };
}

function normalizeRewardResourceId(item: Record<string, any>) {
  return String(
    firstPresent(item, [
      'resourceId',
      'resourceID',
      'resource_id',
      'rewardGroupId',
      'sourceId',
      'propsId',
      'propsSourceId',
      'badgeConfigId',
      'giftId',
      'groupId',
    ]),
  ).trim();
}

function hasRewardResourceId(item: Record<string, any>) {
  const resourceId = normalizeRewardResourceId(item);
  return resourceId !== '' && resourceId !== '0';
}

function openResourcePicker(pool: RewardPoolKey, index: number, record?: Record<string, any>) {
  pickerPool.value = pool;
  pickerRewardIndex.value = index;
  pickerRewardRecord.value = record || null;
  resourcePickerOpen.value = true;
}

function closeResourcePicker() {
  resourcePickerOpen.value = false;
  pickerRewardRecord.value = null;
}

function handleResourceSelect(row: Record<string, any>) {
  const rewards = form[pickerPool.value] as Array<Record<string, any>>;
  const target = pickerRewardRecord.value || rewards?.[pickerRewardIndex.value];
  if (!target) {
    closeResourcePicker();
    return;
  }
  const selected = normalizeSelectedResource(row, target.resourceType || 'AVATAR_FRAME');
  if (!selected.resourceId) {
    message.warning('资源数据缺少 ID，无法选择');
    closeResourcePicker();
    return;
  }
  target.rewardType = 'RESOURCE';
  target.resourceId = String(selected.resourceId).trim();
  target.rewardGroupId = target.resourceId;
  target.resourceType = selected.resourceType;
  target.resourceName = selected.resourceName;
  target.rewardGroupName = selected.resourceName;
  target.resourceUrl = selected.resourceUrl;
  target.coverUrl = selected.coverUrl || target.coverUrl || '';
  target.animationUrl = selected.resourceUrl || target.animationUrl || '';
  target.displayGoldAmount = Number(target.displayGoldAmount || 0);
  target.durationDays = Number(target.durationDays || 7);
  target.goldAmount = 0;
  closeResourcePicker();
}

function clearResource(record: Record<string, any>) {
  record.resourceId = null;
  record.rewardGroupId = null;
  record.resourceName = '';
  record.rewardGroupName = '';
  record.resourceUrl = '';
  record.coverUrl = '';
  record.animationUrl = '';
  record.displayGoldAmount = 0;
  record.durationDays = normalizeRewardTypeValue(record.rewardType) === 'RESOURCE' ? 7 : 0;
}

function handleRewardTypeChange(record: Record<string, any>, value?: string) {
  record.rewardType = normalizeRewardTypeValue(value || record.rewardType);
  record.probability = 0;
  if (record.rewardType === 'GOLD') {
    record.resourceId = null;
    record.rewardGroupId = null;
    record.resourceName = '';
    record.resourceType = '';
    record.resourceUrl = '';
    record.displayGoldAmount = 0;
    record.durationDays = 0;
    record.rewardGroupName = '金币';
    record.goldAmount = Number(record.goldAmount || 100);
    record.rewardValueGold = record.goldAmount;
    return;
  }
  record.goldAmount = 0;
  record.resourceType = record.resourceType || 'AVATAR_FRAME';
  record.durationDays = Number(record.durationDays || 7);
  record.displayGoldAmount = Number(record.displayGoldAmount || 0);
}

function addDrawOption() {
  const options = form.drawOptions as Array<Record<string, any>>;
  const nextTimes = Math.max(0, ...options.map((item) => Number(item.times || 0))) + 1;
  options.push(
    createDrawOption({
      label: `抽 ${nextTimes} 次`,
      optionKey: `CUSTOM_${Date.now()}`,
      priceGold: 500,
      sort: Math.max(0, ...options.map((item) => Number(item.sort || 0))) + 1,
      times: nextTimes,
    }),
  );
}

function confirmRemoveDrawOption(index: number) {
  Modal.confirm({
    onOk: () => {
      (form.drawOptions as Array<Record<string, any>>).splice(index, 1);
    },
    title: '确认删除该抽奖档位？',
  });
}

function addReward(pool: RewardPoolKey = 'rewards') {
  const rewards = form[pool] as Array<Record<string, any>>;
  const row = createReward({ poolType: pool === 'newbieRewards' ? 'NEWBIE' : 'GENERAL' });
  row.sort = Math.max(0, ...rewards.map((item) => Number(item.sort || 0))) + 1;
  rewards.push(row);
}

function confirmRemoveReward(index: number, pool: RewardPoolKey = 'rewards') {
  Modal.confirm({
    onOk: () => {
      (form[pool] as Array<Record<string, any>>).splice(index, 1);
    },
    title: '确认删除该砸蛋奖励？',
  });
}

function validateRewardPool(pool: RewardPoolKey, title: string) {
  const rewards = (form[pool] || []) as Array<Record<string, any>>;
  const enabledRewards = rewards.filter((item: Record<string, any>) => item.enabled !== false);
  if (form.enabled && enabledRewards.length === 0) {
    message.warning(`启用时，${title}必须至少配置一个奖励`);
    return false;
  }
  for (const item of enabledRewards) {
    const rewardType = normalizeRewardTypeValue(item.rewardType);
    item.rewardType = rewardType;
    if (rewardType === 'GOLD') {
      if (Number(item.goldAmount || 0) <= 0) {
        message.warning(`${title}的金币奖励必须设置金币数量`);
        return false;
      }
      continue;
    }
    if (!hasRewardResourceId(item)) {
      message.warning(`${title}的资源奖励必须选择资源`);
      return false;
    }
    if (!String(item.resourceType || '').trim()) {
      message.warning(`${title}的资源奖励必须有资源类型`);
      return false;
    }
    if (Number(item.durationDays || 0) <= 0) {
      message.warning(`${title}的资源奖励有效天数必须大于 0`);
      return false;
    }
    if (Number(item.displayGoldAmount || 0) <= 0) {
      message.warning(`${title}的资源奖励展示金币价格必须大于 0`);
      return false;
    }
  }
  return true;
}

function validateBeforeSave() {
  if (!selectedSysOrigin.value) {
    message.warning('请选择系统');
    return false;
  }
  if (Number(form.rtpBasisPoints || 0) < 0) {
    message.warning('RTP 不能小于 0');
    return false;
  }
  const enabledOptions = (form.drawOptions || []).filter(
    (item: Record<string, any>) => item.enabled !== false,
  );
  if (form.enabled && enabledOptions.length === 0) {
    message.warning('启用时必须至少配置一个抽奖档位');
    return false;
  }
  if (form.newbiePoolEnabled) {
    if (Number(form.newbieWindowDays || 0) <= 0) {
      message.warning('新人窗口天数必须大于 0');
      return false;
    }
    if (Number(form.newbieMaxDrawCount || 0) <= 0) {
      message.warning('新人奖池次数上限必须大于 0');
      return false;
    }
    if (Number(form.newbieMinRechargeAmount || 0) < 0) {
      message.warning('新人最低累计充值金额不能小于 0');
      return false;
    }
  }
  const times = new Set<number>();
  for (const item of form.drawOptions || []) {
    if (item.enabled === false) {
      continue;
    }
    const drawTimes = Number(item.times || 0);
    if (drawTimes <= 0 || Number(item.priceGold || 0) <= 0) {
      message.warning('已启用抽奖档位的次数和价格必须大于 0');
      return false;
    }
    if (times.has(drawTimes)) {
      message.warning('抽奖档位次数不能重复');
      return false;
    }
    times.add(drawTimes);
  }
  if (!validateRewardPool('rewards', '普通奖池')) {
    return false;
  }
  if (form.newbiePoolEnabled && !validateRewardPool('newbieRewards', '新人奖池')) {
    return false;
  }
  return true;
}

function roundDivNumber(numerator: number, denominator: number) {
  if (!Number.isFinite(numerator) || !Number.isFinite(denominator) || denominator <= 0) {
    return 0;
  }
  return Math.floor((numerator + denominator / 2) / denominator);
}

function rewardAutoValue(item: Record<string, any>) {
  if (normalizeRewardTypeValue(item.rewardType) === 'RESOURCE') {
    return Number(item.displayGoldAmount || item.rewardValueGold || 0);
  }
  return Number(item.goldAmount || item.rewardValueGold || 0);
}

function bestHighCount(
  target: number,
  lowValue: number,
  highValue: number,
  remaining: number,
  seed: number,
) {
  const weightedDiff = (count: number) =>
    Math.abs(target - (lowValue * (remaining - count) + highValue * count));
  let best = seed;
  let bestDiff = weightedDiff(seed);
  for (const candidate of [seed - 1, seed + 1]) {
    if (candidate < 0 || candidate > remaining) {
      continue;
    }
    const diff = weightedDiff(candidate);
    if (diff < bestDiff) {
      best = candidate;
      bestDiff = diff;
    }
  }
  return best;
}

function calculateAutoProbabilities(targetWeighted: number, rewards: Array<Record<string, any>>) {
  const probabilities = new Array(rewards.length).fill(0);
  const items = rewards
    .map((item, index) => ({ index, value: rewardAutoValue(item) }))
    .filter((item) => rewards[item.index]?.enabled !== false && item.value > 0)
    .sort((a, b) => (a.value === b.value ? a.index - b.index : a.value - b.value));
  if (items.length === 0 || items.length > PROBABILITY_TOTAL) {
    return probabilities;
  }
  const firstItem = items[0];
  const lastItem = items[items.length - 1];
  if (!firstItem || !lastItem) {
    return probabilities;
  }

  let baseWeighted = 0;
  for (const item of items) {
    probabilities[item.index] = 1;
    baseWeighted += item.value;
  }
  const remaining = PROBABILITY_TOTAL - items.length;
  if (remaining <= 0) {
    return probabilities;
  }

  const residualTarget = targetWeighted - baseWeighted;
  const minResidual = firstItem.value * remaining;
  const maxResidual = lastItem.value * remaining;
  if (residualTarget < minResidual) {
    probabilities[firstItem.index] += remaining;
    return probabilities;
  }
  if (residualTarget > maxResidual) {
    probabilities[lastItem.index] += remaining;
    return probabilities;
  }

  let low = firstItem;
  let high = lastItem;
  for (let index = 0; index < items.length; index += 1) {
    const item = items[index];
    if (!item) {
      continue;
    }
    if (item.value * remaining <= residualTarget) {
      low = item;
      high = items[index + 1] || item;
    }
  }
  if (low.value === high.value) {
    probabilities[low.index] += remaining;
    return probabilities;
  }

  const spread = high.value - low.value;
  let highCount = roundDivNumber(residualTarget - low.value * remaining, spread);
  highCount = Math.max(0, Math.min(remaining, highCount));
  highCount = bestHighCount(residualTarget, low.value, high.value, remaining, highCount);
  probabilities[low.index] += remaining - highCount;
  probabilities[high.index] += highCount;
  return probabilities;
}

function autoProbabilitiesForPool(pool: RewardPoolKey) {
  const options = ((form.drawOptions || []) as Array<Record<string, any>>)
    .filter((item) => item.enabled !== false && Number(item.times || 0) > 0 && Number(item.priceGold || 0) > 0)
    .sort((a, b) => Number(a.sort || 0) - Number(b.sort || 0));
  const rewards = (form[pool] || []) as Array<Record<string, any>>;
  if (options.length === 0) {
    return rewards.map((item) => Number(item.probability || 0));
  }
  const option = options[0];
  if (!option) {
    return rewards.map((item) => Number(item.probability || 0));
  }
  const targetWeighted = roundDivNumber(
    Number(option.priceGold || 0) * Number(form.rtpBasisPoints || 0) * PROBABILITY_TOTAL,
    Number(option.times || 0) * 10_000,
  );
  return calculateAutoProbabilities(targetWeighted, rewards);
}

function autoProbabilityForRow(pool: RewardPoolKey, index: number, record: Record<string, any>) {
  const probability = autoProbabilityMaps.value[pool]?.[index];
  if (probability !== undefined) {
    return Number(probability || 0);
  }
  return Number(record.probability || 0);
}

function rewardPayload(
  item: Record<string, any>,
  poolType: 'GENERAL' | 'NEWBIE',
  probability = 0,
) {
  const rewardType = normalizeRewardTypeValue(item.rewardType);
  const resourceId = normalizeRewardResourceId(item);
  const goldAmount = Number(item.goldAmount || 0);
  const displayGoldAmount = Number(item.displayGoldAmount || 0);
  return {
    animationUrl: String(item.animationUrl || ''),
    coverUrl: String(item.coverUrl || ''),
    displayGoldAmount: rewardType === 'RESOURCE' ? displayGoldAmount : 0,
    durationDays: rewardType === 'RESOURCE' ? Number(item.durationDays || 0) : 0,
    enabled: item.enabled !== false,
    goldAmount: rewardType === 'GOLD' ? goldAmount : 0,
    id: Number(item.id || 0),
    poolType,
    rewardGroupId: null,
    rewardGroupName:
      rewardType === 'RESOURCE' ? String(item.resourceName || item.rewardGroupName || '') : '金币',
    resourceId: rewardType === 'RESOURCE' && resourceId ? resourceId : null,
    resourceName: rewardType === 'RESOURCE' ? String(item.resourceName || '') : '',
    resourceType: rewardType === 'RESOURCE' ? String(item.resourceType || '') : '',
    resourceUrl: rewardType === 'RESOURCE' ? String(item.resourceUrl || '') : '',
    rewardType,
    rewardValueGold: rewardType === 'RESOURCE' ? displayGoldAmount : goldAmount,
    probability: Number(probability || item.probability || 0),
    sort: Number(item.sort || 0),
  };
}

async function submitForm() {
  if (!validateBeforeSave()) {
    return;
  }
  saving.value = true;
  try {
    const generalProbabilities = autoProbabilityMaps.value.rewards;
    const newbieProbabilities = autoProbabilityMaps.value.newbieRewards;
    await saveResidentSmashGoldenEggConfig({
      drawOptions: (form.drawOptions || []).map((item: Record<string, any>) => ({
        enabled: item.enabled !== false,
        id: Number(item.id || 0),
        label: String(item.label || ''),
        optionKey: String(item.optionKey || ''),
        priceGold: Number(item.priceGold || 0),
        sort: Number(item.sort || 0),
        times: Number(item.times || 0),
      })),
      enabled: Boolean(form.enabled),
      newbieMaxDrawCount: Number(form.newbieMaxDrawCount || 0),
      newbieMinRechargeAmount: Number(form.newbieMinRechargeAmount || 0),
      newbiePoolEnabled: Boolean(form.newbiePoolEnabled),
      newbieRewards: (form.newbieRewards || []).map((item: Record<string, any>, index: number) =>
        rewardPayload(item, 'NEWBIE', newbieProbabilities[index] || 0),
      ),
      newbieWindowDays: Number(form.newbieWindowDays || 0),
      rewards: (form.rewards || []).map((item: Record<string, any>, index: number) =>
        rewardPayload(item, 'GENERAL', generalProbabilities[index] || 0),
      ),
      rtpBasisPoints: Number(form.rtpBasisPoints || 0),
      sysOrigin: selectedSysOrigin.value,
      timezone: String(form.timezone || '').trim(),
    });
    message.success('保存成功');
    await loadConfig();
  } finally {
    saving.value = false;
  }
}

function handleRecordSearch() {
  void loadRecords(true);
}

function handleRecordTableChange(pagination: Record<string, any>) {
  recordQuery.cursor = Number(pagination.current || 1);
  recordQuery.limit = Number(pagination.pageSize || 20);
  void loadRecords();
}

function rewardRecordName(record: Record<string, any>) {
  if (record.resourceName || record.rewardGroupName) {
    return record.resourceName || record.rewardGroupName;
  }
  if (record.rewardType === 'GOLD') {
    return `${Number(record.goldAmount || 0).toLocaleString()} 金币`;
  }
  return '-';
}

function resourceDisplayName(record: Record<string, any>) {
  if (record.resourceName || record.rewardGroupName) {
    return record.resourceName || record.rewardGroupName;
  }
  if (record.resourceId || record.rewardGroupId) {
    return `资源 ${record.resourceId || record.rewardGroupId}`;
  }
  return '未选择资源';
}

function statusColor(status: string) {
  switch (String(status || '').toUpperCase()) {
    case 'SUCCESS':
      return 'success';
    case 'FAILED':
      return 'error';
    default:
      return 'processing';
  }
}

function percentText(value: number) {
  return `${(Number(value || 0) / 100).toFixed(2)}%`;
}

function trimFixed(value: number, precision: number) {
  const text = value.toFixed(precision).replace(/\.?0+$/, '');
  return text || '0';
}

function probabilityText(value: number) {
  return `${trimFixed((Number(value || 0) * 100) / PROBABILITY_TOTAL, 5)}%`;
}

function numberText(value: number) {
  return Number(value || 0).toLocaleString();
}

function summaryRatioText() {
  const raw = String(recordSummary.returnRatioPercent || '').trim();
  if (!raw) {
    return percentText(recordSummary.returnRatioBasisPoints);
  }
  return raw.endsWith('%') ? raw : `${raw}%`;
}

function coverStyle(url: string) {
  return {
    backgroundImage: `url("${String(url || '').replaceAll('"', '%22')}")`,
  };
}

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

watch(
  selectedSysOrigin,
  (value) => {
    if (value) {
      void loadConfig();
      void loadRecords(true);
    }
  },
  { immediate: true },
);

watch(activeTab, (value) => {
  if (value === 'records') {
    void loadRecords();
  }
});
</script>

<template>
  <Page auto-content-height>
    <Spin :spinning="loading">
      <Card :bordered="false" title="砸蛋配置">
        <div class="toolbar">
          <Space wrap>
            <Select
              v-model:value="selectedSysOrigin"
              :options="sysOriginOptions"
              option-filter-prop="label"
              option-label-prop="label"
              placeholder="请选择系统"
              show-search
              style="width: 180px"
            />
            <Tag :color="statusMeta.color">{{ statusMeta.text }}</Tag>
            <Tag>概率由后端按 RTP 自动计算</Tag>
            <Button :loading="loading" @click="loadConfig">刷新</Button>
          </Space>
        </div>

        <Tabs v-model:activeKey="activeTab">
          <TabPane key="config" tab="基础配置">
            <div class="config-row">
              <Space align="center" wrap>
                <span class="field-label">启用</span>
                <Switch v-model:checked="form.enabled" />
                <span class="field-label">RTP</span>
                <InputNumber
                  v-model:value="rtpPercent"
                  :min="0"
                  :precision="2"
                  addon-after="%"
                  style="width: 140px"
                />
                <span class="field-label">时区</span>
                <Input v-model:value="form.timezone" style="width: 180px" />
                <span class="sub-text">更新时间：{{ form.updateTime || '-' }}</span>
              </Space>
            </div>
            <div class="config-row">
              <Space align="center" wrap>
                <span class="field-label">新人奖池</span>
                <Switch v-model:checked="form.newbiePoolEnabled" />
                <span class="field-label">新人窗口</span>
                <InputNumber
                  v-model:value="form.newbieWindowDays"
                  :min="1"
                  :precision="0"
                  addon-after="天"
                  style="width: 130px"
                />
                <span class="field-label">新人池次数上限</span>
                <InputNumber
                  v-model:value="form.newbieMaxDrawCount"
                  :min="1"
                  :precision="0"
                  addon-after="次"
                  style="width: 140px"
                />
                <span class="field-label">最低累计充值</span>
                <InputNumber
                  v-model:value="form.newbieMinRechargeAmount"
                  :min="0"
                  :precision="0"
                  style="width: 150px"
                />
              </Space>
            </div>

            <Table
              :columns="optionColumns"
              :data-source="form.drawOptions"
              :loading="loading"
              :pagination="false"
              row-key="rowKey"
              :scroll="{ x: 920 }"
            >
              <template #bodyCell="{ column, index, record }">
                <template v-if="column.key === 'enabled'">
                  <Switch v-model:checked="record.enabled" />
                </template>
                <template v-else-if="column.key === 'sort'">
                  <InputNumber
                    v-model:value="record.sort"
                    :min="1"
                    :precision="0"
                    style="width: 72px"
                  />
                </template>
                <template v-else-if="column.key === 'label'">
                  <Input v-model:value="record.label" style="width: 140px" />
                </template>
                <template v-else-if="column.key === 'times'">
                  <InputNumber
                    v-model:value="record.times"
                    :min="1"
                    :precision="0"
                    style="width: 100px"
                  />
                </template>
                <template v-else-if="column.key === 'priceGold'">
                  <InputNumber
                    v-model:value="record.priceGold"
                    :min="1"
                    :precision="0"
                    addon-after="金币"
                    style="width: 136px"
                  />
                </template>
                <template v-else-if="column.key === 'calculatedRTPBasisPoints'">
                  {{ percentText(record.calculatedRTPBasisPoints) }}
                </template>
                <template v-else-if="column.key === 'actions'">
                  <Button danger type="link" @click="confirmRemoveDrawOption(index)">删除</Button>
                </template>
              </template>
            </Table>

            <div class="actions">
              <Button @click="addDrawOption">新增抽奖档位</Button>
            </div>

            <div class="section-title">普通奖池</div>
            <Table
              class="reward-table"
              :columns="rewardColumns"
              :data-source="form.rewards"
              :loading="loading"
              :pagination="false"
              row-key="rowKey"
              :scroll="{ x: 1360 }"
            >
              <template #bodyCell="{ column, index, record }">
                <template v-if="column.key === 'enabled'">
                  <Switch v-model:checked="record.enabled" />
                </template>
                <template v-else-if="column.key === 'sort'">
                  <InputNumber
                    v-model:value="record.sort"
                    :min="1"
                    :precision="0"
                    style="width: 72px"
                  />
                </template>
                <template v-else-if="column.key === 'rewardType'">
                  <Select
                    v-model:value="record.rewardType"
                    :options="REWARD_TYPE_OPTIONS"
                    style="width: 100px"
                    @change="(value: string) => handleRewardTypeChange(record, value)"
                  />
                </template>
                <template v-else-if="column.key === 'reward'">
                  <div class="reward-cell">
                    <div v-if="normalizeRewardTypeValue(record.rewardType) === 'RESOURCE'">
                      <Space wrap>
                        <Button size="small" @click="openResourcePicker('rewards', index, record)">
                          {{ record.resourceId || record.rewardGroupId ? '更换资源' : '选择资源' }}
                        </Button>
                        <Button
                          v-if="record.resourceId || record.rewardGroupId"
                          danger
                          size="small"
                          type="link"
                          @click="clearResource(record)"
                        >
                          清空
                        </Button>
                      </Space>
                      <div class="resource-summary">
                        <div
                          v-if="record.coverUrl"
                          class="cover-thumb"
                          :style="coverStyle(record.coverUrl)"
                        />
                        <div>
                          <div class="reward-title">
                            {{ resourceDisplayName(record) }}
                            <span v-if="record.resourceId || record.rewardGroupId">
                              ID: {{ record.resourceId || record.rewardGroupId }}
                            </span>
                            <span v-if="record.resourceType">{{ record.resourceType }}</span>
                          </div>
                          <InputNumber
                            v-model:value="record.durationDays"
                            :min="1"
                            :precision="0"
                            addon-after="天"
                            style="width: 130px"
                          />
                          <InputNumber
                            v-model:value="record.displayGoldAmount"
                            :min="1"
                            :precision="0"
                            addon-after="金币"
                            placeholder="展示价格"
                            style="width: 160px"
                          />
                        </div>
                      </div>
                    </div>
                    <div v-else class="gold-row">
                      <InputNumber
                        v-model:value="record.goldAmount"
                        :min="1"
                        :precision="0"
                        addon-after="金币"
                        style="width: 160px"
                      />
                    </div>
                    <div class="asset-grid">
                      <div class="asset-preview">
                        <div
                          v-if="record.coverUrl"
                          class="cover-thumb"
                          :style="coverStyle(record.coverUrl)"
                        />
                        <Input
                          v-model:value="record.coverUrl"
                          allow-clear
                          placeholder="封面图 URL"
                          style="width: 360px"
                        />
                      </div>
                      <div class="asset-preview">
                        <div
                          v-if="record.animationUrl"
                          class="cover-thumb"
                          :style="coverStyle(record.animationUrl)"
                        />
                        <Input
                          v-model:value="record.animationUrl"
                          allow-clear
                          placeholder="动态图 URL"
                          style="width: 360px"
                        />
                      </div>
                    </div>
                  </div>
                </template>
                <template v-else-if="column.key === 'probability'">
                  {{ probabilityText(autoProbabilityForRow('rewards', index, record)) }}
                </template>
                <template v-else-if="column.key === 'actions'">
                  <Button danger type="link" @click="confirmRemoveReward(index)">删除</Button>
                </template>
              </template>
            </Table>

            <div class="actions">
              <Button @click="addReward('rewards')">普通池新增奖励</Button>
            </div>

            <div class="section-title">新人奖池</div>
            <Table
              class="reward-table"
              :columns="rewardColumns"
              :data-source="form.newbieRewards"
              :loading="loading"
              :pagination="false"
              row-key="rowKey"
              :scroll="{ x: 1360 }"
            >
              <template #bodyCell="{ column, index, record }">
                <template v-if="column.key === 'enabled'">
                  <Switch v-model:checked="record.enabled" />
                </template>
                <template v-else-if="column.key === 'sort'">
                  <InputNumber
                    v-model:value="record.sort"
                    :min="1"
                    :precision="0"
                    style="width: 72px"
                  />
                </template>
                <template v-else-if="column.key === 'rewardType'">
                  <Select
                    v-model:value="record.rewardType"
                    :options="REWARD_TYPE_OPTIONS"
                    style="width: 100px"
                    @change="(value: string) => handleRewardTypeChange(record, value)"
                  />
                </template>
                <template v-else-if="column.key === 'reward'">
                  <div class="reward-cell">
                    <div v-if="normalizeRewardTypeValue(record.rewardType) === 'RESOURCE'">
                      <Space wrap>
                        <Button
                          size="small"
                          @click="openResourcePicker('newbieRewards', index, record)"
                        >
                          {{ record.resourceId || record.rewardGroupId ? '更换资源' : '选择资源' }}
                        </Button>
                        <Button
                          v-if="record.resourceId || record.rewardGroupId"
                          danger
                          size="small"
                          type="link"
                          @click="clearResource(record)"
                        >
                          清空
                        </Button>
                      </Space>
                      <div class="resource-summary">
                        <div
                          v-if="record.coverUrl"
                          class="cover-thumb"
                          :style="coverStyle(record.coverUrl)"
                        />
                        <div>
                          <div class="reward-title">
                            {{ resourceDisplayName(record) }}
                            <span v-if="record.resourceId || record.rewardGroupId">
                              ID: {{ record.resourceId || record.rewardGroupId }}
                            </span>
                            <span v-if="record.resourceType">{{ record.resourceType }}</span>
                          </div>
                          <InputNumber
                            v-model:value="record.durationDays"
                            :min="1"
                            :precision="0"
                            addon-after="天"
                            style="width: 130px"
                          />
                          <InputNumber
                            v-model:value="record.displayGoldAmount"
                            :min="1"
                            :precision="0"
                            addon-after="金币"
                            placeholder="展示价格"
                            style="width: 160px"
                          />
                        </div>
                      </div>
                    </div>
                    <div v-else class="gold-row">
                      <InputNumber
                        v-model:value="record.goldAmount"
                        :min="1"
                        :precision="0"
                        addon-after="金币"
                        style="width: 160px"
                      />
                    </div>
                    <div class="asset-grid">
                      <div class="asset-preview">
                        <div
                          v-if="record.coverUrl"
                          class="cover-thumb"
                          :style="coverStyle(record.coverUrl)"
                        />
                        <Input
                          v-model:value="record.coverUrl"
                          allow-clear
                          placeholder="封面图 URL"
                          style="width: 360px"
                        />
                      </div>
                      <div class="asset-preview">
                        <div
                          v-if="record.animationUrl"
                          class="cover-thumb"
                          :style="coverStyle(record.animationUrl)"
                        />
                        <Input
                          v-model:value="record.animationUrl"
                          allow-clear
                          placeholder="动态图 URL"
                          style="width: 360px"
                        />
                      </div>
                    </div>
                  </div>
                </template>
                <template v-else-if="column.key === 'probability'">
                  {{ probabilityText(autoProbabilityForRow('newbieRewards', index, record)) }}
                </template>
                <template v-else-if="column.key === 'actions'">
                  <Button danger type="link" @click="confirmRemoveReward(index, 'newbieRewards')">
                    删除
                  </Button>
                </template>
              </template>
            </Table>

            <div class="actions">
              <Button @click="addReward('newbieRewards')">新人池新增奖励</Button>
              <Button :loading="saving" type="primary" @click="submitForm">保存配置</Button>
            </div>
          </TabPane>

          <TabPane key="records" tab="抽奖记录">
            <div class="toolbar">
              <Space wrap>
                <Input
                  v-model:value="recordQuery.userId"
                  allow-clear
                  placeholder="用户ID"
                  style="width: 170px"
                />
                <Select
                  v-model:value="recordQuery.status"
                  allow-clear
                  :options="[
                    { label: '成功', value: 'SUCCESS' },
                    { label: '失败', value: 'FAILED' },
                    { label: '处理中', value: 'PENDING' },
                  ]"
                  placeholder="状态"
                  style="width: 130px"
                />
                <RangePicker
                  v-model:value="recordRangeDate"
                  show-time
                  style="width: 380px"
                />
                <Button :loading="recordLoading" type="primary" @click="handleRecordSearch">
                  查询
                </Button>
              </Space>
            </div>

            <div class="record-summary">
              <div class="record-summary-item">
                <span>金币总消耗</span>
                <strong>{{ numberText(recordSummary.totalPaidGold) }}</strong>
              </div>
              <div class="record-summary-item">
                <span>金币总返还</span>
                <strong>{{ numberText(recordSummary.totalRewardGold) }}</strong>
              </div>
              <div class="record-summary-item">
                <span>返还比例</span>
                <strong>{{ summaryRatioText() }}</strong>
              </div>
              <div class="record-summary-item record-summary-time">
                <span>统计时间</span>
                <strong>{{ recordSummary.startTime || '-' }} 至 {{ recordSummary.endTime || '-' }}</strong>
              </div>
            </div>

            <Table
              :columns="recordColumns"
              :data-source="recordPage.records"
              :loading="recordLoading"
              :pagination="{
                current: recordPage.current,
                pageSize: recordPage.size,
                showSizeChanger: true,
                total: recordPage.total,
              }"
              row-key="id"
              :scroll="{ x: 1560 }"
              @change="handleRecordTableChange"
            >
              <template #bodyCell="{ column, record }">
                <template v-if="column.key === 'reward'">
                  <div class="record-reward">
                    <div
                      v-if="record.coverUrl"
                      class="cover-thumb"
                      :style="coverStyle(record.coverUrl)"
                    />
                    <div>
                      <div>{{ rewardRecordName(record) }}</div>
                      <div class="sub-text">
                        {{ record.rewardType || '-' }}
                        <span v-if="record.durationDays"> / {{ record.durationDays }} 天</span>
                        <span v-if="record.displayGoldAmount">
                          / 展示价 {{ Number(record.displayGoldAmount || 0).toLocaleString() }}
                        </span>
                      </div>
                    </div>
                  </div>
                </template>
                <template v-else-if="column.key === 'poolType'">
                  <Tag :color="record.poolType === 'NEWBIE' ? 'processing' : 'default'">
                    {{ record.poolType === 'NEWBIE' ? '新人' : '普通' }}
                  </Tag>
                </template>
                <template v-else-if="column.key === 'probability'">
                  {{ probabilityText(record.probability) }}
                </template>
                <template v-else-if="column.key === 'status'">
                  <Tag :color="statusColor(record.status)">{{ record.status || '-' }}</Tag>
                </template>
                <template v-else-if="column.key === 'errorMessage'">
                  {{ record.errorMessage || '-' }}
                </template>
              </template>
            </Table>
          </TabPane>
        </Tabs>
      </Card>

      <PropsSourceSelectDrawer
        :default-type="
          pickerRewardRecord?.resourceType ||
          (form[pickerPool] || [])[pickerRewardIndex]?.resourceType ||
          'AVATAR_FRAME'
        "
        :open="resourcePickerOpen"
        :sys-origin="selectedSysOrigin"
        @close="closeResourcePicker"
        @select="handleResourceSelect"
      />
    </Spin>
  </Page>
</template>

<style scoped>
.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 16px;
}

.asset-grid {
  display: grid;
  gap: 8px;
  margin-top: 10px;
}

.asset-preview {
  align-items: center;
  display: flex;
  gap: 10px;
}

.config-row {
  margin-bottom: 16px;
}

.cover-thumb {
  background-position: center;
  background-repeat: no-repeat;
  background-size: contain;
  border: 1px solid rgb(226 232 240);
  border-radius: 6px;
  flex: 0 0 auto;
  height: 48px;
  width: 48px;
}

.field-label {
  color: rgb(51 65 85);
  font-weight: 600;
}

.record-reward {
  align-items: center;
  display: flex;
  gap: 10px;
}

.record-summary {
  display: grid;
  gap: 10px;
  grid-template-columns: repeat(4, minmax(160px, 1fr));
  margin-bottom: 16px;
}

.record-summary-item {
  background: rgb(248 250 252);
  border: 1px solid rgb(226 232 240);
  border-radius: 6px;
  padding: 12px 14px;
}

.record-summary-item span {
  color: rgb(100 116 139);
  display: block;
  font-size: 12px;
  margin-bottom: 4px;
}

.record-summary-item strong {
  color: rgb(15 23 42);
  font-size: 20px;
  font-weight: 700;
}

.record-summary-time {
  min-width: 280px;
}

.record-summary-time strong {
  font-size: 13px;
}

.resource-summary {
  align-items: center;
  display: flex;
  gap: 10px;
  margin-top: 8px;
}

.reward-cell {
  min-width: 560px;
}

.reward-table {
  margin-top: 18px;
}

.reward-title {
  color: rgb(15 23 42);
  font-weight: 600;
  margin-bottom: 6px;
}

.reward-title span {
  color: rgb(100 116 139);
  font-size: 12px;
  font-weight: 400;
  margin-left: 8px;
}

.section-title {
  color: rgb(15 23 42);
  font-weight: 600;
  margin: 22px 0 10px;
}

.sub-text {
  color: rgb(100 116 139);
  font-size: 12px;
}

.toolbar {
  margin-bottom: 16px;
}
</style>
