<template>
  <el-dialog
    v-model="visible"
    title="奖励对照表（dice_reward）权重配比"
    width="900px"
    align-center
    :close-on-click-modal="false"
    @close="handleClose"
  >
    <div class="global-tip">
      编辑的是<strong>奖励对照表（dice_reward / DiceReward 模型）</strong>的权重，按<strong>结束索引（end_index）</strong>区分
      <strong>顺时针</strong>与<strong>逆时针</strong>两套权重；抽奖时按当前方向取对应权重。
    </div>
    <div v-loading="loading" class="dialog-body">
      <el-tabs v-model="activeTier" type="card">
        <el-tab-pane v-for="t in tierKeys" :key="t" :label="t" :name="t">
          <div v-if="getTierItems(t).length === 0" class="empty-tip">该档位暂无配置数据</div>
          <template v-else>
            <div class="chart-wrap" v-if="t !== 'T4' && t !== 'T5'">
              <div class="chart-row">
                <ArtBarChart
                  x-axis-name="结束索引"
                  :x-axis-data="getTierChartLabels(t)"
                  :data="getTierChartData(t, 'clockwise')"
                  height="180px"
                />
                <ArtBarChart
                  x-axis-name="结束索引"
                  :x-axis-data="getTierChartLabels(t)"
                  :data="getTierChartData(t, 'counterclockwise')"
                  height="180px"
                />
              </div>
            </div>
            <div class="weight-sum" v-if="t !== 'T4' && t !== 'T5'">
              当前档位权重合计（顺时针）：<strong>{{ getTierSum(t, 'clockwise') }}</strong>
              ；逆时针：<strong>{{ getTierSum(t, 'counterclockwise') }}</strong>
              （各条 1-10000，和不限制）
            </div>
            <div class="weight-sum weight-sum-t4t5" v-else>T4、T5 仅单一结果，无需配置权重。</div>
            <el-table :data="getTierItems(t)" border size="small" class="weight-table">
              <el-table-column label="结束索引(id)" prop="id" width="90" align="center" show-overflow-tooltip />
              <el-table-column label="色子点数" prop="grid_number" width="80" align="center" />
              <el-table-column label="实际中奖金额" prop="real_ev" width="90" align="center" show-overflow-tooltip />
              <el-table-column label="显示文本" prop="ui_text" min-width="70" align="center" show-overflow-tooltip />
              <el-table-column label="备注" prop="remark" min-width="70" align="center" show-overflow-tooltip />
              <el-table-column label="顺时针权重(direction=0)" min-width="160" align="center">
                <template #default="{ row }">
                  <div class="weight-cell-vertical">
                    <div class="weight-slider-wrap">
                      <el-slider
                        :model-value="getItemWeight(row, 'clockwise')"
                        :min="1"
                        :max="10000"
                        :step="1"
                        size="small"
                        :disabled="isWeightDisabled(row, t)"
                        class="weight-slider"
                        @update:model-value="
                          (v: number | number[]) =>
                            setItemWeightByRow(t, row, 'clockwise', Array.isArray(v) ? (v[0] ?? 1) : (v ?? 1))
                        "
                      />
                    </div>
                    <div class="weight-input-wrap">
                      <el-button
                        type="primary"
                        link
                        :disabled="isWeightDisabled(row, t) || getItemWeight(row, 'clockwise') <= 1"
                        @click="setItemWeightByRow(t, row, 'clockwise', Math.max(1, getItemWeight(row, 'clockwise') - 1))"
                      >－</el-button>
                      <el-input-number
                        :model-value="getItemWeight(row, 'clockwise')"
                        :min="1"
                        :max="10000"
                        :step="1"
                        :disabled="isWeightDisabled(row, t)"
                        controls-position="right"
                        size="small"
                        class="weight-input"
                        @update:model-value="
                          (v: number | string | undefined) =>
                            setItemWeightByRow(
                              t,
                              row,
                              'clockwise',
                              typeof v === 'number' && !Number.isNaN(v) ? v : Number(v) || 1
                            )
                        "
                      />
                      <el-button
                        type="primary"
                        link
                        :disabled="isWeightDisabled(row, t) || getItemWeight(row, 'clockwise') >= 10000"
                        @click="setItemWeightByRow(t, row, 'clockwise', Math.min(10000, getItemWeight(row, 'clockwise') + 1))"
                      >＋</el-button>
                    </div>
                  </div>
                </template>
              </el-table-column>
              <el-table-column label="逆时针权重(direction=1)" min-width="160" align="center">
                <template #default="{ row }">
                  <div class="weight-cell-vertical">
                    <div class="weight-slider-wrap">
                      <el-slider
                        :model-value="getItemWeight(row, 'counterclockwise')"
                        :min="1"
                        :max="10000"
                        :step="1"
                        size="small"
                        :disabled="isWeightDisabled(row, t)"
                        class="weight-slider"
                        @update:model-value="
                          (v: number | number[]) =>
                            setItemWeightByRow(t, row, 'counterclockwise', Array.isArray(v) ? (v[0] ?? 1) : (v ?? 1))
                        "
                      />
                    </div>
                    <div class="weight-input-wrap">
                      <el-button
                        type="primary"
                        link
                        :disabled="isWeightDisabled(row, t) || getItemWeight(row, 'counterclockwise') <= 1"
                        @click="setItemWeightByRow(t, row, 'counterclockwise', Math.max(1, getItemWeight(row, 'counterclockwise') - 1))"
                      >－</el-button>
                      <el-input-number
                        :model-value="getItemWeight(row, 'counterclockwise')"
                        :min="1"
                        :max="10000"
                        :step="1"
                        :disabled="isWeightDisabled(row, t)"
                        controls-position="right"
                        size="small"
                        class="weight-input"
                        @update:model-value="
                          (v: number | string | undefined) =>
                            setItemWeightByRow(
                              t,
                              row,
                              'counterclockwise',
                              typeof v === 'number' && !Number.isNaN(v) ? v : Number(v) || 1
                            )
                        "
                      />
                      <el-button
                        type="primary"
                        link
                        :disabled="isWeightDisabled(row, t) || getItemWeight(row, 'counterclockwise') >= 10000"
                        @click="setItemWeightByRow(t, row, 'counterclockwise', Math.min(10000, getItemWeight(row, 'counterclockwise') + 1))"
                      >＋</el-button>
                    </div>
                  </div>
                </template>
              </el-table-column>
            </el-table>
          </template>
        </el-tab-pane>
      </el-tabs>
    </div>
    <template #footer>
      <el-button @click="handleClose">取消</el-button>
      <el-button type="primary" :loading="submitting" @click="handleSubmit">提交</el-button>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
  import api from '../../../api/reward/index'
  import ArtBarChart from '@/components/core/charts/art-bar-chart/index.vue'
  import { ElMessage } from 'element-plus'

  const TIER_KEYS = ['T1', 'T2', 'T3', 'T4', 'T5'] as const
  /** 供模板 v-for 使用 */
  const tierKeys = TIER_KEYS
  type DirectionKey = 'clockwise' | 'counterclockwise'

  interface WeightRow {
    reward_id_clockwise?: number
    reward_id_counterclockwise?: number
    id?: number
    grid_number?: number
    real_ev?: number
    ui_text?: string
    remark?: string
    tier?: string
    weight_clockwise: number
    weight_counterclockwise: number
  }

  interface Props {
    modelValue: boolean
  }

  interface Emits {
    (e: 'update:modelValue', value: boolean): void
    (e: 'success'): void
  }

  const props = withDefaults(defineProps<Props>(), {
    modelValue: false
  })

  const emit = defineEmits<Emits>()

  const visible = computed({
    get: () => props.modelValue,
    set: (v) => emit('update:modelValue', v)
  })

  const activeTier = ref('T1')
  const submitting = ref(false)
  const loading = ref(false)
  const grouped = ref<Record<string, WeightRow[]>>({
    T1: [],
    T2: [],
    T3: [],
    T4: [],
    T5: []
  })

  function getTierItems(tier: string): WeightRow[] {
    return grouped.value[tier] ?? []
  }

  function getTierChartLabels(tier: string): string[] {
    return getTierItems(tier).map((r) => String(r.grid_number ?? ''))
  }

  function getTierChartData(tier: string, dir: DirectionKey): number[] {
    const key = dir === 'clockwise' ? 'weight_clockwise' : 'weight_counterclockwise'
    return getTierItems(tier).map((r) => toWeightPrecision(r[key] ?? 1))
  }

  function getTierSum(tier: string, dir: DirectionKey): number {
    const key = dir === 'clockwise' ? 'weight_clockwise' : 'weight_counterclockwise'
    return getTierItems(tier).reduce((s, r) => s + toWeightPrecision(r[key] ?? 1), 0)
  }

  function getItemWeight(row: WeightRow, dir: DirectionKey): number {
    const key = dir === 'clockwise' ? 'weight_clockwise' : 'weight_counterclockwise'
    const w = row[key]
    const num = typeof w === 'number' && !Number.isNaN(w) ? w : Number(w)
    if (Number.isNaN(num)) return 1
    return toWeightPrecision(num)
  }

  function toWeightPrecision(value: number): number {
    return Math.max(1, Math.min(10000, Math.floor(value)))
  }

  function setItemWeightByRow(tier: string, row: WeightRow, dir: DirectionKey, value: number) {
    const v = toWeightPrecision(typeof value === 'number' && !Number.isNaN(value) ? value : 1)
    const list = grouped.value[tier]
    if (!list) return
    const key = dir === 'clockwise' ? 'weight_clockwise' : 'weight_counterclockwise'
    const rid =
      dir === 'clockwise' ? row.reward_id_clockwise : row.reward_id_counterclockwise
    const idx = list.findIndex(
      (r) =>
        r === row ||
        (rid != null &&
          (dir === 'clockwise' ? r.reward_id_clockwise : r.reward_id_counterclockwise) === rid)
    )
    if (idx >= 0) list[idx][key] = v
    else row[key] = v
  }

  function isWeightDisabled(row: WeightRow, tier: string): boolean {
    if (tier === 'T4' || tier === 'T5') return true
    return false
  }

  function normalizeWeightValue(v: unknown): number {
    const num = typeof v === 'number' && !Number.isNaN(v) ? v : Number(v)
    if (Number.isNaN(num)) return 1
    return Math.max(1, Math.min(10000, Math.floor(num)))
  }

  /** 兼容接口返回 tier -> { 0: [], 1: [] }，按 grid_number 合并为每档位一行，含 reward_id 与双方向权重 */
  function parsePayload(res: any): Record<string, WeightRow[]> {
    const empty: Record<string, WeightRow[]> = {
      T1: [],
      T2: [],
      T3: [],
      T4: [],
      T5: []
    }
    if (!res || typeof res !== 'object') return empty
    const raw = res?.data ?? res
    if (!raw || typeof raw !== 'object') return empty
    const out = { ...empty }
    for (const t of TIER_KEYS) {
      const tierData = raw[t]
      if (!tierData || typeof tierData !== 'object') continue
      const list0 = Array.isArray(tierData[0]) ? tierData[0] : []
      const list1 = Array.isArray(tierData[1]) ? tierData[1] : []
      const byGrid = new Map<
        number,
        {
          reward_id_clockwise?: number
          reward_id_counterclockwise?: number
          id?: number
          grid_number?: number
          real_ev?: number
          ui_text?: string
          remark?: string
          weight_clockwise: number
          weight_counterclockwise: number
        }
      >()
      for (const r of list0) {
        const gn = r.grid_number != null ? Number(r.grid_number) : NaN
        if (!Number.isNaN(gn)) {
          byGrid.set(gn, {
            reward_id_clockwise: r.reward_id != null ? Number(r.reward_id) : undefined,
            id: r.id != null ? Number(r.id) : undefined,
            grid_number: gn,
            real_ev: r.real_ev,
            ui_text: r.ui_text,
            remark: r.remark,
            weight_clockwise: normalizeWeightValue(r.weight),
            weight_counterclockwise: 1
          })
        }
      }
      for (const r of list1) {
        const gn = r.grid_number != null ? Number(r.grid_number) : NaN
        if (!Number.isNaN(gn)) {
          const cur = byGrid.get(gn)
          if (cur) {
            cur.reward_id_counterclockwise = r.reward_id != null ? Number(r.reward_id) : undefined
            cur.weight_counterclockwise = normalizeWeightValue(r.weight)
          } else {
            byGrid.set(gn, {
              reward_id_counterclockwise: r.reward_id != null ? Number(r.reward_id) : undefined,
              id: r.id != null ? Number(r.id) : undefined,
              grid_number: gn,
              real_ev: r.real_ev,
              ui_text: r.ui_text,
              remark: r.remark,
              weight_clockwise: 1,
              weight_counterclockwise: normalizeWeightValue(r.weight)
            })
          }
        }
      }
      out[t] = Array.from(byGrid.values())
    }
    return out
  }

  function loadData() {
    loading.value = true
    api
      .weightRatioListWithDirection()
      .then((res: any) => {
        grouped.value = parsePayload(res)
      })
      .catch(() => {
        ElMessage.error('获取权重数据失败')
      })
      .finally(() => {
        loading.value = false
      })
  }

  /** 按 DiceReward 主键 id 收集：每条记录一条 { id, weight } */
  function collectItems(): Array<{ id: number; weight: number }> {
    const items: Array<{ id: number; weight: number }> = []
    for (const t of TIER_KEYS) {
      for (const row of getTierItems(t)) {
        const w0 = isWeightDisabled(row, t) ? 10000 : getItemWeight(row, 'clockwise')
        const w1 = isWeightDisabled(row, t) ? 10000 : getItemWeight(row, 'counterclockwise')
        const rid0 = row.reward_id_clockwise != null ? row.reward_id_clockwise : 0
        const rid1 = row.reward_id_counterclockwise != null ? row.reward_id_counterclockwise : 0
        if (rid0 > 0) items.push({ id: rid0, weight: w0 })
        if (rid1 > 0) items.push({ id: rid1, weight: w1 })
      }
    }
    return items
  }

  function handleSubmit() {
    const items = collectItems()
    if (items.length === 0) {
      ElMessage.info('没有可提交的配置')
      return
    }
    submitting.value = true
    api
      .batchUpdateWeights(items)
      .then(() => {
        ElMessage.success('保存成功')
        emit('success')
        handleClose()
      })
      .catch((e: { message?: string }) => {
        ElMessage.error(e?.message ?? '保存失败')
      })
      .finally(() => {
        submitting.value = false
      })
  }

  function handleClose() {
    visible.value = false
  }

  watch(
    () => props.modelValue,
    (open) => {
      if (open) {
        loadData()
        activeTier.value = 'T1'
      }
    }
  )
</script>

<style lang="scss" scoped>
  .chart-wrap {
    margin-bottom: 12px;
  }
  .chart-row {
    display: flex;
    gap: 16px;
    flex-wrap: wrap;
    > * {
      flex: 1;
      min-width: 200px;
    }
  }
  .weight-sum {
    margin-bottom: 12px;
    font-size: 13px;
  }
  .weight-sum-t4t5 {
    color: var(--el-text-color-secondary);
  }
  .global-tip {
    margin-bottom: 12px;
    padding: 10px 12px;
    font-size: 13px;
    color: var(--el-text-color-regular);
    background: var(--el-fill-color-light);
    border-radius: 6px;
    line-height: 1.5;
  }
  .weight-table {
    margin-top: 8px;
  }
  .weight-cell-vertical {
    display: flex;
    flex-direction: column;
    gap: 8px;
    align-items: center;
  }
  .weight-slider-wrap {
    width: 100%;
    min-width: 80px;
    padding: 0 8px;
    :deep(.weight-slider) {
      width: 100%;
    }
  }
  .weight-input-wrap {
    display: flex;
    align-items: center;
    gap: 6px;
  }
  .empty-tip {
    padding: 24px;
    text-align: center;
    color: var(--el-text-color-secondary);
  }
  .dialog-body {
    min-height: 320px;
  }
</style>
