<template>
  <div v-if="app">
    <el-page-header @back="$router.back()" content="推送服务配置" style="margin-bottom:24px" />

    <el-card class="info-card" style="margin-bottom:16px">
      <el-descriptions :column="isMobile ? 1 : 2" border>
        <el-descriptions-item label="应用名称">{{ app.name }}</el-descriptions-item>
        <el-descriptions-item label="包名">{{ app.packageName }}</el-descriptions-item>
        <el-descriptions-item label="AppKey">
          <el-text class="mono">{{ app.appKey }}</el-text>
          <el-button link @click="copy(app.appKey)"><el-icon><CopyDocument /></el-icon></el-button>
        </el-descriptions-item>
        <el-descriptions-item label="服务状态">
          <el-tag :type="pushEnabled ? 'success' : 'info'">{{ pushEnabled ? '已开通' : '未开通' }}</el-tag>
        </el-descriptions-item>
        <el-descriptions-item label="配置平台">
          <el-segmented v-model="selectedPlatform" :options="platformOptions" @change="applySelectedPlatformConfig" />
        </el-descriptions-item>
      </el-descriptions>
      <div class="push-switch-row">
        <el-switch :model-value="pushEnabled" @change="(val: boolean) => onTogglePushService(val)" />
        <span class="hint">关闭后，推送注册与推送发送都不会再向该应用开放。</span>
      </div>
    </el-card>

    <el-alert
      title="新推送模型按 vendors + profiles 管理。厂商凭据只负责连厂商，profiles 负责按场景配置 Channel ID、Category、Importance、角标、声音、振动等。"
      type="info"
      :closable="false"
      show-icon
      style="margin-bottom:16px"
    />

    <el-card style="margin-bottom:16px">
      <template #header>厂商凭据</template>
      <div class="vendor-grid">
        <el-card v-for="vendor in vendorDefs" :key="vendor.key" shadow="never" class="vendor-card">
          <template #header>{{ vendor.label }}</template>
          <div class="vendor-hint">{{ vendor.hint }}</div>
          <el-form :label-position="isMobile ? 'top' : 'right'" label-width="110px">
            <el-form-item v-for="field in vendor.fields" :key="field.key" :label="field.label">
              <el-input
                v-if="field.type === 'textarea'"
                v-model="vendorModel(vendor.key)[field.key]"
                type="textarea"
                :rows="field.rows ?? 4"
                :placeholder="field.placeholder"
              />
              <el-switch
                v-else-if="field.type === 'switch'"
                v-model="vendorModel(vendor.key)[field.key]"
              />
              <el-input
                v-else
                v-model="vendorModel(vendor.key)[field.key]"
                :placeholder="field.placeholder"
              />
            </el-form-item>
          </el-form>
        </el-card>
      </div>
    </el-card>

    <el-card>
      <template #header>
        <div class="profiles-header">
          <span>平台 Profiles</span>
          <div class="profiles-actions">
            <el-button size="small" @click="addProfile()">新增通用 profile</el-button>
            <el-button size="small" @click="addProfile('xiaomi')">新增小米</el-button>
            <el-button size="small" @click="addProfile('huawei')">新增华为</el-button>
            <el-button size="small" @click="addProfile('honor')">新增荣耀</el-button>
            <el-button size="small" @click="addProfile('oppo')">新增 OPPO</el-button>
            <el-button size="small" @click="addProfile('vivo')">新增 vivo</el-button>
            <el-button size="small" @click="addProfile('harmony')">新增鸿蒙</el-button>
            <el-button size="small" @click="addProfile('apns')">新增 iOS</el-button>
          </div>
        </div>
      </template>

      <el-alert
        description="routeType 为空时表示默认兜底 profile。你可以先建 3 条，后续随时补充剩余的 2 条，或者删除不再使用的 profile。"
        type="info"
        :closable="false"
        :show-icon="false"
        style="margin-bottom:12px"
      />

      <el-table :data="pushConfig.profiles" border style="margin-bottom:16px" class="profiles-table">
        <el-table-column label="启用" width="78" align="center">
          <template #default="{ row }">
            <el-switch v-model="row.enabled" />
          </template>
        </el-table-column>
        <el-table-column label="厂商" min-width="120">
          <template #default="{ row }">
            <el-select v-model="row.vendor" filterable>
              <el-option v-for="vendor in vendorOptions" :key="vendor.value" :label="vendor.label" :value="vendor.value" />
            </el-select>
          </template>
        </el-table-column>
        <el-table-column label="场景 RouteType" min-width="180">
          <template #default="{ row }">
            <el-select
              v-model="row.routeType"
              filterable
              allow-create
              default-first-option
              placeholder="例如 IM_MESSAGE / SYSTEM_NOTICE"
            >
              <el-option v-for="route in routeTypeOptions" :key="route" :label="route" :value="route" />
            </el-select>
          </template>
        </el-table-column>
        <el-table-column label="Profile Key" min-width="180">
          <template #default="{ row }">
            <el-input v-model="row.profileKey" placeholder="例如 xiaomi_im_message_v1" />
          </template>
        </el-table-column>
        <el-table-column label="Channel ID" min-width="180">
          <template #default="{ row }">
            <el-input v-model="row.channelId" placeholder="厂商 Channel ID / 通知通道 ID" />
          </template>
        </el-table-column>
        <el-table-column label="Category" min-width="160">
          <template #default="{ row }">
            <el-input v-model="row.category" placeholder="MESSAGE / SYSTEM / ..." />
          </template>
        </el-table-column>
        <el-table-column label="重要性" width="120">
          <template #default="{ row }">
            <el-select v-model="row.importance">
              <el-option v-for="item in importanceOptions" :key="item.value" :label="item.label" :value="item.value" />
            </el-select>
          </template>
        </el-table-column>
        <el-table-column label="优先级" width="120">
          <template #default="{ row }">
            <el-select v-model="row.priority">
              <el-option v-for="item in priorityOptions" :key="item.value" :label="item.label" :value="item.value" />
            </el-select>
          </template>
        </el-table-column>
        <el-table-column label="角标" width="78" align="center">
          <template #default="{ row }">
            <el-switch v-model="row.badge" />
          </template>
        </el-table-column>
        <el-table-column label="声音" width="78" align="center">
          <template #default="{ row }">
            <el-switch v-model="row.sound" />
          </template>
        </el-table-column>
        <el-table-column label="振动" width="78" align="center">
          <template #default="{ row }">
            <el-switch v-model="row.vibration" />
          </template>
        </el-table-column>
        <el-table-column label="Thread ID" min-width="150">
          <template #default="{ row }">
            <el-input v-model="row.threadIdentifier" placeholder="iOS thread-id" />
          </template>
        </el-table-column>
        <el-table-column label="中断级别" min-width="150">
          <template #default="{ row }">
            <el-select v-model="row.interruptionLevel" clearable placeholder="默认">
              <el-option v-for="item in interruptionOptions" :key="item.value" :label="item.label" :value="item.value" />
            </el-select>
          </template>
        </el-table-column>
        <el-table-column label="NotifyType" width="120">
          <template #default="{ row }">
            <el-input-number v-model="row.notifyType" :min="0" :max="10" controls-position="right" style="width:100%" />
          </template>
        </el-table-column>
        <el-table-column label="版本" width="92">
          <template #default="{ row }">
            <el-input-number v-model="row.version" :min="1" controls-position="right" style="width:74px" />
          </template>
        </el-table-column>
        <el-table-column label="备注" min-width="200">
          <template #default="{ row }">
            <el-input v-model="row.remark" placeholder="可选说明" />
          </template>
        </el-table-column>
        <el-table-column label="操作" width="84" fixed="right">
          <template #default="{ $index }">
            <el-button link type="danger" @click="removeProfile($index)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>

      <div class="toolbar">
        <el-button @click="reloadConfig" :loading="loading">刷新</el-button>
        <el-button type="primary" @click="saveConfig" :loading="saving">保存配置</el-button>
      </div>
    </el-card>
  </div>
</template>

<script setup lang="ts">
import { computed, onBeforeUnmount, onMounted, reactive, ref } from 'vue'
import { useRoute } from 'vue-router'
import { CopyDocument } from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import {
  appApi,
  type App,
  type FeatureService,
  type ApnsPushVendorConfig,
  type HarmonyPushVendorConfig,
  type HonorPushVendorConfig,
  type HuaweiPushVendorConfig,
  type OppoPushVendorConfig,
  type PushImportance,
  type PushInterruptionLevel,
  type PushPriority,
  type PushProfileConfig,
  type PushServiceConfig,
  type PushVendorKey,
  type XiaomiPushVendorConfig,
  type VivoPushVendorConfig,
} from '@/api/app'

type PushVendorsState = {
  huawei: HuaweiPushVendorConfig
  xiaomi: XiaomiPushVendorConfig
  oppo: OppoPushVendorConfig
  vivo: VivoPushVendorConfig
  honor: HonorPushVendorConfig
  harmony: HarmonyPushVendorConfig
  apns: ApnsPushVendorConfig
}

type FieldDef = {
  key: string
  label: string
  type?: 'textarea' | 'switch'
  placeholder?: string
  rows?: number
}

type VendorDef = {
  key: PushVendorKey
  label: string
  hint: string
  fields: FieldDef[]
}

type PushConfigState = {
  schemaVersion: number
  updatedAt: string
  vendors: PushVendorsState
  profiles: PushProfileConfig[]
}

const route = useRoute()
const app = ref<App | null>(null)
const services = ref<FeatureService[]>([])
const loading = ref(false)
const saving = ref(false)
const isMobile = ref(window.innerWidth < 768)
const selectedPlatform = ref<'ANDROID' | 'IOS' | 'HARMONY'>('ANDROID')

const platformOptions = [
  { label: 'Android', value: 'ANDROID' },
  { label: 'iOS', value: 'IOS' },
  { label: '鸿蒙', value: 'HARMONY' },
]

const vendorOptions: Array<{ label: string; value: PushVendorKey }> = [
  { label: '华为', value: 'huawei' },
  { label: '小米', value: 'xiaomi' },
  { label: 'OPPO', value: 'oppo' },
  { label: 'vivo', value: 'vivo' },
  { label: '荣耀', value: 'honor' },
  { label: '鸿蒙', value: 'harmony' },
  { label: 'iOS', value: 'apns' },
]

const routeTypeOptions = [
  'IM_MESSAGE',
  'FRIEND_REQUEST',
  'SYSTEM_NOTICE',
  'SERVICE_NOTICE',
  'MARKETING',
  'DEFAULT',
]

const importanceOptions = [
  { label: '最小', value: 'MIN' },
  { label: '低', value: 'LOW' },
  { label: '默认', value: 'DEFAULT' },
  { label: '高', value: 'HIGH' },
  { label: '最高', value: 'MAX' },
] as const satisfies ReadonlyArray<{ label: string; value: PushImportance }>

const priorityOptions = [
  { label: '低', value: 'LOW' },
  { label: '默认', value: 'DEFAULT' },
  { label: '高', value: 'HIGH' },
] as const satisfies ReadonlyArray<{ label: string; value: PushPriority }>

const interruptionOptions = [
  { label: 'Passive', value: 'passive' },
  { label: 'Active', value: 'active' },
  { label: 'Time Sensitive', value: 'time-sensitive' },
  { label: 'Critical', value: 'critical' },
] as const satisfies ReadonlyArray<{ label: string; value: PushInterruptionLevel }>

const vendors = reactive<PushVendorsState>(createEmptyVendors())
const pushConfig = reactive<PushConfigState>({
  schemaVersion: 2,
  updatedAt: '',
  vendors,
  profiles: [],
})

const vendorDefs: VendorDef[] = [
  {
    key: 'xiaomi',
    label: '小米 MiPush',
    hint: '这里仅填写厂商凭据。Channel ID 放在 profiles 中按场景单独配置，支持后续补充或删除。',
    fields: [
      { key: 'appId', label: 'AppId' },
      { key: 'appKey', label: 'AppKey' },
      { key: 'appSecret', label: 'AppSecret' },
    ],
  },
  {
    key: 'huawei',
    label: '华为 HMS',
    hint: '仅保留厂商账号信息。Category、Channel ID、重要性等由 profiles 负责。',
    fields: [
      { key: 'appId', label: 'AppId' },
      { key: 'appSecret', label: 'AppSecret' },
    ],
  },
  {
    key: 'honor',
    label: '荣耀 Push',
    hint: '荣耀账号凭据。业务场景与展示策略在 profiles 中配置。',
    fields: [
      { key: 'appId', label: 'AppId' },
      { key: 'clientId', label: 'ClientId' },
      { key: 'clientSecret', label: 'ClientSecret' },
    ],
  },
  {
    key: 'oppo',
    label: 'OPPO 推送',
    hint: '仅保留 AppKey / MasterSecret。通道配置与优先级在 profiles 中维护。',
    fields: [
      { key: 'appId', label: 'AppId' },
      { key: 'appKey', label: 'AppKey' },
      { key: 'masterSecret', label: 'MasterSecret' },
    ],
  },
  {
    key: 'vivo',
    label: 'vivo 推送',
    hint: '厂商凭据与业务分类分离。classification 由 profiles 的 Category 驱动。',
    fields: [
      { key: 'appId', label: 'AppId' },
      { key: 'appKey', label: 'AppKey' },
      { key: 'appSecret', label: 'AppSecret' },
    ],
  },
  {
    key: 'harmony',
    label: '鸿蒙 Push Kit',
    hint: '鸿蒙厂商凭据。需要的 Category / Channel ID 放到 profiles 中。',
    fields: [
      { key: 'appId', label: 'AppId' },
      { key: 'appSecret', label: 'AppSecret' },
    ],
  },
  {
    key: 'apns',
    label: 'iOS APNs',
    hint: 'Team ID / Key ID / Bundle ID / 私钥统一放这里。Badge、Thread ID、Interruption Level 放在 profiles 中。',
    fields: [
      { key: 'teamId', label: 'Team ID' },
      { key: 'keyId', label: 'Key ID' },
      { key: 'bundleId', label: 'Bundle ID' },
      { key: 'privateKey', label: 'Private Key', type: 'textarea', rows: 6, placeholder: '粘贴 .p8 内容' },
      { key: 'sandbox', label: 'Sandbox', type: 'switch' },
    ],
  },
]

const pushEnabled = computed(() => services.value.some(
  s => s.serviceType === 'PUSH' && s.platform === selectedPlatform.value && s.enabled,
))

function updateViewport() {
  isMobile.value = window.innerWidth < 768
}

function createEmptyVendors(): PushVendorsState {
  return {
    huawei: { appId: '', appSecret: '' },
    xiaomi: { appId: '', appKey: '', appSecret: '' },
    oppo: { appId: '', appKey: '', masterSecret: '' },
    vivo: { appId: '', appKey: '', appSecret: '' },
    honor: { appId: '', clientId: '', clientSecret: '' },
    harmony: { appId: '', appSecret: '' },
    apns: { teamId: '', keyId: '', bundleId: '', privateKey: '', sandbox: false },
  }
}

function createEmptyState(): PushConfigState {
  return {
    schemaVersion: 2,
    updatedAt: '',
    vendors: createEmptyVendors(),
    profiles: [],
  }
}

function createProfile(vendor: PushVendorKey = 'xiaomi', routeType = ''): PushProfileConfig {
  return {
    profileKey: `${vendor}_${routeType || 'default'}_${Date.now()}`,
    vendor,
    routeType,
    enabled: true,
    channelId: '',
    category: '',
    importance: 'DEFAULT',
    priority: 'DEFAULT',
    threadIdentifier: '',
    interruptionLevel: '',
    badge: true,
    sound: true,
    vibration: true,
    notifyType: 1,
    version: 1,
    remark: '',
  }
}

function vendorModel(vendor: PushVendorKey): Record<string, any> {
  return vendors[vendor] as Record<string, any>
}

function replaceState(next: PushConfigState) {
  Object.assign(pushConfig.vendors.huawei, next.vendors.huawei)
  Object.assign(pushConfig.vendors.xiaomi, next.vendors.xiaomi)
  Object.assign(pushConfig.vendors.oppo, next.vendors.oppo)
  Object.assign(pushConfig.vendors.vivo, next.vendors.vivo)
  Object.assign(pushConfig.vendors.honor, next.vendors.honor)
  Object.assign(pushConfig.vendors.harmony, next.vendors.harmony)
  Object.assign(pushConfig.vendors.apns, next.vendors.apns)
  pushConfig.schemaVersion = next.schemaVersion
  pushConfig.updatedAt = next.updatedAt
  pushConfig.profiles.splice(0, pushConfig.profiles.length, ...next.profiles.map(profile => normalizeProfile(profile)))
}

function normalizeProfile(profile: Partial<PushProfileConfig> & Pick<PushProfileConfig, 'vendor'>): PushProfileConfig {
  return {
    profileKey: profile.profileKey?.trim() || `${profile.vendor}_${profile.routeType || 'default'}_${Date.now()}`,
    vendor: profile.vendor,
    routeType: profile.routeType?.trim() || '',
    enabled: profile.enabled ?? true,
    channelId: profile.channelId?.trim() || '',
    category: profile.category?.trim() || '',
    importance: profile.importance || 'DEFAULT',
    priority: profile.priority || 'DEFAULT',
    threadIdentifier: profile.threadIdentifier?.trim() || '',
    interruptionLevel: profile.interruptionLevel || '',
    badge: profile.badge ?? true,
    sound: profile.sound ?? true,
    vibration: profile.vibration ?? true,
    notifyType: Number.isFinite(profile.notifyType as number) ? Math.max(Number(profile.notifyType ?? 1), 0) : 1,
    version: Math.max(Number(profile.version ?? 1), 1),
    remark: profile.remark?.trim() || '',
  }
}

function parseConfig(raw?: string | null): PushConfigState {
  if (!raw) {
    return createEmptyState()
  }
  try {
    const parsed = JSON.parse(raw) as Partial<PushConfigState>
    return {
      schemaVersion: parsed.schemaVersion ?? 2,
      updatedAt: parsed.updatedAt ?? '',
      vendors: {
        ...createEmptyVendors(),
        ...parsed.vendors,
        huawei: { ...createEmptyVendors().huawei, ...(parsed.vendors?.huawei ?? {}) },
        xiaomi: { ...createEmptyVendors().xiaomi, ...(parsed.vendors?.xiaomi ?? {}) },
        oppo: { ...createEmptyVendors().oppo, ...(parsed.vendors?.oppo ?? {}) },
        vivo: { ...createEmptyVendors().vivo, ...(parsed.vendors?.vivo ?? {}) },
        honor: { ...createEmptyVendors().honor, ...(parsed.vendors?.honor ?? {}) },
        harmony: { ...createEmptyVendors().harmony, ...(parsed.vendors?.harmony ?? {}) },
        apns: { ...createEmptyVendors().apns, ...(parsed.vendors?.apns ?? {}) },
      },
      profiles: Array.isArray(parsed.profiles)
        ? parsed.profiles.map(profile => normalizeProfile(profile as Partial<PushProfileConfig> & Pick<PushProfileConfig, 'vendor'>))
        : [],
    }
  } catch {
    return createEmptyState()
  }
}

async function loadData() {
  loading.value = true
  try {
    const id = route.params.appKey as string
    const [appRes, svcRes] = await Promise.all([
      appApi.get(id),
      appApi.getServices(id),
    ])
    app.value = appRes.data.data
    services.value = svcRes.data.data
    const firstPushService = services.value.find(s => s.serviceType === 'PUSH')
    if (firstPushService && !services.value.some(s => s.serviceType === 'PUSH' && s.platform === selectedPlatform.value)) {
      selectedPlatform.value = firstPushService.platform
    }
    applySelectedPlatformConfig()
  } finally {
    loading.value = false
  }
}

function applySelectedPlatformConfig() {
  const raw = services.value.find(
    s => s.serviceType === 'PUSH' && s.platform === selectedPlatform.value,
  )?.config
  replaceState(parseConfig(raw))
}

async function saveConfig() {
  if (!app.value) return
  saving.value = true
  try {
    const payload: PushServiceConfig = {
      schemaVersion: 2,
      updatedAt: new Date().toISOString(),
      vendors: {
        huawei: { ...pushConfig.vendors.huawei },
        xiaomi: { ...pushConfig.vendors.xiaomi },
        oppo: { ...pushConfig.vendors.oppo },
        vivo: { ...pushConfig.vendors.vivo },
        honor: { ...pushConfig.vendors.honor },
        harmony: { ...pushConfig.vendors.harmony },
        apns: { ...pushConfig.vendors.apns },
      },
      profiles: pushConfig.profiles.map(profile => normalizeProfile(profile)),
    }
    await appApi.updateServiceConfig(app.value.appKey, selectedPlatform.value, 'PUSH', payload)
    ElMessage.success('推送配置已保存')
    await loadData()
  } catch {
    ElMessage.error('保存失败')
  } finally {
    saving.value = false
  }
}

function addProfile(vendor: PushVendorKey = 'xiaomi') {
  pushConfig.profiles.push(createProfile(vendor))
}

function removeProfile(index: number) {
  pushConfig.profiles.splice(index, 1)
}

async function onTogglePushService(enable: boolean) {
  if (enable) {
    ElMessage.info('请通过服务开通流程启用推送服务')
    return
  }
  await ElMessageBox.confirm('确认关闭离线推送服务？', '关闭服务', {
    type: 'warning',
    confirmButtonText: '确认关闭',
    cancelButtonText: '取消',
  })
  if (!app.value) return
  await appApi.toggleService(app.value.appKey, selectedPlatform.value, 'PUSH', false)
  ElMessage.success('已关闭')
  await loadData()
}

function reloadConfig() {
  return loadData()
}

function copy(text: string) {
  navigator.clipboard.writeText(text)
  ElMessage.success('已复制')
}

onMounted(loadData)
onMounted(() => window.addEventListener('resize', updateViewport))
onBeforeUnmount(() => window.removeEventListener('resize', updateViewport))
</script>

<style scoped>
.mono {
  font-family: monospace;
  font-size: 12px;
}

.hint {
  font-size: 12px;
  color: #909399;
}

.info-card :deep(.el-descriptions__body) {
  overflow-x: auto;
}

.push-switch-row {
  margin-top: 12px;
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
}

.vendor-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 16px;
}

.vendor-card {
  min-height: 100%;
}

.vendor-hint {
  margin-bottom: 12px;
  font-size: 12px;
  color: #909399;
  line-height: 1.5;
}

.profiles-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}

.profiles-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.toolbar {
  margin-top: 16px;
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.profiles-table :deep(.el-select),
.profiles-table :deep(.el-input),
.profiles-table :deep(.el-input-number) {
  width: 100%;
}

@media (max-width: 767px) {
  .vendor-grid {
    grid-template-columns: 1fr;
  }

  .push-switch-row {
    flex-direction: column;
    align-items: flex-start;
  }

  .toolbar :deep(.el-button),
  .profiles-actions :deep(.el-button) {
    width: 100%;
  }

  .vendor-card :deep(.el-form-item__label) {
    padding-bottom: 4px;
  }
}
</style>
