<template>
  <div class="app-container aslan-game-king">
    <div class="filter-container">
      <el-button class="filter-item" type="primary" icon="el-icon-plus" @click="openCreate">
        新建活动
      </el-button>
      <el-button class="filter-item" icon="el-icon-refresh" :loading="listLoading" @click="loadActivities">
        刷新
      </el-button>
      <el-alert
        class="page-tip"
        type="info"
        :closable="false"
        show-icon
        title="消费金额、抽奖次数和排行榜均以后端金币流水为准；活动开始后，每次抽奖金币数、开始时间、平台及事件白名单不可修改。"
      />
    </div>

    <el-table v-loading="listLoading" :data="activities" border fit highlight-current-row>
      <el-table-column label="活动" min-width="220">
        <template slot-scope="scope">
          <div class="primary-text">{{ scope.row.activityName }}</div>
          <div class="secondary-text">{{ scope.row.activityCode }}</div>
          <div class="secondary-text">ID: {{ scope.row.id }}</div>
        </template>
      </el-table-column>
      <el-table-column label="平台 / 时区" min-width="135" align="center">
        <template slot-scope="scope">
          <div>{{ scope.row.sysOrigin }}</div>
          <div class="secondary-text">{{ scope.row.timeZone || 'Asia/Riyadh' }}</div>
        </template>
      </el-table-column>
      <el-table-column label="活动时间" min-width="205" align="center">
        <template slot-scope="scope">
          <div>{{ formatTime(scope.row.startTime) }}</div>
          <div>{{ formatTime(scope.row.endTime) }}</div>
        </template>
      </el-table-column>
      <el-table-column label="抽奖门槛" min-width="125" align="right">
        <template slot-scope="scope">
          每 {{ formatNumber(scope.row.coinPerDraw) }} 金币
        </template>
      </el-table-column>
      <el-table-column label="精确事件白名单" min-width="220">
        <template slot-scope="scope">
          <el-tag
            v-for="eventType in scope.row.eventTypes || []"
            :key="eventType"
            class="event-tag"
            size="mini"
          >
            {{ eventType }}
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column label="状态" min-width="130" align="center">
        <template slot-scope="scope">
          <el-tag :type="activityStatusTag(activityStatus(scope.row))">
            {{ activityStatusText(activityStatus(scope.row)) }}
          </el-tag>
          <div class="settlement-status">结算：{{ settlementStatusText(scope.row.settlementStatus) }}</div>
          <div class="secondary-text">可结算：{{ formatTime(scope.row.settlementTime) }}</div>
        </template>
      </el-table-column>
      <el-table-column label="启用" width="85" align="center">
        <template slot-scope="scope">
          <el-switch
            v-model="scope.row.enabled"
            :disabled="hasStarted(scope.row)"
            @change="changeEnabled(scope.row)"
          />
        </template>
      </el-table-column>
      <el-table-column label="操作" min-width="350" align="center" fixed="right">
        <template slot-scope="scope">
          <el-button type="text" @click="openEdit(scope.row)">配置</el-button>
          <el-button type="text" @click="openDrawRecords(scope.row)">抽奖发放</el-button>
          <el-button type="text" @click="openSettlements(scope.row)">结算记录</el-button>
          <el-button
            type="text"
            :disabled="scope.row.settlementStatus !== 'NOT_STARTED'"
            @click="openBackfill(scope.row)"
          >
            消费补数
          </el-button>
        </template>
      </el-table-column>
    </el-table>

    <el-dialog
      :title="form.id ? '编辑 Aslan 游戏王活动' : '新建 Aslan 游戏王活动'"
      :visible.sync="editorVisible"
      width="1180px"
      top="4vh"
      :close-on-click-modal="false"
      @closed="resetEditor"
    >
      <div v-loading="editorLoading" class="editor-body">
        <el-alert
          v-if="startedLocked"
          type="warning"
          :closable="false"
          show-icon
          title="后端判定活动已经开始：统计、结算、启用状态、七个奖项和六档排行奖励均已锁定；仅名称与说明可维护。"
        />

        <div class="section-title">基础配置</div>
        <el-form ref="activityForm" :model="form" :rules="formRules" label-width="135px">
          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item label="活动编码" prop="activityCode">
                <el-input
                  v-model.trim="form.activityCode"
                  maxlength="64"
                  show-word-limit
                  :disabled="startedLocked"
                  placeholder="例如 ASLAN_GAME_KING_S2"
                />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="活动名称" prop="activityName">
                <el-input v-model.trim="form.activityName" maxlength="128" show-word-limit />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="所属平台" prop="sysOrigin">
                <el-select v-model="form.sysOrigin" style="width: 100%" :disabled="startedLocked" filterable>
                  <el-option
                    v-for="item in permissionsSysOriginPlatforms"
                    :key="item.value"
                    :label="item.label"
                    :value="item.value"
                  />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="活动时区" prop="timeZone">
                <el-select v-model="form.timeZone" style="width: 100%" filterable :disabled="startedLocked">
                  <el-option v-for="item in timeZoneOptions" :key="item" :label="item" :value="item" />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="活动时间" prop="timeRange">
                <el-date-picker
                  v-model="form.timeRange"
                  type="datetimerange"
                  value-format="timestamp"
                  style="width: 100%"
                  range-separator="至"
                  start-placeholder="开始时间"
                  end-placeholder="结束时间"
                  :disabled="startedLocked"
                />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="每次抽奖金币数" prop="coinPerDraw">
                <el-input-number
                  v-model="form.coinPerDraw"
                  :min="1"
                  :max="999999999999"
                  :precision="0"
                  controls-position="right"
                  style="width: 100%"
                  :disabled="startedLocked"
                />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="结算等待（分钟）" prop="settlementDelayMinutes">
                <el-input-number
                  v-model="form.settlementDelayMinutes"
                  :min="0"
                  :max="1440"
                  :precision="0"
                  controls-position="right"
                  style="width: 100%"
                  :disabled="startedLocked"
                />
                <div class="form-help">活动结束后继续等待钱包异步流水到达，再冻结最终榜单；默认 30 分钟。</div>
              </el-form-item>
            </el-col>
            <el-col :span="24">
              <el-form-item label="精确事件白名单" prop="eventTypes">
                <el-select
                  v-model="form.eventTypes"
                  multiple
                  filterable
                  allow-create
                  default-first-option
                  style="width: 100%"
                  :disabled="startedLocked"
                  placeholder="输入钱包流水的完整 eventType 后回车，例如 HOT_GAME_123；不支持前缀和通配符"
                />
                <div class="form-help">
                  这里只做精确等值匹配。第三方游戏通常包含游戏 ID，请从真实金币支出流水复制完整 eventType，避免把礼物或其他支出计入活动。
                </div>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="排行口径">
                <el-input value="消费金币榜（TYCOON）" disabled />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="排行周期">
                <el-input value="活动总榜（OVERALL）" disabled />
              </el-form-item>
            </el-col>
            <el-col :span="24">
              <el-form-item label="活动说明">
                <el-input v-model.trim="form.activityDesc" type="textarea" :rows="3" maxlength="500" show-word-limit />
              </el-form-item>
            </el-col>
          </el-row>
        </el-form>

        <div class="section-title">抽奖奖项（固定 7 个且必须全部启用）</div>
        <el-alert
          type="info"
          :closable="false"
          show-icon
          title="权重只表示相对概率；总权重必须大于 0。库存 -1 表示不限库存，0 表示不可再抽中。"
        />
        <el-table :data="form.prizes" border class="config-table">
          <el-table-column label="顺序" width="70" align="center" prop="sortOrder" />
          <el-table-column label="启用" width="75" align="center">
            <template slot-scope="scope">
              <el-switch v-model="scope.row.enabled" :disabled="startedLocked" />
            </template>
          </el-table-column>
          <el-table-column label="奖项名称" min-width="160">
            <template slot-scope="scope">
              <el-input v-model.trim="scope.row.prizeName" maxlength="128" placeholder="必填" :disabled="startedLocked" />
            </template>
          </el-table-column>
          <el-table-column label="奖项图片" min-width="175" align="center">
            <template slot-scope="scope">
              <el-image
                v-if="startedLocked"
                class="readonly-prize-image"
                :src="scope.row.prizeImage"
                fit="contain"
              />
              <upload-image
                v-else
                v-model="scope.row.prizeImage"
                file-dir="activity/game-king"
                tips="建议透明 PNG"
              />
            </template>
          </el-table-column>
          <el-table-column label="权重" min-width="120">
            <template slot-scope="scope">
              <el-input-number v-model="scope.row.weight" :min="1" :max="999999999" :precision="0" controls-position="right" :disabled="startedLocked" />
            </template>
          </el-table-column>
          <el-table-column label="库存" min-width="120">
            <template slot-scope="scope">
              <el-input-number v-model="scope.row.stock" :min="-1" :max="999999999" :precision="0" controls-position="right" :disabled="startedLocked" />
            </template>
          </el-table-column>
          <el-table-column label="奖励资源组" min-width="190">
            <template slot-scope="scope">
              <el-button type="text" :disabled="startedLocked" @click="selectResourceGroup('prize', scope.$index)">
                {{ scope.row.resourceGroupId ? `资源组 ${scope.row.resourceGroupId}` : '选择资源组' }}
              </el-button>
              <props-row v-if="scope.row.rewards && scope.row.rewards.length" :list="scope.row.rewards" />
            </template>
          </el-table-column>
        </el-table>
        <div class="weight-summary">当前总权重：{{ totalPrizeWeight }}</div>

        <div class="section-title">排行榜结算奖励（固定六档）</div>
        <el-alert
          type="warning"
          :closable="false"
          show-icon
          title="名次范围不可增删或修改；活动结束后按最终消费榜快照结算，失败记录可在结算记录中单独重试。"
        />
        <el-table :data="form.rankRewards" border class="config-table">
          <el-table-column label="名次范围" width="130" align="center">
            <template slot-scope="scope">
              <el-tag type="success">{{ rankRangeText(scope.row) }}</el-tag>
            </template>
          </el-table-column>
          <el-table-column label="奖励名称" min-width="220">
            <template slot-scope="scope">
              <el-input v-model.trim="scope.row.rewardName" maxlength="128" placeholder="例如 Top 1 奖励" :disabled="startedLocked" />
            </template>
          </el-table-column>
          <el-table-column label="奖励资源组" min-width="360">
            <template slot-scope="scope">
              <el-button type="text" :disabled="startedLocked" @click="selectResourceGroup('rank', scope.$index)">
                {{ scope.row.resourceGroupId ? `资源组 ${scope.row.resourceGroupId}` : '选择资源组' }}
              </el-button>
              <props-row v-if="scope.row.rewards && scope.row.rewards.length" :list="scope.row.rewards" />
            </template>
          </el-table-column>
        </el-table>
      </div>

      <span slot="footer">
        <el-button @click="editorVisible = false">取消</el-button>
        <el-button type="primary" :loading="saveLoading" @click="submitActivity">保存全部配置</el-button>
      </span>
    </el-dialog>

    <el-dialog
      :title="`${selectedActivity.activityName || ''} - 结算记录`"
      :visible.sync="settlementsVisible"
      width="1120px"
      top="6vh"
      :close-on-click-modal="false"
    >
      <div class="dialog-actions">
        <el-button icon="el-icon-refresh" :loading="settlementsLoading" @click="loadSettlements">刷新</el-button>
        <el-button
          type="danger"
          icon="el-icon-s-check"
          :disabled="!settlementReady(selectedActivity)"
          :loading="settleLoading"
          @click="manualSettle"
        >
          手工结算
        </el-button>
        <span class="form-help">到达“结束时间 + 结算等待”后才可执行；UNKNOWN 必须按奖励项 ID 核账，禁止直接重发。</span>
      </div>
      <el-table v-loading="settlementsLoading" :data="settlementRecords" border max-height="570">
        <el-table-column type="expand" width="50">
          <template slot-scope="scope">
            <el-table :data="scope.row.deliveryItems || []" border size="mini" class="delivery-item-table">
              <el-table-column label="奖励项 ID" min-width="145" prop="id" />
              <el-table-column label="类型" min-width="115">
                <template slot-scope="itemScope">
                  {{ itemScope.row.rewardType }} / {{ itemScope.row.detailType || '-' }}
                </template>
              </el-table-column>
              <el-table-column label="内容" min-width="160" show-overflow-tooltip prop="content" />
              <el-table-column label="数量" width="80" align="right" prop="quantity" />
              <el-table-column label="状态" width="100" align="center">
                <template slot-scope="itemScope">
                  <el-tag :type="deliveryStatusTag(itemScope.row.deliveryStatus)">{{ itemScope.row.deliveryStatus }}</el-tag>
                </template>
              </el-table-column>
              <el-table-column label="重试" width="70" align="center" prop="retryCount" />
              <el-table-column label="失败原因" min-width="180" show-overflow-tooltip prop="failureReason" />
              <el-table-column label="发放时间" min-width="165" align="center">
                <template slot-scope="itemScope">{{ formatTime(itemScope.row.deliverTime) }}</template>
              </el-table-column>
              <el-table-column label="UNKNOWN 核账" min-width="185" align="center" fixed="right">
                <template slot-scope="itemScope">
                  <template v-if="itemScope.row.deliveryStatus === 'UNKNOWN'">
                    <el-button
                      type="text"
                      :loading="resolvingDeliveryItemId === itemScope.row.id"
                      @click="resolveUnknownDeliveryItem(itemScope.row, true)"
                    >
                      已到账
                    </el-button>
                    <el-button
                      type="text"
                      class="danger-link"
                      :loading="resolvingDeliveryItemId === itemScope.row.id"
                      @click="resolveUnknownDeliveryItem(itemScope.row, false)"
                    >
                      未到账并补发
                    </el-button>
                  </template>
                </template>
              </el-table-column>
            </el-table>
          </template>
        </el-table-column>
        <el-table-column label="名次" width="70" align="center" prop="rank" />
        <el-table-column label="用户 ID" min-width="160" prop="userId" />
        <el-table-column label="消费金币" min-width="120" align="right">
          <template slot-scope="scope">{{ formatNumber(scope.row.totalConsumed) }}</template>
        </el-table-column>
        <el-table-column label="资源组" min-width="145" prop="resourceGroupId" />
        <el-table-column label="发放状态" width="110" align="center">
          <template slot-scope="scope">
            <el-tag :type="deliveryStatusTag(scope.row.deliveryStatus)">{{ scope.row.deliveryStatus }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="重试次数" width="90" align="center" prop="retryCount" />
        <el-table-column label="失败原因" min-width="210" show-overflow-tooltip prop="failureReason" />
        <el-table-column label="发放时间" min-width="165" align="center">
          <template slot-scope="scope">{{ formatTime(scope.row.deliverTime) }}</template>
        </el-table-column>
        <el-table-column label="操作" width="90" align="center" fixed="right">
          <template slot-scope="scope">
            <el-button
              v-if="scope.row.deliveryStatus === 'FAILED'"
              type="text"
              :loading="retryingRecordId === scope.row.id"
              @click="retrySettlement(scope.row)"
            >
              重试
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-dialog>

    <el-dialog
      :title="`${selectedActivity.activityName || ''} - 抽奖发放记录`"
      :visible.sync="drawRecordsVisible"
      width="1120px"
      top="6vh"
      :close-on-click-modal="false"
    >
      <div class="dialog-actions">
        <el-select v-model="drawDeliveryStatus" clearable placeholder="全部发放状态" @change="loadDrawRecords">
          <el-option label="待发放" value="PENDING" />
          <el-option label="发放中" value="PROCESSING" />
          <el-option label="成功" value="SUCCESS" />
          <el-option label="失败" value="FAILED" />
          <el-option label="结果未知（需核账）" value="UNKNOWN" />
        </el-select>
        <el-button icon="el-icon-refresh" :loading="drawRecordsLoading" @click="loadDrawRecords">刷新</el-button>
        <span class="form-help">仅 FAILED 可重试；UNKNOWN 表示调用结果不确定，必须按奖励项 ID 核账，页面不会自动重发。</span>
      </div>
      <el-table v-loading="drawRecordsLoading" :data="drawRecords" border max-height="570">
        <el-table-column type="expand" width="50">
          <template slot-scope="scope">
            <el-table :data="scope.row.deliveryItems || []" border size="mini" class="delivery-item-table">
              <el-table-column label="奖励项 ID" min-width="145" prop="id" />
              <el-table-column label="类型" min-width="115">
                <template slot-scope="itemScope">
                  {{ itemScope.row.rewardType }} / {{ itemScope.row.detailType || '-' }}
                </template>
              </el-table-column>
              <el-table-column label="内容" min-width="160" show-overflow-tooltip prop="content" />
              <el-table-column label="数量" width="80" align="right" prop="quantity" />
              <el-table-column label="状态" width="100" align="center">
                <template slot-scope="itemScope">
                  <el-tag :type="deliveryStatusTag(itemScope.row.deliveryStatus)">{{ itemScope.row.deliveryStatus }}</el-tag>
                </template>
              </el-table-column>
              <el-table-column label="重试" width="70" align="center" prop="retryCount" />
              <el-table-column label="失败原因" min-width="180" show-overflow-tooltip prop="failureReason" />
              <el-table-column label="发放时间" min-width="165" align="center">
                <template slot-scope="itemScope">{{ formatTime(itemScope.row.deliverTime) }}</template>
              </el-table-column>
              <el-table-column label="UNKNOWN 核账" min-width="185" align="center" fixed="right">
                <template slot-scope="itemScope">
                  <template v-if="itemScope.row.deliveryStatus === 'UNKNOWN'">
                    <el-button
                      type="text"
                      :loading="resolvingDeliveryItemId === itemScope.row.id"
                      @click="resolveUnknownDeliveryItem(itemScope.row, true)"
                    >
                      已到账
                    </el-button>
                    <el-button
                      type="text"
                      class="danger-link"
                      :loading="resolvingDeliveryItemId === itemScope.row.id"
                      @click="resolveUnknownDeliveryItem(itemScope.row, false)"
                    >
                      未到账并补发
                    </el-button>
                  </template>
                </template>
              </el-table-column>
            </el-table>
          </template>
        </el-table-column>
        <el-table-column label="记录 ID" min-width="150" prop="id" />
        <el-table-column label="用户 ID" min-width="150" prop="userId" />
        <el-table-column label="奖项" min-width="150" prop="prizeName" />
        <el-table-column label="资源组" min-width="145" prop="resourceGroupId" />
        <el-table-column label="发放状态" width="110" align="center">
          <template slot-scope="scope">
            <el-tag :type="deliveryStatusTag(scope.row.deliveryStatus)">{{ scope.row.deliveryStatus }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="失败原因" min-width="210" show-overflow-tooltip prop="failureReason" />
        <el-table-column label="抽奖时间" min-width="165" align="center">
          <template slot-scope="scope">{{ formatTime(scope.row.drawTime) }}</template>
        </el-table-column>
        <el-table-column label="发放时间" min-width="165" align="center">
          <template slot-scope="scope">{{ formatTime(scope.row.deliverTime) }}</template>
        </el-table-column>
        <el-table-column label="操作" width="90" align="center" fixed="right">
          <template slot-scope="scope">
            <el-button
              v-if="scope.row.deliveryStatus === 'FAILED'"
              type="text"
              :loading="retryingDrawRecordId === scope.row.id"
              @click="retryDrawRecord(scope.row)"
            >
              重试
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-dialog>

    <el-dialog
      :title="`${selectedActivity.activityName || ''} - 历史游戏流水补数`"
      :visible.sync="backfillVisible"
      width="620px"
      :close-on-click-modal="false"
    >
      <el-alert
        type="warning"
        :closable="false"
        show-icon
        title="补数按收支类型、单个精确 eventType 和金币流水主键游标执行。每组条件必须分别补到 finished=true，防止共用游标漏数据。"
      />
      <el-form label-width="120px" class="backfill-form">
        <el-form-item label="流水类型">
          <el-select v-model="backfillForm.receiptType" style="width: 100%" @change="resetBackfillCursor">
            <el-option label="游戏消费（Tycoon / 抽奖次数）" :value="1" />
            <el-option label="游戏中奖收入（Victorious）" :value="0" />
          </el-select>
        </el-form-item>
        <el-form-item label="精确 eventType">
          <el-select
            v-model="backfillForm.eventType"
            style="width: 100%"
            filterable
            @change="resetBackfillCursor"
          >
            <el-option
              v-for="item in selectedActivity.eventTypes || []"
              :key="item"
              :label="item"
              :value="item"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="lastId 游标">
          <el-input v-model.trim="backfillForm.lastId" placeholder="首次留空；后续自动回填 nextLastId" />
        </el-form-item>
        <el-form-item label="单批数量">
          <el-input-number v-model="backfillForm.limit" :min="1" :max="500" :precision="0" />
        </el-form-item>
      </el-form>
      <el-descriptions v-if="backfillResult" :column="2" border>
        <el-descriptions-item label="扫描">{{ backfillResult.scanned }}</el-descriptions-item>
        <el-descriptions-item label="计入">{{ backfillResult.accepted }}</el-descriptions-item>
        <el-descriptions-item label="下一游标">{{ backfillResult.nextLastId || '-' }}</el-descriptions-item>
        <el-descriptions-item label="完成">{{ backfillResult.finished ? '是' : '否' }}</el-descriptions-item>
      </el-descriptions>
      <span slot="footer">
        <el-button @click="backfillVisible = false">关闭</el-button>
        <el-button type="primary" :loading="backfillLoading" :disabled="backfillResult && backfillResult.finished" @click="runBackfill">
          执行一批
        </el-button>
      </span>
    </el-dialog>

    <associated-resources
      v-if="resourceSelectorVisible"
      :sys-origin="form.sysOrigin"
      @select="applyResourceGroup"
      @close="resourceSelectorVisible = false"
    />
  </div>
</template>

<script>
import { mapGetters } from 'vuex'
import AssociatedResources from '@/components/data/AssociatedResources'
import PropsRow from '@/components/data/PropsRow'
import UploadImage from '@/components/upload-image'
import {
  backfillAslanGameKingConsumption,
  getAslanGameKingDetail,
  listAslanGameKingActivities,
  listAslanGameKingDrawRecords,
  listAslanGameKingSettlementRecords,
  resolveAslanGameKingUnknownDeliveryItem,
  retryAslanGameKingDraw,
  retryAslanGameKingSettlement,
  saveAslanGameKingActivity,
  setAslanGameKingEnabled,
  settleAslanGameKingActivity
} from '@/api/aslan-game-king'

const REQUIRED_RANK_RANGES = [
  [1, 1],
  [2, 2],
  [3, 3],
  [4, 7],
  [8, 10],
  [11, 30]
]

export default {
  name: 'ActivityGameKing',
  components: { AssociatedResources, PropsRow, UploadImage },
  data() {
    return {
      activities: [],
      listLoading: false,
      editorVisible: false,
      editorLoading: false,
      saveLoading: false,
      serverTime: 0,
      originalStartTime: 0,
      backendActivityStatus: '',
      form: this.emptyForm(),
      formRules: {
        activityCode: [{ required: true, message: '请输入活动编码', trigger: 'blur' }],
        activityName: [{ required: true, message: '请输入活动名称', trigger: 'blur' }],
        sysOrigin: [{ required: true, message: '请选择所属平台', trigger: 'change' }],
        timeZone: [{ required: true, message: '请选择活动时区', trigger: 'change' }],
        timeRange: [{ type: 'array', required: true, len: 2, message: '请选择完整活动时间', trigger: 'change' }],
        coinPerDraw: [{ required: true, message: '请输入每次抽奖金币数', trigger: 'blur' }],
        settlementDelayMinutes: [{ required: true, message: '请输入结算等待分钟数', trigger: 'blur' }],
        eventTypes: [{ type: 'array', required: true, min: 1, message: '至少配置一个精确 eventType', trigger: 'change' }]
      },
      timeZoneOptions: ['Asia/Riyadh', 'Asia/Shanghai', 'UTC'],
      resourceSelectorVisible: false,
      resourceSelection: null,
      selectedActivity: {},
      settlementsVisible: false,
      settlementsLoading: false,
      settleLoading: false,
      settlementRecords: [],
      retryingRecordId: '',
      drawRecordsVisible: false,
      drawRecordsLoading: false,
      drawRecords: [],
      drawDeliveryStatus: '',
      retryingDrawRecordId: '',
      resolvingDeliveryItemId: '',
      backfillVisible: false,
      backfillLoading: false,
      backfillResult: null,
      backfillForm: {
        receiptType: 1,
        eventType: '',
        lastId: '',
        limit: 500
      }
    }
  },
  computed: {
    ...mapGetters(['permissionsSysOriginPlatforms']),
    startedLocked() {
      if (!this.form.id) {
        return false
      }
      // 以详情接口返回的 serverTime/startTime 为最终判定，避免运营电脑时间漂移绕过后端锁定。
      return ['ACTIVE', 'ENDED'].indexOf(this.backendActivityStatus) >= 0 ||
        (this.serverTime > 0 && this.originalStartTime > 0 && this.serverTime >= this.originalStartTime)
    },
    totalPrizeWeight() {
      return this.form.prizes.reduce((total, item) => total + Number(item.weight || 0), 0)
    }
  },
  created() {
    this.loadActivities()
  },
  methods: {
    emptyForm() {
      return {
        id: '',
        activityCode: '',
        activityName: '',
        activityDesc: '',
        sysOrigin: 'ATYOU',
        timeZone: 'Asia/Riyadh',
        timeRange: [],
        coinPerDraw: 1,
        settlementDelayMinutes: 30,
        eventTypes: [],
        rankingType: 'TYCOON',
        rankingPeriod: 'OVERALL',
        enabled: false,
        prizes: this.emptyPrizes(),
        rankRewards: this.emptyRankRewards()
      }
    },
    emptyPrizes() {
      return Array.from({ length: 7 }, (item, index) => ({
        id: '',
        activityId: '',
        prizeName: '',
        prizeImage: '',
        weight: 1,
        stock: -1,
        resourceGroupId: '',
        enabled: true,
        sortOrder: index + 1,
        rewards: []
      }))
    },
    emptyRankRewards() {
      return REQUIRED_RANK_RANGES.map((range, index) => ({
        id: '',
        activityId: '',
        startRank: range[0],
        endRank: range[1],
        resourceGroupId: '',
        rewardName: index < 3 ? `Top ${index + 1} 奖励` : `Top ${range[0]}-${range[1]} 奖励`,
        rewards: []
      }))
    },
    loadActivities() {
      this.listLoading = true
      listAslanGameKingActivities().then(res => {
        this.activities = Array.isArray(res.body) ? res.body : []
      }).finally(() => {
        this.listLoading = false
      })
    },
    openCreate() {
      this.resetEditor()
      const availablePlatforms = this.permissionsSysOriginPlatforms || []
      if (availablePlatforms.length > 0) {
        this.form.sysOrigin = availablePlatforms[0].value
      }
      this.editorVisible = true
    },
    openEdit(row) {
      this.resetEditor()
      this.editorVisible = true
      this.editorLoading = true
      getAslanGameKingDetail(row.id).then(res => {
        const detail = res.body || {}
        const activity = detail.activity || {}
        const prizes = this.mergePrizes(detail.prizes || [])
        const rankRewards = this.mergeRankRewards(detail.rankRewards || [])
        this.form = Object.assign(this.emptyForm(), activity, {
          timeZone: activity.timeZone || 'Asia/Riyadh',
          settlementDelayMinutes: activity.settlementDelayMinutes === null || activity.settlementDelayMinutes === undefined
            ? 30 : Number(activity.settlementDelayMinutes),
          timeRange: [activity.startTime, activity.endTime],
          prizes,
          rankRewards
        })
        this.serverTime = Number(detail.serverTime || 0)
        this.originalStartTime = Number(activity.startTime || 0)
        this.backendActivityStatus = detail.activityStatus || ''
      }).finally(() => {
        this.editorLoading = false
      })
    },
    mergePrizes(prizes) {
      const result = this.emptyPrizes()
      prizes.forEach((item, index) => {
        const targetIndex = Number(item.sortOrder || index + 1) - 1
        if (targetIndex >= 0 && targetIndex < result.length) {
          result.splice(targetIndex, 1, Object.assign({}, result[targetIndex], item, {
            stock: item.stock === null || item.stock === undefined ? -1 : item.stock,
            rewards: item.rewardItems || item.rewards || []
          }))
        }
      })
      return result
    },
    mergeRankRewards(rankRewards) {
      const result = this.emptyRankRewards()
      rankRewards.forEach(item => {
        const index = REQUIRED_RANK_RANGES.findIndex(range => range[0] === Number(item.startRank) && range[1] === Number(item.endRank))
        if (index >= 0) {
          result.splice(index, 1, Object.assign({}, result[index], item, {
            rewards: item.rewardItems || item.rewards || []
          }))
        }
      })
      return result
    },
    resetEditor() {
      this.form = this.emptyForm()
      this.serverTime = 0
      this.originalStartTime = 0
      this.backendActivityStatus = ''
      this.resourceSelectorVisible = false
      this.resourceSelection = null
      if (this.$refs.activityForm) {
        this.$refs.activityForm.clearValidate()
      }
    },
    submitActivity() {
      this.$refs.activityForm.validate(valid => {
        if (!valid || !this.validateConfiguration()) {
          return
        }
        const payload = this.buildSavePayload()
        this.saveLoading = true
        // 基础配置、七个奖项与六档排行奖励一次提交，由后端事务保证不会保存出半套配置。
        saveAslanGameKingActivity(payload).then(() => {
          this.$message.success('活动配置已保存')
          this.editorVisible = false
          this.loadActivities()
        }).finally(() => {
          this.saveLoading = false
        })
      })
    },
    validateConfiguration() {
      const range = this.form.timeRange || []
      if (range.length !== 2 || Number(range[0]) >= Number(range[1])) {
        this.$message.error('活动结束时间必须晚于开始时间')
        return false
      }
      if (!Number.isSafeInteger(Number(this.form.coinPerDraw)) || Number(this.form.coinPerDraw) <= 0) {
        this.$message.error('每次抽奖金币数必须是大于 0 的安全整数')
        return false
      }
      if (!Number.isInteger(Number(this.form.settlementDelayMinutes)) ||
        Number(this.form.settlementDelayMinutes) < 0 || Number(this.form.settlementDelayMinutes) > 1440) {
        this.$message.error('结算等待必须是 0 到 1440 的整数分钟')
        return false
      }
      const eventTypes = (this.form.eventTypes || []).map(item => String(item).trim())
      const invalidEventType = eventTypes.find(item => !item || item.length > 64 || item.indexOf(',') >= 0)
      if (invalidEventType !== undefined || new Set(eventTypes).size !== eventTypes.length) {
        this.$message.error('eventType 必须非空、最长 64 字符、不含逗号且不可重复')
        return false
      }
      // 活动开始后后端只允许更新非统计字段；奖项与排行奖励既不重新校验，也不随保存请求发送。
      if (this.startedLocked) {
        return true
      }
      if (this.form.prizes.length !== 7 || this.form.prizes.some(item => !item.enabled)) {
        this.$message.error('必须且只能配置 7 个启用奖项')
        return false
      }
      const invalidPrize = this.form.prizes.find(item =>
        !item.prizeName || !item.prizeImage || !item.resourceGroupId ||
        !Number.isSafeInteger(Number(item.weight)) || Number(item.weight) <= 0 ||
        !Number.isSafeInteger(Number(item.stock)) || Number(item.stock) < -1
      )
      if (invalidPrize || this.totalPrizeWeight <= 0) {
        this.$message.error('请补全 7 个奖项的名称、图片、正整数权重、合法库存和奖励资源组')
        return false
      }
      const rangesValid = this.form.rankRewards.length === REQUIRED_RANK_RANGES.length &&
        this.form.rankRewards.every((item, index) =>
          Number(item.startRank) === REQUIRED_RANK_RANGES[index][0] &&
          Number(item.endRank) === REQUIRED_RANK_RANGES[index][1] &&
          Boolean(item.resourceGroupId)
        )
      if (!rangesValid) {
        this.$message.error('六档名次范围必须保持固定，并为每档选择奖励资源组')
        return false
      }
      return true
    },
    buildSavePayload() {
      const payload = {
        id: this.form.id || null,
        activityCode: this.form.activityCode.trim(),
        activityName: this.form.activityName.trim(),
        activityDesc: this.form.activityDesc,
        sysOrigin: this.form.sysOrigin,
        timeZone: this.form.timeZone,
        startTime: Number(this.form.timeRange[0]),
        endTime: Number(this.form.timeRange[1]),
        settlementDelayMinutes: Number(this.form.settlementDelayMinutes),
        coinPerDraw: Number(this.form.coinPerDraw),
        eventTypes: this.form.eventTypes.map(item => String(item).trim()),
        rankingType: 'TYCOON',
        rankingPeriod: 'OVERALL',
        enabled: Boolean(this.form.enabled)
      }
      if (!this.startedLocked) {
        payload.prizes = this.form.prizes.map(item => ({
          id: item.id || null,
          activityId: this.form.id || null,
          prizeName: item.prizeName.trim(),
          prizeImage: item.prizeImage,
          weight: Number(item.weight),
          stock: Number(item.stock),
          resourceGroupId: String(item.resourceGroupId),
          enabled: true,
          sortOrder: Number(item.sortOrder)
        }))
        payload.rankRewards = this.form.rankRewards.map(item => ({
          id: item.id || null,
          activityId: this.form.id || null,
          startRank: Number(item.startRank),
          endRank: Number(item.endRank),
          resourceGroupId: String(item.resourceGroupId),
          rewardName: item.rewardName
        }))
      }
      return payload
    },
    selectResourceGroup(type, index) {
      if (this.startedLocked) {
        return
      }
      if (!this.form.sysOrigin) {
        this.$message.warning('请先选择所属平台')
        return
      }
      this.resourceSelection = { type, index }
      this.resourceSelectorVisible = true
    },
    applyResourceGroup(source) {
      if (!this.resourceSelection) {
        return
      }
      const list = this.resourceSelection.type === 'prize' ? this.form.prizes : this.form.rankRewards
      const row = list[this.resourceSelection.index]
      // Long ID 保留为字符串传回 Java，避免 Snowflake ID 在浏览器里发生精度截断。
      row.resourceGroupId = String(source.id)
      row.rewards = source.rewardConfigList || []
      if (this.resourceSelection.type === 'rank' && !row.rewardName) {
        row.rewardName = source.name || ''
      }
      this.resourceSelectorVisible = false
      this.resourceSelection = null
    },
    changeEnabled(row) {
      const enabled = Boolean(row.enabled)
      const action = enabled ? '启用' : '停用'
      this.$confirm(`确认${action}活动「${row.activityName}」？`, '状态确认', { type: 'warning' }).then(() => {
        return setAslanGameKingEnabled(row.id, enabled)
      }).then(() => {
        this.$message.success(`活动已${action}`)
        this.loadActivities()
      }).catch(() => {
        // 确认取消和接口失败都恢复开关，列表状态只能以后端成功响应为准。
        row.enabled = !enabled
      })
    },
    openSettlements(row) {
      this.selectedActivity = row
      this.settlementsVisible = true
      this.loadSettlements()
    },
    loadSettlements() {
      if (!this.selectedActivity.id) {
        return
      }
      this.settlementsLoading = true
      listAslanGameKingSettlementRecords(this.selectedActivity.id).then(res => {
        this.settlementRecords = Array.isArray(res.body) ? res.body : []
      }).finally(() => {
        this.settlementsLoading = false
      })
    },
    manualSettle() {
      this.$confirm('将按活动结束时最终消费榜生成 Top 30 奖励并立即尝试发放，确认继续？', '手工结算', {
        type: 'warning'
      }).then(() => {
        this.settleLoading = true
        return settleAslanGameKingActivity(this.selectedActivity.id)
      }).then(() => {
        this.$message.success('结算任务已执行')
        this.loadSettlements()
        this.loadActivities()
      }).finally(() => {
        this.settleLoading = false
      })
    },
    retrySettlement(row) {
      this.retryingRecordId = row.id
      retryAslanGameKingSettlement(row.id).then(() => {
        this.$message.success('该条奖励已重新发放')
        this.loadSettlements()
      }).finally(() => {
        this.retryingRecordId = ''
      })
    },
    openDrawRecords(row) {
      this.selectedActivity = row
      this.drawDeliveryStatus = ''
      this.drawRecordsVisible = true
      this.loadDrawRecords()
    },
    loadDrawRecords() {
      if (!this.selectedActivity.id) {
        return
      }
      const params = { limit: 200 }
      if (this.drawDeliveryStatus) {
        params.deliveryStatus = this.drawDeliveryStatus
      }
      this.drawRecordsLoading = true
      listAslanGameKingDrawRecords(this.selectedActivity.id, params).then(res => {
        this.drawRecords = Array.isArray(res.body) ? res.body : []
      }).finally(() => {
        this.drawRecordsLoading = false
      })
    },
    retryDrawRecord(row) {
      this.retryingDrawRecordId = row.id
      retryAslanGameKingDraw(row.id).then(() => {
        this.$message.success('该条抽奖奖励已重新发放')
        this.loadDrawRecords()
      }).finally(() => {
        this.retryingDrawRecordId = ''
      })
    },
    resolveUnknownDeliveryItem(item, delivered) {
      const action = delivered ? '确认该奖励项已经到账并标记成功' : '确认该奖励项未到账并立即补发'
      const warning = delivered
        ? '此操作不会再次发奖。请先按奖励项 ID 核对钱包流水或背包记录。'
        : '此操作会真实补发奖励。只有下游核账明确未到账时才能继续，否则可能重复发放。'
      this.$confirm(`${action}？${warning}`, 'UNKNOWN 奖励核账', {
        type: delivered ? 'warning' : 'error',
        confirmButtonText: delivered ? '已核账，标记到账' : '已核账，确认补发'
      }).then(() => {
        this.resolvingDeliveryItemId = item.id
        return resolveAslanGameKingUnknownDeliveryItem(item.id, delivered)
      }).then(() => {
        this.$message.success(delivered ? '已标记该奖励项到账' : '已解锁并执行补发')
        if (this.drawRecordsVisible) {
          this.loadDrawRecords()
        }
        if (this.settlementsVisible) {
          this.loadSettlements()
        }
      }).finally(() => {
        this.resolvingDeliveryItemId = ''
      })
    },
    openBackfill(row) {
      this.selectedActivity = row
      this.backfillForm = {
        receiptType: 1,
        eventType: row.eventTypes && row.eventTypes.length ? row.eventTypes[0] : '',
        lastId: '',
        limit: 500
      }
      this.backfillResult = null
      this.backfillVisible = true
    },
    runBackfill() {
      if (this.backfillForm.receiptType !== 0 && this.backfillForm.receiptType !== 1) {
        this.$message.error('请选择金币流水类型')
        return
      }
      if (!this.backfillForm.eventType) {
        this.$message.error('请选择一个精确 eventType')
        return
      }
      const params = {
        eventType: this.backfillForm.eventType,
        receiptType: this.backfillForm.receiptType,
        limit: Number(this.backfillForm.limit)
      }
      if (this.backfillForm.lastId) {
        params.lastId = this.backfillForm.lastId
      }
      this.backfillLoading = true
      backfillAslanGameKingConsumption(this.selectedActivity.id, params).then(res => {
        this.backfillResult = res.body || {}
        // 游标由服务端返回并按 eventType 独立推进；浏览器不自行计算，避免大整数精度和跳行问题。
        this.backfillForm.lastId = this.backfillResult.nextLastId || this.backfillForm.lastId
        this.$message.success(this.backfillResult.finished ? '该 eventType 已补数完成' : '本批补数完成，请继续下一批')
      }).finally(() => {
        this.backfillLoading = false
      })
    },
    resetBackfillCursor() {
      // lastId 仅在同一 receiptType + eventType 查询条件内有效，切换条件必须从首批重新开始。
      this.backfillForm.lastId = ''
      this.backfillResult = null
    },
    activityStatus(row) {
      if (!row || !row.id) {
        return 'DISABLED'
      }
      if (!row.enabled) {
        return 'DISABLED'
      }
      const now = Date.now()
      if (now < Number(row.startTime)) {
        return 'UPCOMING'
      }
      if (now >= Number(row.endTime)) {
        return 'ENDED'
      }
      return 'ACTIVE'
    },
    hasStarted(row) {
      return Boolean(row && row.startTime && Date.now() >= Number(row.startTime))
    },
    settlementReady(row) {
      // 手工结算只负责首次冻结榜单；PROCESSING/PARTIAL_FAILED 的恢复与 UNKNOWN 核账
      // 走各自专用链路，避免运营把“继续发放”误当成再次生成快照。
      if (!row || !row.id || row.settlementStatus !== 'NOT_STARTED') {
        return false
      }
      const settlementTime = Number(row.settlementTime ||
        (Number(row.endTime) + Number(row.settlementDelayMinutes || 0) * 60 * 1000))
      return Number.isFinite(settlementTime) && Date.now() >= settlementTime
    },
    activityStatusText(status) {
      return {
        DISABLED: '未启用',
        UPCOMING: '待开始',
        ACTIVE: '进行中',
        ENDED: '已结束'
      }[status] || status
    },
    activityStatusTag(status) {
      return {
        DISABLED: 'info',
        UPCOMING: 'warning',
        ACTIVE: 'success',
        ENDED: 'danger'
      }[status] || 'info'
    },
    settlementStatusText(status) {
      return {
        NOT_STARTED: '未结算',
        PROCESSING: '结算中',
        COMPLETED: '已完成',
        PARTIAL_FAILED: '部分失败'
      }[status] || status || '未结算'
    },
    deliveryStatusTag(status) {
      return {
        SUCCESS: 'success',
        FAILED: 'danger',
        UNKNOWN: 'warning',
        PROCESSING: 'warning',
        PENDING: 'info'
      }[status] || 'info'
    },
    rankRangeText(row) {
      return row.startRank === row.endRank ? `Top ${row.startRank}` : `Top ${row.startRank}-${row.endRank}`
    },
    formatTime(value) {
      if (!value) {
        return '-'
      }
      const date = new Date(Number(value))
      if (Number.isNaN(date.getTime())) {
        return '-'
      }
      const pad = number => String(number).padStart(2, '0')
      return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`
    },
    formatNumber(value) {
      if (value === null || value === undefined || value === '') {
        return '-'
      }
      return Number(value).toLocaleString('en-US', { maximumFractionDigits: 2 })
    }
  }
}
</script>

<style scoped lang="scss">
.aslan-game-king {
  .filter-container {
    display: flex;
    align-items: flex-start;
    margin-bottom: 15px;
  }

  .page-tip {
    flex: 1;
    margin-left: 15px;
  }

  .primary-text {
    color: #303133;
    font-weight: 600;
  }

  .secondary-text,
  .form-help {
    color: #909399;
    font-size: 12px;
    line-height: 20px;
  }

  .event-tag {
    margin: 2px 4px 2px 0;
  }

  .settlement-status {
    margin-top: 6px;
    color: #606266;
    font-size: 12px;
  }

  .editor-body {
    max-height: 76vh;
    overflow-y: auto;
    padding: 0 8px 20px;
  }

  .section-title {
    margin: 22px 0 14px;
    padding-left: 10px;
    border-left: 4px solid #409eff;
    color: #303133;
    font-size: 16px;
    font-weight: 600;
    line-height: 22px;
  }

  .config-table {
    margin-top: 12px;
  }

  .weight-summary {
    padding: 10px 5px;
    color: #606266;
    text-align: right;
  }

  .readonly-prize-image {
    width: 72px;
    height: 72px;
  }

  .dialog-actions {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 15px;
  }

  .backfill-form {
    margin-top: 20px;
  }

  .delivery-item-table {
    margin: 8px 0;
  }

  .danger-link {
    color: #f56c6c;
  }
}
</style>
