<template>
  <div class="governance-page">
    <a-row :gutter="16" class="summary-row">
      <a-col :xs="24" :sm="12" :lg="6" v-for="item in summaryItems" :key="item.label">
        <a-card :bordered="false" class="summary-card">
          <div class="summary-label">{{ item.label }}</div>
          <div class="summary-value">{{ item.value }}</div>
        </a-card>
      </a-col>
    </a-row>

    <a-card :bordered="false" class="panel-card">
      <template #title>运营治理</template>
      <template #extra>
        <a-space>
          <a-select v-model="hours" :style="{ width: '120px' }" @change="loadAll">
            <a-option :value="24">24 小时</a-option>
            <a-option :value="168">7 天</a-option>
            <a-option :value="720">30 天</a-option>
          </a-select>
          <a-input v-model="riskQuery.resource_uid" :style="{ width: '220px' }" allow-clear placeholder="resource_uid" />
          <a-input v-model="riskQuery.metric_code" :style="{ width: '160px' }" allow-clear placeholder="metric_code" />
          <a-button :loading="loading" :disabled="pageUnauthorized" @click="loadAll">
            <template #icon><icon-refresh /></template>
          </a-button>
        </a-space>
      </template>

      <PageState :status="pageStatus" :error-text="errorMessage" :partial-text="partialMessage" @retry="loadAll">
      <a-tabs v-if="pageStatus !== 'error' && pageStatus !== 'unauthorized'" default-active-key="quality">
        <a-tab-pane key="quality" title="告警质量">
          <a-table row-key="rule_id" :loading="loading" :data="qualityScores" :pagination="false">
            <template #columns>
              <a-table-column title="规则" data-index="rule_id" :width="100" />
              <a-table-column title="资源" data-index="resource_uid" :width="220" />
              <a-table-column title="质量分" data-index="score" :width="120">
                <template #cell="{ record }">
                  <a-progress :percent="record.score / 100" size="small" :color="scoreColor(record.score)" />
                </template>
              </a-table-column>
              <a-table-column title="重复" data-index="repeat_count" :width="100" />
              <a-table-column title="通知" data-index="notify_count" :width="100" />
              <a-table-column title="确认耗时" :width="140">
                <template #cell="{ record }">{{ formatDuration(record.avg_ack_seconds) }}</template>
              </a-table-column>
              <a-table-column title="解决耗时" :width="140">
                <template #cell="{ record }">{{ formatDuration(record.avg_resolve_seconds) }}</template>
              </a-table-column>
            </template>
          </a-table>
        </a-tab-pane>
        <a-tab-pane key="noise" title="噪声分析">
          <a-table row-key="window_start" :loading="loading" :data="noiseBuckets" :pagination="false">
            <template #columns>
              <a-table-column title="规则" data-index="rule_id" :width="100" />
              <a-table-column title="资源" data-index="resource_uid" :width="220" />
              <a-table-column title="业务系统" data-index="business_system_id" :width="120" />
              <a-table-column title="告警数" data-index="alert_count" :width="100" />
              <a-table-column title="通知数" data-index="notify_count" :width="100" />
              <a-table-column title="噪声分" data-index="noise_score" :width="100" />
              <a-table-column title="窗口" :width="260">
                <template #cell="{ record }">{{ record.window_start }} - {{ record.window_end }}</template>
              </a-table-column>
            </template>
          </a-table>
        </a-tab-pane>
        <a-tab-pane key="suggestions" title="规则建议">
          <a-list :data="suggestions" :bordered="false">
            <template #item="{ item }">
              <a-list-item>
                <a-list-item-meta :title="suggestionTitle(item)" :description="item.action" />
                <a-tag :color="item.priority === 'high' ? 'red' : 'orange'">{{ item.priority }}</a-tag>
              </a-list-item>
            </template>
          </a-list>
        </a-tab-pane>
        <a-tab-pane key="risk" title="容量风险">
          <a-descriptions v-if="capacityRisk" :data="riskDescriptions" bordered :column="2" />
          <a-empty v-else />
        </a-tab-pane>
        <a-tab-pane key="slo" title="SLO">
          <a-row :gutter="16">
            <a-col :xs="24" :lg="8">
              <a-statistic title="关闭工单" :value="sloDashboard?.total_closed || 0" />
            </a-col>
            <a-col :xs="24" :lg="8">
              <a-statistic title="总体违规" :value="sloDashboard?.overall_breached || 0" />
            </a-col>
            <a-col :xs="24" :lg="8">
              <a-statistic title="违规率" :value="(sloDashboard?.breach_rate || 0) * 100" :precision="1" suffix="%" />
            </a-col>
          </a-row>
          <a-table class="slo-table" row-key="key" :data="sloRows" :pagination="false">
            <template #columns>
              <a-table-column title="维度" data-index="key" />
              <a-table-column title="总数" data-index="total" />
              <a-table-column title="响应违规" data-index="response_breached" />
              <a-table-column title="解决违规" data-index="resolve_breached" />
              <a-table-column title="总体违规" data-index="breached" />
              <a-table-column title="违规率">
                <template #cell="{ record }">{{ percent(record.breach_rate) }}</template>
              </a-table-column>
            </template>
          </a-table>
        </a-tab-pane>
      </a-tabs>
      </PageState>
    </a-card>
  </div>
</template>

<script setup lang="ts">
import { computed, reactive, ref } from 'vue'
import { Message } from '@arco-design/web-vue'
import {
  fetchAlertNoise,
  fetchAlertQualityScores,
  fetchCapacityRisk,
  fetchRuleSuggestions,
  fetchSloDashboard,
  type AlertQualityScore,
  type CapacityRisk,
  type NoiseBucket,
  type RuleSuggestion,
  type SloDashboard,
} from '@/api/ops/governance'

const loading = ref(false)
const errorMessage = ref('')
const partialMessage = ref('')
const pageUnauthorized = ref(false)
const hours = ref(168)
const qualityScores = ref<AlertQualityScore[]>([])
const noiseBuckets = ref<NoiseBucket[]>([])
const suggestions = ref<RuleSuggestion[]>([])
const capacityRisk = ref<CapacityRisk | null>(null)
const sloDashboard = ref<SloDashboard | null>(null)
const riskQuery = reactive({ resource_uid: '', metric_code: 'cpu_usage' })

const unwrap = <T,>(res: any): T => res?.data ?? res?.details ?? res

const summaryItems = computed(() => [
  { label: '质量对象', value: qualityScores.value.length },
  { label: '高噪声窗口', value: noiseBuckets.value.filter((item) => item.noise_score >= 30).length },
  { label: '规则建议', value: suggestions.value.length },
  { label: 'SLO 违规', value: sloDashboard.value?.overall_breached || 0 },
])

const hasGovernanceData = computed(
  () => qualityScores.value.length || noiseBuckets.value.length || suggestions.value.length || capacityRisk.value || sloDashboard.value
)

const pageStatus = computed(() => {
  if (pageUnauthorized.value) return 'unauthorized'
  if (loading.value) return 'loading'
  if (errorMessage.value && !hasGovernanceData.value) return 'error'
  if (partialMessage.value) return 'partial'
  if (!hasGovernanceData.value) return 'empty'
  return 'success'
})

const isForbidden = (error: any) => error?.response?.status === 403 || error?.code === 403 || error?.code === 401

const loadErrorMessage = (error: any, fallback: string) => error?.message || fallback

const riskDescriptions = computed(() => {
  if (!capacityRisk.value) return []
  return [
    { label: '资源', value: capacityRisk.value.resource_uid || '-' },
    { label: '指标', value: capacityRisk.value.metric_code },
    { label: '当前值', value: `${capacityRisk.value.current_value}${capacityRisk.value.unit || ''}` },
    { label: '阈值', value: `${capacityRisk.value.threshold}${capacityRisk.value.unit || ''}` },
    { label: '每小时斜率', value: capacityRisk.value.slope_per_hour },
    { label: '风险', value: capacityRisk.value.risk_level },
    { label: '预测时间', value: capacityRisk.value.predicted_at || '-' },
    { label: '样本数', value: capacityRisk.value.sample_count },
  ]
})

const sloRows = computed(() => {
  const rows: any[] = []
  const dashboard = sloDashboard.value
  if (!dashboard) return rows
  Object.entries(dashboard.by_business_system || {}).forEach(([key, value]) => rows.push({ key: `业务 ${key}`, ...value }))
  Object.entries(dashboard.by_resource_category || {}).forEach(([key, value]) => rows.push({ key: `资源 ${key || '-'}`, ...value }))
  return rows
})

const loadAll = async () => {
  loading.value = true
  errorMessage.value = ''
  partialMessage.value = ''
  pageUnauthorized.value = false
  try {
    const [qualityRes, noiseRes, suggestionRes, riskRes, sloRes] = await Promise.allSettled([
      fetchAlertQualityScores({ hours: hours.value }),
      fetchAlertNoise({ hours: hours.value }),
      fetchRuleSuggestions({ hours: hours.value }),
      fetchCapacityRisk({
        resource_uid: riskQuery.resource_uid || undefined,
        metric_code: riskQuery.metric_code || undefined,
      }),
      fetchSloDashboard(),
    ])
    const settled = [qualityRes, noiseRes, suggestionRes, riskRes, sloRes]
    const firstRejected = settled.find((item) => item.status === 'rejected') as PromiseRejectedResult | undefined
    if (firstRejected?.reason && isForbidden(firstRejected.reason)) {
      pageUnauthorized.value = true
      errorMessage.value = '当前账号没有访问运营治理的权限。'
      return
    }
    if (qualityRes.status === 'fulfilled') qualityScores.value = unwrap<AlertQualityScore[]>(qualityRes.value) || []
    if (noiseRes.status === 'fulfilled') noiseBuckets.value = unwrap<NoiseBucket[]>(noiseRes.value) || []
    if (suggestionRes.status === 'fulfilled') suggestions.value = unwrap<RuleSuggestion[]>(suggestionRes.value) || []
    if (riskRes.status === 'fulfilled') capacityRisk.value = unwrap<CapacityRisk>(riskRes.value) || null
    if (sloRes.status === 'fulfilled') sloDashboard.value = unwrap<SloDashboard>(sloRes.value) || null
    if (settled.every((item) => item.status === 'rejected')) {
      errorMessage.value = loadErrorMessage(firstRejected?.reason, '加载治理数据失败')
      Message.error(errorMessage.value)
    } else if (firstRejected) {
      partialMessage.value = '治理数据部分加载失败，当前页面展示可用面板。'
    }
  } catch (error: any) {
    errorMessage.value = loadErrorMessage(error, '加载治理数据失败')
    Message.error(error.message || '加载治理数据失败')
  } finally {
    loading.value = false
  }
}

const scoreColor = (score: number) => {
  if (score >= 80) return '#00b42a'
  if (score >= 60) return '#ff7d00'
  return '#f53f3f'
}

const formatDuration = (seconds: number) => {
  if (!seconds) return '-'
  if (seconds < 3600) return `${Math.round(seconds / 60)} 分钟`
  return `${(seconds / 3600).toFixed(1)} 小时`
}

const percent = (value: number) => `${(value * 100).toFixed(1)}%`

const suggestionTitle = (item: RuleSuggestion) => `规则 ${item.rule_id} / ${item.reason}`

loadAll()
</script>

<script lang="ts">
export default {
  name: 'OpsGovernance',
}
</script>

<style scoped lang="less">
.governance-page {
  padding: 16px 20px 24px;
}

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

.summary-card {
  min-height: 96px;
}

.summary-label {
  color: var(--color-text-2);
  font-size: 13px;
}

.summary-value {
  margin-top: 12px;
  font-size: 28px;
  line-height: 1;
  font-weight: 600;
}

.panel-card {
  border-radius: 6px;
}

.slo-table {
  margin-top: 16px;
}

@media (max-width: 768px) {
  .governance-page {
    padding: 12px;
  }

  :deep(.arco-card-header) {
    flex-wrap: wrap;
    gap: 8px;
  }

  :deep(.arco-card-extra) {
    width: 100%;
  }

  :deep(.arco-card-extra .arco-space) {
    width: 100%;
    flex-wrap: wrap;
    justify-content: flex-start;
  }

  :deep(.arco-select),
  :deep(.arco-input-wrapper) {
    max-width: 100%;
  }

  :deep(.arco-table-container) {
    overflow-x: auto;
  }
}
</style>
