<script setup lang="ts">
import { ElMessage } from 'element-plus'
import { computed, onMounted, ref } from 'vue'

import {
  emptyListingSalePriceConfig,
  emptyListingPublishOptions,
  mergeListingSalePriceConfig,
  mergeListingPublishOptions,
  type ListingPublishOptions,
  type PublishSalePriceConfig,
} from '@/api/listingOptions'
import {
  defaultHomeAnnouncements,
  defaultHomeBanners,
  mergeHomeConfig,
  type HomeBannerSlide,
} from '@/api/homeConfig'
import { uploadAdminFile } from '@/api/files'
import { fetchSystemConfigs, updateSystemConfig, type SystemConfig } from '@/api/systemConfigs'
import { formatDateTime } from '@/utils/time'

const loading = ref(false)
const submitting = ref(false)
const configs = ref<SystemConfig[]>([])
const activeConfig = ref<SystemConfig | null>(null)
const value = ref('')
const description = ref('')
const publishOptionsDraft = ref<ListingPublishOptions>(cloneOptions(emptyListingPublishOptions))
const salePriceConfigDraft = ref<PublishSalePriceConfig>(cloneSalePriceConfig(emptyListingSalePriceConfig))
const homeAnnouncementLines = ref(itemsToLines(defaultHomeAnnouncements))
const homeBannersDraft = ref<HomeBannerSlide[]>(cloneHomeBanners(defaultHomeBanners))
const uploadingBannerIndex = ref<number | null>(null)

const publishConfig = computed(() => configs.value.find((item) => item.key === 'listing.publish_options') || null)
const salePriceConfig = computed(() => configs.value.find((item) => item.key === 'listing.sale_price_config') || null)
const homeAnnouncementsConfig = computed(() => configs.value.find((item) => item.key === 'mobile.home_announcements') || null)
const homeBannersConfig = computed(() => configs.value.find((item) => item.key === 'mobile.home_banners') || null)
const regularConfigs = computed(() =>
  configs.value.filter(
    (item) =>
      item.key !== 'listing.publish_options' &&
      item.key !== 'listing.sale_price_config' &&
      item.key !== 'mobile.home_announcements' &&
      item.key !== 'mobile.home_banners',
  ),
)
const isPublishOptionsConfig = computed(() => activeConfig.value?.key === 'listing.publish_options')
const isSalePriceConfig = computed(() => activeConfig.value?.key === 'listing.sale_price_config')
const isHomeAnnouncementsConfig = computed(() => activeConfig.value?.key === 'mobile.home_announcements')
const isHomeBannersConfig = computed(() => activeConfig.value?.key === 'mobile.home_banners')
const publishStats = computed(() => {
  const options = safeParsePublishOptions(publishConfig.value?.value || '')
  return {
    baseCount:
      options.server_options.length +
      options.rank_options.length +
      options.insurance_options.length +
      options.level_options.length,
    skinCount: options.skin_groups.reduce((sum, group) => sum + group.options.length, 0),
    resourceCount: options.quantity_items.length,
    screenshotCount: options.screenshot_slots.length,
    regionCount: options.region_options.length,
  }
})
const salePriceStats = computed(() => {
  const config = safeParseSalePriceConfig(salePriceConfig.value?.value || '')
  return {
    fixedCount: config.fixed_markup_rules.length,
    ratioCount: config.ratio_adjustment_rules.length,
  }
})
const homeStats = computed(() => {
  const announcements = parseHomeAnnouncements(homeAnnouncementsConfig.value?.value || '', false)
  const banners = parseHomeBanners(homeBannersConfig.value?.value || '', false)
  return {
    announcementCount: announcements.length,
    bannerCount: banners.length,
  }
})

const isStructuredConfig = computed(() => {
  const trimmed = value.value.trim()
  return (
    isPublishOptionsConfig.value ||
    isSalePriceConfig.value ||
    isHomeAnnouncementsConfig.value ||
    isHomeBannersConfig.value ||
    trimmed.startsWith('{') ||
    trimmed.startsWith('[')
  )
})

const dialogWidth = computed(() => {
  if (isPublishOptionsConfig.value || isSalePriceConfig.value || isHomeBannersConfig.value) return '920px'
  if (isHomeAnnouncementsConfig.value) return '680px'
  return '560px'
})

onMounted(loadConfigs)

async function loadConfigs() {
  loading.value = true
  try {
    configs.value = await fetchSystemConfigs()
  } finally {
    loading.value = false
  }
}

function openEdit(row: SystemConfig) {
  activeConfig.value = row
  value.value = row.value
  description.value = row.description
  if (row.key === 'listing.publish_options') {
    publishOptionsDraft.value = parsePublishOptions(row.value)
  }
  if (row.key === 'listing.sale_price_config') {
    salePriceConfigDraft.value = parseSalePriceConfig(row.value)
  }
  if (row.key === 'mobile.home_announcements') {
    homeAnnouncementLines.value = itemsToLines(parseHomeAnnouncements(row.value, true))
  }
  if (row.key === 'mobile.home_banners') {
    homeBannersDraft.value = parseHomeBanners(row.value, true)
  }
}

async function handleSave() {
  if (!activeConfig.value) return
  submitting.value = true
  try {
    if (isPublishOptionsConfig.value) {
      value.value = JSON.stringify(publishOptionsDraft.value, null, 2)
    }
    if (isSalePriceConfig.value) {
      value.value = JSON.stringify(salePriceConfigDraft.value, null, 2)
    }
    if (isHomeAnnouncementsConfig.value) {
      value.value = JSON.stringify(linesToItems(homeAnnouncementLines.value), null, 2)
    }
    if (isHomeBannersConfig.value) {
      value.value = JSON.stringify(
        homeBannersDraft.value.filter((item) => item.title.trim() || item.image_url?.trim()),
        null,
        2,
      )
    }
    await updateSystemConfig(activeConfig.value.key, {
      value: value.value,
      description: description.value,
    })
    ElMessage.success('配置已更新')
    activeConfig.value = null
    await loadConfigs()
  } catch (error) {
    ElMessage.error(readError(error, '保存失败'))
  } finally {
    submitting.value = false
  }
}

function parsePublishOptions(raw: string) {
  try {
    const parsed = raw.trim() ? JSON.parse(raw) : emptyListingPublishOptions
    return cloneOptions(mergeListingPublishOptions(parsed))
  } catch {
    ElMessage.warning('发布选项 JSON 解析失败，已清空草稿')
    return cloneOptions(emptyListingPublishOptions)
  }
}

function safeParsePublishOptions(raw: string) {
  try {
    const parsed = raw.trim() ? JSON.parse(raw) : emptyListingPublishOptions
    return cloneOptions(mergeListingPublishOptions(parsed))
  } catch {
    return cloneOptions(emptyListingPublishOptions)
  }
}

function parseSalePriceConfig(raw: string) {
  try {
    const parsed = raw.trim() ? JSON.parse(raw) : emptyListingSalePriceConfig
    return cloneSalePriceConfig(mergeListingSalePriceConfig(parsed))
  } catch {
    ElMessage.warning('出售定价规则 JSON 解析失败，已清空草稿')
    return cloneSalePriceConfig(emptyListingSalePriceConfig)
  }
}

function safeParseSalePriceConfig(raw: string) {
  try {
    const parsed = raw.trim() ? JSON.parse(raw) : emptyListingSalePriceConfig
    return cloneSalePriceConfig(mergeListingSalePriceConfig(parsed))
  } catch {
    return cloneSalePriceConfig(emptyListingSalePriceConfig)
  }
}

function parseHomeAnnouncements(raw: string, showWarning = false) {
  try {
    const parsed = raw.trim() ? JSON.parse(raw) : defaultHomeAnnouncements
    return mergeHomeConfig({ announcements: Array.isArray(parsed) ? parsed : [] }).announcements
  } catch {
    if (showWarning) ElMessage.warning('首页公告 JSON 解析失败，已使用默认配置')
    return [...defaultHomeAnnouncements]
  }
}

function parseHomeBanners(raw: string, showWarning = false) {
  try {
    const parsed = raw.trim() ? JSON.parse(raw) : defaultHomeBanners
    return cloneHomeBanners(mergeHomeConfig({ banners: Array.isArray(parsed) ? parsed : [] }).banners)
  } catch {
    if (showWarning) ElMessage.warning('首页轮播 JSON 解析失败，已使用默认配置')
    return cloneHomeBanners(defaultHomeBanners)
  }
}

function cloneOptions(options: ListingPublishOptions) {
  return JSON.parse(JSON.stringify(options)) as ListingPublishOptions
}

function cloneSalePriceConfig(config: PublishSalePriceConfig) {
  return JSON.parse(JSON.stringify(config)) as PublishSalePriceConfig
}

function cloneHomeBanners(banners: HomeBannerSlide[]) {
  return JSON.parse(JSON.stringify(banners)) as HomeBannerSlide[]
}

function linesToItems(value: string) {
  return value
    .split('\n')
    .map((item) => item.trim())
    .filter(Boolean)
}

function itemsToLines(items: string[]) {
  return items.join('\n')
}

function updateOptionLines(key: keyof Pick<ListingPublishOptions, 'server_options' | 'face_options' | 'rank_options' | 'insurance_options' | 'level_options' | 'login_method_options' | 'region_options' | 'ban_record_options' | 'ban_evidence_options'>, nextValue: string) {
  publishOptionsDraft.value[key] = linesToItems(nextValue)
}

function updateSkinGroupOptions(index: number, nextValue: string) {
  const group = publishOptionsDraft.value.skin_groups[index]
  if (group) {
    group.options = linesToItems(nextValue)
  }
}

function addSkinGroup() {
  publishOptionsDraft.value.skin_groups.push({
    key: `group_${Date.now()}`,
    title: '新皮肤分类',
    options: [],
  })
}

function removeSkinGroup(index: number) {
  publishOptionsDraft.value.skin_groups.splice(index, 1)
}

function addQuantityItem() {
  publishOptionsDraft.value.quantity_items.push({
    key: `item_${Date.now()}`,
    label: '',
    price: '',
  })
}

function removeQuantityItem(index: number) {
  publishOptionsDraft.value.quantity_items.splice(index, 1)
}

function addScreenshotSlot() {
  publishOptionsDraft.value.screenshot_slots.push({
    key: `screenshot_${Date.now()}`,
    label: '',
    required: false,
    hint: '',
  })
}

function removeScreenshotSlot(index: number) {
  publishOptionsDraft.value.screenshot_slots.splice(index, 1)
}

function addInsuranceBaseRatio() {
  publishOptionsDraft.value.ratio_config.insurance_base_ratios.push({
    insurance: '',
    ratio: 0,
  })
}

function removeInsuranceBaseRatio(index: number) {
  publishOptionsDraft.value.ratio_config.insurance_base_ratios.splice(index, 1)
}

function addRatioConfigItem() {
  publishOptionsDraft.value.ratio_config.config_items.push({
    key: `config_${Date.now()}`,
    label: '',
    kind: 'skin_group',
    group_key: '',
    missing_penalty: 1,
  })
}

function removeRatioConfigItem(index: number) {
  publishOptionsDraft.value.ratio_config.config_items.splice(index, 1)
}

function addCoinCorrection() {
  publishOptionsDraft.value.ratio_config.coin_corrections.push({
    threshold_m: 0,
    correction: 0,
  })
}

function removeCoinCorrection(index: number) {
  publishOptionsDraft.value.ratio_config.coin_corrections.splice(index, 1)
}

function addSaleFixedMarkupRule() {
  salePriceConfigDraft.value.fixed_markup_rules.push({
    min_m: 0,
    max_m: 0,
    markup_amount: 0,
  })
}

function removeSaleFixedMarkupRule(index: number) {
  salePriceConfigDraft.value.fixed_markup_rules.splice(index, 1)
}

function addSaleRatioAdjustmentRule() {
  salePriceConfigDraft.value.ratio_adjustment_rules.push({
    min_m: 0,
    max_m: 0,
    ratio_subtract: 0,
  })
}

function removeSaleRatioAdjustmentRule(index: number) {
  salePriceConfigDraft.value.ratio_adjustment_rules.splice(index, 1)
}

function addHomeBanner() {
  homeBannersDraft.value.push({
    eyebrow: '首页推荐',
    title: '',
    badge: 'NEW',
    pill: '',
    tone: 'blue',
    image_url: '',
  })
}

function removeHomeBanner(index: number) {
  homeBannersDraft.value.splice(index, 1)
}

function resetHomeAnnouncements() {
  homeAnnouncementLines.value = itemsToLines(defaultHomeAnnouncements)
}

function resetHomeBanners() {
  homeBannersDraft.value = cloneHomeBanners(defaultHomeBanners)
}

async function handleHomeBannerUpload(event: Event, index: number) {
  const input = event.target as HTMLInputElement
  const file = input.files?.[0]
  input.value = ''
  if (!file) return
  uploadingBannerIndex.value = index
  try {
    const uploaded = await uploadAdminFile(file, 'home-banner')
    const banner = homeBannersDraft.value[index]
    if (banner) {
      banner.image_url = uploaded.url
      if (!banner.title) {
        banner.title = banner.eyebrow || '首页轮播图'
      }
    }
    ElMessage.success('图片已上传')
  } catch (error) {
    ElMessage.error(readError(error, '图片上传失败'))
  } finally {
    uploadingBannerIndex.value = null
  }
}

function formatHomeConfigStatus(row: SystemConfig | null, fallback: string) {
  if (!row) return fallback
  return formatDateTime(row.updated_at, fallback)
}

function formatConfigValue(row: SystemConfig) {
  const trimmed = row.value.trim()
  if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
    return 'JSON 配置'
  }
  return row.value
}

function readError(error: unknown, fallback: string) {
  if (typeof error === 'object' && error && 'response' in error) {
    const response = (error as { response?: { data?: { message?: string } } }).response
    return response?.data?.message || fallback
  }
  return fallback
}
</script>

<template>
  <section class="page">
    <div class="page-header">
      <p class="eyebrow">Configs</p>
      <h1>系统配置</h1>
      <p>管理交接超时、归还超时、短信限流、最低押金和抽成比例。</p>
    </div>

    <section v-if="publishConfig" class="publish-config-panel">
      <div class="publish-config-main">
        <div>
          <p class="eyebrow">Publish Options</p>
          <h2>发布表单选项</h2>
          <span>管理移动端发布页的区服、段位、皮肤、额外消耗品、截图材料和地区选项。</span>
        </div>
        <el-button type="primary" @click="openEdit(publishConfig)">编辑发布选项</el-button>
      </div>
      <div class="publish-stat-grid">
        <div class="publish-stat">
          <strong>{{ publishStats.baseCount }}</strong>
          <span>基础选项</span>
        </div>
        <div class="publish-stat">
          <strong>{{ publishStats.skinCount }}</strong>
          <span>皮肤项</span>
        </div>
        <div class="publish-stat">
          <strong>{{ publishStats.resourceCount }}</strong>
          <span>额外消耗品</span>
        </div>
        <div class="publish-stat">
          <strong>{{ publishStats.screenshotCount }}</strong>
          <span>截图材料</span>
        </div>
        <div class="publish-stat">
          <strong>{{ publishStats.regionCount }}</strong>
          <span>地区</span>
        </div>
      </div>
    </section>

    <section v-if="salePriceConfig" class="publish-config-panel">
      <div class="publish-config-main">
        <div>
          <p class="eyebrow">Sale Pricing</p>
          <h2>内部出售定价规则</h2>
          <span>管理出售专用比例计算规则，仅用于平台内部定价计算，不在发布页展示。</span>
        </div>
        <el-button type="primary" @click="openEdit(salePriceConfig)">编辑出售规则</el-button>
      </div>
      <div class="publish-stat-grid home-stat-grid">
        <div class="publish-stat">
          <strong>{{ salePriceStats.fixedCount }}</strong>
          <span>固定加价</span>
        </div>
        <div class="publish-stat">
          <strong>{{ salePriceStats.ratioCount }}</strong>
          <span>比例修正</span>
        </div>
        <div class="publish-stat">
          <strong>内部</strong>
          <span>不展示给发布用户</span>
        </div>
        <div class="publish-stat">
          <strong>配置</strong>
          <span>listing.sale_price_config</span>
        </div>
        <div class="publish-stat">
          <strong>更新</strong>
          <span>{{ formatHomeConfigStatus(salePriceConfig, '未初始化') }}</span>
        </div>
      </div>
    </section>

    <section v-if="homeAnnouncementsConfig || homeBannersConfig" class="publish-config-panel">
      <div class="publish-config-main">
        <div>
          <p class="eyebrow">Home Content</p>
          <h2>移动端首页运营配置</h2>
          <span>管理首页公告滚动内容和顶部轮播图，保存后移动端会从接口读取最新配置。</span>
        </div>
        <div class="panel-actions">
          <el-button v-if="homeAnnouncementsConfig" @click="openEdit(homeAnnouncementsConfig)">编辑公告</el-button>
          <el-button v-if="homeBannersConfig" type="primary" @click="openEdit(homeBannersConfig)">编辑轮播图</el-button>
        </div>
      </div>
      <div class="publish-stat-grid home-stat-grid">
        <div class="publish-stat">
          <strong>{{ homeStats.announcementCount }}</strong>
          <span>公告条数</span>
        </div>
        <div class="publish-stat">
          <strong>{{ homeStats.bannerCount }}</strong>
          <span>轮播图</span>
        </div>
        <div class="publish-stat">
          <strong>接口</strong>
          <span>/api/mobile-home-config</span>
        </div>
        <div class="publish-stat">
          <strong>公告</strong>
          <span>{{ formatHomeConfigStatus(homeAnnouncementsConfig, '未初始化') }}</span>
        </div>
        <div class="publish-stat">
          <strong>轮播</strong>
          <span>{{ formatHomeConfigStatus(homeBannersConfig, '未初始化') }}</span>
        </div>
      </div>
    </section>

    <el-table v-loading="loading" class="table-panel" :data="regularConfigs">
      <el-table-column prop="key" label="配置项" min-width="260" />
      <el-table-column label="当前值" min-width="180" show-overflow-tooltip>
        <template #default="{ row }">
          <el-tag v-if="formatConfigValue(row) === 'JSON 配置'" type="info">JSON 配置</el-tag>
          <span v-else class="config-value">{{ formatConfigValue(row) }}</span>
        </template>
      </el-table-column>
      <el-table-column prop="description" label="说明" min-width="260" show-overflow-tooltip />
      <el-table-column prop="updated_by" label="更新人" width="100" />
      <el-table-column label="更新时间" min-width="180">
        <template #default="{ row }">{{ formatDateTime(row.updated_at) }}</template>
      </el-table-column>
      <el-table-column label="操作" width="100">
        <template #default="{ row }">
          <el-button size="small" @click="openEdit(row)">编辑</el-button>
        </template>
      </el-table-column>
    </el-table>

    <el-dialog :model-value="!!activeConfig" title="编辑系统配置" :width="dialogWidth" @update:model-value="activeConfig = null">
      <div v-if="activeConfig" class="dialog-body">
        <p><strong>{{ activeConfig.key }}</strong></p>

        <div v-if="isPublishOptionsConfig" class="publish-options-editor">
          <div class="editor-toolbar">
            <span>发布页选项配置</span>
          </div>

          <div class="editor-grid">
            <el-form-item label="区服">
              <el-input
                :model-value="itemsToLines(publishOptionsDraft.server_options)"
                type="textarea"
                :rows="4"
                placeholder="一行一个选项"
                @update:model-value="updateOptionLines('server_options', $event)"
              />
            </el-form-item>
            <el-form-item label="段位">
              <el-input
                :model-value="itemsToLines(publishOptionsDraft.rank_options)"
                type="textarea"
                :rows="4"
                placeholder="一行一个选项"
                @update:model-value="updateOptionLines('rank_options', $event)"
              />
            </el-form-item>
            <el-form-item label="保险">
              <el-input
                :model-value="itemsToLines(publishOptionsDraft.insurance_options)"
                type="textarea"
                :rows="4"
                placeholder="一行一个选项"
                @update:model-value="updateOptionLines('insurance_options', $event)"
              />
            </el-form-item>
            <el-form-item label="体力/负重">
              <el-input
                :model-value="itemsToLines(publishOptionsDraft.level_options)"
                type="textarea"
                :rows="4"
                placeholder="一行一个选项"
                @update:model-value="updateOptionLines('level_options', $event)"
              />
            </el-form-item>
            <el-form-item label="人脸选项">
              <el-input
                :model-value="itemsToLines(publishOptionsDraft.face_options)"
                type="textarea"
                :rows="3"
                placeholder="一行一个选项"
                @update:model-value="updateOptionLines('face_options', $event)"
              />
            </el-form-item>
            <el-form-item label="上号方式">
              <el-input
                :model-value="itemsToLines(publishOptionsDraft.login_method_options)"
                type="textarea"
                :rows="3"
                placeholder="一行一个选项"
                @update:model-value="updateOptionLines('login_method_options', $event)"
              />
            </el-form-item>
          </div>

          <el-form-item label="常用登录地区">
            <el-input
              :model-value="itemsToLines(publishOptionsDraft.region_options)"
              type="textarea"
              :rows="5"
              placeholder="一行一个省市"
              @update:model-value="updateOptionLines('region_options', $event)"
            />
          </el-form-item>

          <div class="editor-grid">
            <el-form-item label="封禁记录">
              <el-input
                :model-value="itemsToLines(publishOptionsDraft.ban_record_options)"
                type="textarea"
                :rows="3"
                placeholder="一行一个选项"
                @update:model-value="updateOptionLines('ban_record_options', $event)"
              />
            </el-form-item>
            <el-form-item label="需传安全图">
              <el-input
                :model-value="itemsToLines(publishOptionsDraft.ban_evidence_options)"
                type="textarea"
                :rows="3"
                placeholder="选择这些封禁记录时，腾讯安全中心截图必传"
                @update:model-value="updateOptionLines('ban_evidence_options', $event)"
              />
            </el-form-item>
          </div>

          <div class="editor-block">
            <div class="editor-block-title">
              <strong>发布规则</strong>
            </div>
            <el-form-item label="最低烽火等级">
              <el-input-number v-model="publishOptionsDraft.fire_level_min" :min="1" :step="1" class="full-control" />
            </el-form-item>
          </div>

          <div class="editor-block">
            <div class="editor-block-title">
              <strong>押金与价格提示</strong>
            </div>
            <el-form-item label="押金提示">
              <el-input v-model="publishOptionsDraft.price_config.deposit_placeholder" type="textarea" :rows="3" />
            </el-form-item>
            <el-form-item label="价格提示">
              <el-input v-model="publishOptionsDraft.price_config.price_placeholder" />
            </el-form-item>
            <el-form-item label="比例说明">
              <el-input v-model="publishOptionsDraft.price_config.ratio_description" />
            </el-form-item>
          </div>

          <div class="editor-block">
            <div class="editor-block-title">
              <strong>比例计算配置</strong>
            </div>
            <div class="editor-block-title subtle-title">
              <span>保险基础比例</span>
              <el-button size="small" @click="addInsuranceBaseRatio">添加保险比例</el-button>
            </div>
            <el-table :data="publishOptionsDraft.ratio_config.insurance_base_ratios" size="small" border>
              <el-table-column label="保险" min-width="160">
                <template #default="{ row }"><el-input v-model="row.insurance" placeholder="3*3" /></template>
              </el-table-column>
              <el-table-column label="基础比例" min-width="120">
                <template #default="{ row }"><el-input-number v-model="row.ratio" :min="0" :step="0.5" /></template>
              </el-table-column>
              <el-table-column label="操作" width="90">
                <template #default="{ $index }">
                  <el-button size="small" type="danger" plain @click="removeInsuranceBaseRatio($index)">删除</el-button>
                </template>
              </el-table-column>
            </el-table>

            <div class="editor-block-title subtle-title">
              <span>配置项缺失加成</span>
              <el-button size="small" @click="addRatioConfigItem">添加配置项</el-button>
            </div>
            <el-table :data="publishOptionsDraft.ratio_config.config_items" size="small" border>
              <el-table-column label="Key" min-width="140">
                <template #default="{ row }"><el-input v-model="row.key" /></template>
              </el-table-column>
              <el-table-column label="名称" min-width="140">
                <template #default="{ row }"><el-input v-model="row.label" /></template>
              </el-table-column>
              <el-table-column label="类型" min-width="160">
                <template #default="{ row }">
                  <el-select v-model="row.kind">
                    <el-option label="皮肤分组" value="skin_group" />
                    <el-option label="满体力" value="max_stamina" />
                    <el-option label="满负重" value="max_load" />
                  </el-select>
                </template>
              </el-table-column>
              <el-table-column label="皮肤分组 Key" min-width="150">
                <template #default="{ row }"><el-input v-model="row.group_key" /></template>
              </el-table-column>
              <el-table-column label="缺失加成" min-width="120">
                <template #default="{ row }"><el-input-number v-model="row.missing_penalty" :min="0" :step="0.5" /></template>
              </el-table-column>
              <el-table-column label="操作" width="90">
                <template #default="{ $index }">
                  <el-button size="small" type="danger" plain @click="removeRatioConfigItem($index)">删除</el-button>
                </template>
              </el-table-column>
            </el-table>

            <div class="editor-block-title subtle-title">
              <span>大额币修正</span>
              <el-button size="small" @click="addCoinCorrection">添加修正</el-button>
            </div>
            <el-table :data="publishOptionsDraft.ratio_config.coin_corrections" size="small" border>
              <el-table-column label="大于 M" min-width="130">
                <template #default="{ row }"><el-input-number v-model="row.threshold_m" :min="0" :step="10" /></template>
              </el-table-column>
              <el-table-column label="比例加成" min-width="130">
                <template #default="{ row }"><el-input-number v-model="row.correction" :min="0" :step="0.5" /></template>
              </el-table-column>
              <el-table-column label="操作" width="90">
                <template #default="{ $index }">
                  <el-button size="small" type="danger" plain @click="removeCoinCorrection($index)">删除</el-button>
                </template>
              </el-table-column>
            </el-table>

          </div>

          <div class="editor-block">
            <div class="editor-block-title">
              <strong>皮肤分类</strong>
              <el-button size="small" @click="addSkinGroup">添加分类</el-button>
            </div>
            <div v-for="(group, index) in publishOptionsDraft.skin_groups" :key="`${group.key}-${index}`" class="skin-config-row">
              <el-input v-model="group.key" placeholder="分类 key" />
              <el-input v-model="group.title" placeholder="分类名称" />
              <el-input
                :model-value="itemsToLines(group.options)"
                type="textarea"
                :rows="4"
                placeholder="皮肤名称，一行一个"
                @update:model-value="updateSkinGroupOptions(index, $event)"
              />
              <el-button type="danger" plain @click="removeSkinGroup(index)">删除</el-button>
            </div>
          </div>

          <div class="editor-block">
            <div class="editor-block-title">
              <strong>额外消耗品</strong>
              <el-button size="small" @click="addQuantityItem">添加消耗品</el-button>
            </div>
            <el-table :data="publishOptionsDraft.quantity_items" size="small" border>
              <el-table-column label="Key" min-width="150">
                <template #default="{ row }"><el-input v-model="row.key" /></template>
              </el-table-column>
              <el-table-column label="名称" min-width="150">
                <template #default="{ row }"><el-input v-model="row.label" /></template>
              </el-table-column>
              <el-table-column label="价格" min-width="130">
                <template #default="{ row }"><el-input v-model="row.price" /></template>
              </el-table-column>
              <el-table-column label="提示" min-width="220">
                <template #default="{ row }"><el-input v-model="row.placeholder" /></template>
              </el-table-column>
              <el-table-column label="操作" width="90">
                <template #default="{ $index }">
                  <el-button size="small" type="danger" plain @click="removeQuantityItem($index)">删除</el-button>
                </template>
              </el-table-column>
            </el-table>
          </div>

          <div class="editor-block">
            <div class="editor-block-title">
              <strong>截图材料</strong>
              <el-button size="small" @click="addScreenshotSlot">添加截图项</el-button>
            </div>
            <el-table :data="publishOptionsDraft.screenshot_slots" size="small" border>
              <el-table-column label="Key" min-width="150">
                <template #default="{ row }"><el-input v-model="row.key" /></template>
              </el-table-column>
              <el-table-column label="名称" min-width="150">
                <template #default="{ row }"><el-input v-model="row.label" /></template>
              </el-table-column>
              <el-table-column label="必填" width="90">
                <template #default="{ row }"><el-switch v-model="row.required" /></template>
              </el-table-column>
              <el-table-column label="提示" min-width="260">
                <template #default="{ row }"><el-input v-model="row.hint" /></template>
              </el-table-column>
              <el-table-column label="操作" width="90">
                <template #default="{ $index }">
                  <el-button size="small" type="danger" plain @click="removeScreenshotSlot($index)">删除</el-button>
                </template>
              </el-table-column>
            </el-table>
          </div>
        </div>

        <div v-else-if="isSalePriceConfig" class="publish-options-editor">
          <div class="editor-toolbar">
            <span>内部出售定价规则</span>
          </div>

          <div class="editor-block">
            <div class="editor-block-title subtle-title">
              <span>90M 及以下固定加价：出售价格 = 回收价格 + 固定加价</span>
              <el-button size="small" @click="addSaleFixedMarkupRule">添加固定加价</el-button>
            </div>
            <el-table :data="salePriceConfigDraft.fixed_markup_rules" size="small" border>
              <el-table-column label="最小 M" min-width="120">
                <template #default="{ row }"><el-input-number v-model="row.min_m" :min="0" :step="10" /></template>
              </el-table-column>
              <el-table-column label="最大 M" min-width="120">
                <template #default="{ row }"><el-input-number v-model="row.max_m" :min="0" :step="10" /></template>
              </el-table-column>
              <el-table-column label="加价金额/元" min-width="140">
                <template #default="{ row }"><el-input-number v-model="row.markup_amount" :min="0" :step="1" /></template>
              </el-table-column>
              <el-table-column label="操作" width="90">
                <template #default="{ $index }">
                  <el-button size="small" type="danger" plain @click="removeSaleFixedMarkupRule($index)">删除</el-button>
                </template>
              </el-table-column>
            </el-table>

            <div class="editor-block-title subtle-title">
              <span>90M 以上比例修正：出售比例 = 回收比例 - 比例修正；最大 M 为 0 表示无上限</span>
              <el-button size="small" @click="addSaleRatioAdjustmentRule">添加比例修正</el-button>
            </div>
            <el-table :data="salePriceConfigDraft.ratio_adjustment_rules" size="small" border>
              <el-table-column label="最小 M" min-width="120">
                <template #default="{ row }"><el-input-number v-model="row.min_m" :min="0" :step="10" /></template>
              </el-table-column>
              <el-table-column label="最大 M" min-width="120">
                <template #default="{ row }"><el-input-number v-model="row.max_m" :min="0" :step="10" /></template>
              </el-table-column>
              <el-table-column label="比例修正" min-width="130">
                <template #default="{ row }"><el-input-number v-model="row.ratio_subtract" :min="0" :step="0.5" /></template>
              </el-table-column>
              <el-table-column label="操作" width="90">
                <template #default="{ $index }">
                  <el-button size="small" type="danger" plain @click="removeSaleRatioAdjustmentRule($index)">删除</el-button>
                </template>
              </el-table-column>
            </el-table>
          </div>
        </div>

        <div v-else-if="isHomeAnnouncementsConfig" class="home-config-editor">
          <div class="editor-toolbar">
            <span>首页公告</span>
            <el-button size="small" @click="resetHomeAnnouncements">恢复默认公告</el-button>
          </div>
          <el-form-item label="公告内容">
            <el-input
              v-model="homeAnnouncementLines"
              type="textarea"
              :rows="8"
              placeholder="一行一条公告，移动端会自动轮播展示"
            />
          </el-form-item>
        </div>

        <div v-else-if="isHomeBannersConfig" class="home-config-editor">
          <div class="editor-toolbar">
            <span>首页轮播图</span>
            <div class="panel-actions">
              <el-button size="small" @click="resetHomeBanners">恢复默认轮播</el-button>
              <el-button size="small" type="primary" @click="addHomeBanner">添加轮播</el-button>
            </div>
          </div>
          <el-table :data="homeBannersDraft" size="small" border>
            <el-table-column label="图片" min-width="240">
              <template #default="{ row, $index }">
                <div class="banner-image-editor">
                  <el-input v-model="row.image_url" placeholder="图片 URL，留空使用文字卡片" />
                  <div class="banner-image-tools">
                    <img v-if="row.image_url" :src="row.image_url" alt="轮播图预览" />
                    <span v-else>无图</span>
                    <label class="upload-trigger">
                      <input type="file" accept="image/jpeg,image/png,image/webp" @change="handleHomeBannerUpload($event, $index)" />
                      {{ uploadingBannerIndex === $index ? '上传中' : '上传图片' }}
                    </label>
                  </div>
                </div>
              </template>
            </el-table-column>
            <el-table-column label="眉标" min-width="160">
              <template #default="{ row }"><el-input v-model="row.eyebrow" placeholder="如 三角洲行动账号专区" /></template>
            </el-table-column>
            <el-table-column label="主标题" min-width="220">
              <template #default="{ row }"><el-input v-model="row.title" placeholder="轮播主文案" /></template>
            </el-table-column>
            <el-table-column label="角标" width="110">
              <template #default="{ row }"><el-input v-model="row.badge" placeholder="HOT" /></template>
            </el-table-column>
            <el-table-column label="胶囊文案" min-width="220">
              <template #default="{ row }"><el-input v-model="row.pill" placeholder="底部补充文案" /></template>
            </el-table-column>
            <el-table-column label="色调" width="130">
              <template #default="{ row }">
                <el-select v-model="row.tone" placeholder="色调">
                  <el-option label="蓝色" value="blue" />
                  <el-option label="绿色" value="green" />
                  <el-option label="橙色" value="orange" />
                </el-select>
              </template>
            </el-table-column>
            <el-table-column label="操作" width="90">
              <template #default="{ $index }">
                <el-button size="small" type="danger" plain @click="removeHomeBanner($index)">删除</el-button>
              </template>
            </el-table-column>
          </el-table>
        </div>

        <el-input v-else-if="isStructuredConfig" v-model="value" type="textarea" :rows="12" placeholder="配置值 JSON" />
        <el-input v-else v-model="value" placeholder="配置值" />
        <el-input v-model="description" type="textarea" :rows="3" placeholder="配置说明" />
      </div>
      <template #footer>
        <el-button @click="activeConfig = null">取消</el-button>
        <el-button type="primary" :loading="submitting" @click="handleSave">保存</el-button>
      </template>
    </el-dialog>
  </section>
</template>

<style scoped>
.publish-config-panel {
  display: grid;
  gap: 18px;
  margin-bottom: 18px;
  padding: 20px;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  background: #fff;
}

.publish-config-main {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
}

.panel-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.publish-config-main h2 {
  margin: 4px 0 6px;
  color: #111827;
  font-size: 20px;
}

.publish-config-main span {
  color: #6b7280;
  font-size: 13px;
}

.publish-stat-grid {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 10px;
}

.home-stat-grid .publish-stat strong {
  font-size: 18px;
}

.publish-stat {
  display: grid;
  gap: 4px;
  padding: 12px;
  border-radius: 8px;
  background: #f8fafc;
}

.publish-stat strong {
  color: #1477ff;
  font-size: 22px;
  line-height: 1;
}

.publish-stat span,
.config-value {
  color: #4b5563;
  font-size: 13px;
}

.publish-options-editor {
  display: grid;
  gap: 16px;
}

.home-config-editor {
  display: grid;
  gap: 14px;
}

.banner-image-editor {
  display: grid;
  gap: 8px;
}

.banner-image-tools {
  display: flex;
  align-items: center;
  gap: 8px;
}

.banner-image-tools img,
.banner-image-tools span {
  width: 68px;
  height: 38px;
  border-radius: 6px;
  background: #f3f4f6;
  object-fit: cover;
}

.banner-image-tools span {
  display: grid;
  place-items: center;
  color: #9ca3af;
  font-size: 12px;
}

.upload-trigger {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 28px;
  padding: 0 10px;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  background: #fff;
  color: #606266;
  cursor: pointer;
  font-size: 12px;
}

.upload-trigger input {
  position: absolute;
  inset: 0;
  opacity: 0;
  cursor: pointer;
}

.editor-toolbar,
.editor-block-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.editor-toolbar span {
  color: #30343a;
  font-weight: 700;
}

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

.editor-block {
  display: grid;
  gap: 10px;
}

.subtle-title {
  margin-top: 6px;
  color: #4b5563;
  font-size: 13px;
}

.skin-config-row {
  display: grid;
  grid-template-columns: 140px 180px minmax(0, 1fr) 72px;
  gap: 8px;
  align-items: start;
}

@media (max-width: 1100px) {
  .publish-stat-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}
</style>
