<template>
  <div class="business-system-detail-page">
    <a-page-header :title="system?.name || '业务系统详情'" :subtitle="system?.code" @back="goBack">
      <template #extra>
        <a-button type="primary" :loading="loading" :disabled="pageUnauthorized" @click="fetchAll">
          <template #icon><icon-refresh /></template>
          刷新
        </a-button>
      </template>
    </a-page-header>

    <PageState :status="pageStatus" :error-text="errorMessage" @retry="fetchAll">
    <a-row :gutter="16" class="summary-row">
      <a-col :xs="24" :md="8">
        <a-card :bordered="false" class="summary-card">
          <div class="summary-label">健康分</div>
          <div class="health-summary">
            <span :class="healthClass(healthScore)">{{ scoreText(healthScore) }}</span>
            <a-tag :color="healthTagColor(healthScore)">{{ health?.health?.level || 'healthy' }}</a-tag>
          </div>
          <div class="health-track">
            <span :class="healthClass(healthScore)" :style="{ width: `${scoreValue(healthScore)}%` }" />
          </div>
        </a-card>
      </a-col>
      <a-col :xs="24" :md="8">
        <a-card :bordered="false" class="summary-card">
          <div class="summary-label">影响范围</div>
          <div class="summary-value">{{ topology?.resources?.length || members.length || 0 }}</div>
          <div class="summary-hint">受影响资源</div>
        </a-card>
      </a-col>
      <a-col :xs="24" :md="8">
        <a-card :bordered="false" class="summary-card">
          <div class="summary-label">活跃 Incident</div>
          <div class="summary-value danger">{{ health?.signal_counts?.active_incidents || 0 }}</div>
          <div class="summary-hint">未关闭事件</div>
        </a-card>
      </a-col>
    </a-row>

    <a-row :gutter="16">
      <a-col :xs="24" :xl="15">
        <a-card :bordered="false" title="业务拓扑" class="section-card">
          <div v-if="topologyNodes.length" class="topology-panel">
            <div v-for="node in topologyNodes" :key="node.node_id || node.resource_uid" class="topology-node">
              <div class="node-icon" :class="nodeStatusClass(node.status)">
                <icon-apps />
              </div>
              <div class="node-content">
                <div class="node-title">{{ node.label }}</div>
                <div class="node-meta">{{ node.resource_uid || node.type }}</div>
              </div>
              <a-tag :color="statusColor(node.status)">{{ node.status || 'unknown' }}</a-tag>
            </div>
          </div>
          <a-empty v-else description="暂无拓扑节点" />
          <a-divider orientation="left">链路与业务依赖</a-divider>
          <a-row :gutter="12">
            <a-col :xs="24" :lg="12">
              <a-table row-key="id" :data="topologyLinks" :pagination="false" size="small">
                <template #columns>
                  <a-table-column title="源节点" data-index="source_node_id" />
                  <a-table-column title="目标节点" data-index="target_node_id" />
                </template>
              </a-table>
            </a-col>
            <a-col :xs="24" :lg="12">
              <a-table row-key="id" :data="businessDependencies" :pagination="false" size="small">
                <template #columns>
                  <a-table-column title="依赖业务 ID" data-index="depends_on_business_system_id" :width="110" />
                  <a-table-column title="类型" data-index="dependency_type" :width="100" />
                  <a-table-column title="重要性" data-index="criticality" :width="90">
                    <template #cell="{ record }">
                      <a-tag :color="criticalityColor(record.criticality)">{{ record.criticality }}</a-tag>
                    </template>
                  </a-table-column>
                  <a-table-column title="说明" data-index="description" />
                </template>
              </a-table>
            </a-col>
          </a-row>
        </a-card>

        <a-card :bordered="false" title="业务时间线" class="section-card">
          <a-timeline v-if="timeline.length">
            <a-timeline-item v-for="item in timeline" :key="`${item.source}-${item.source_id}-${item.occurred_at}`" :label="formatTime(item.occurred_at)">
              <div class="timeline-title">
                <a-tag size="small" :color="sourceColor(item.source)">{{ sourceText(item.source) }}</a-tag>
                <span>{{ item.title || '-' }}</span>
              </div>
              <div class="timeline-message">{{ item.message || '-' }}</div>
              <a-typography-text v-if="timelineResourceUID(item)" class="timeline-resource" copyable>
                {{ timelineResourceUID(item) }}
              </a-typography-text>
            </a-timeline-item>
          </a-timeline>
          <a-empty v-else description="暂无时间线" />
        </a-card>
      </a-col>

      <a-col :xs="24" :xl="9">
        <a-card :bordered="false" title="基础信息" class="section-card">
          <a-descriptions :column="1" bordered size="medium">
            <a-descriptions-item label="编码">{{ system?.code || '-' }}</a-descriptions-item>
            <a-descriptions-item label="类型">{{ system?.system_type || '-' }}</a-descriptions-item>
            <a-descriptions-item label="状态">{{ system?.status || '-' }}</a-descriptions-item>
            <a-descriptions-item label="责任人">{{ system?.owner_user_id || '-' }}</a-descriptions-item>
            <a-descriptions-item label="部门">{{ system?.department_id || '-' }}</a-descriptions-item>
            <a-descriptions-item label="描述">{{ system?.description || '-' }}</a-descriptions-item>
          </a-descriptions>
        </a-card>

        <a-card :bordered="false" title="健康因素" class="section-card">
          <a-list v-if="healthFactors.length" :bordered="false" size="small">
            <a-list-item v-for="factor in healthFactors" :key="factor.key">
              <a-list-item-meta :title="factor.label" :description="factor.description" />
              <template #actions>
                <a-tag :color="factor.value > 0 ? 'orange' : 'green'">-{{ factor.value }}</a-tag>
              </template>
            </a-list-item>
          </a-list>
          <a-empty v-else description="暂无扣分项" />
        </a-card>

        <a-card :bordered="false" title="资源成员" class="section-card">
          <a-table row-key="resource_uid" :data="members" :pagination="false" size="small">
            <template #columns>
              <a-table-column title="资源 UID" data-index="resource_uid" />
              <a-table-column title="角色" data-index="role" :width="90" />
              <a-table-column title="重要性" data-index="criticality" :width="90">
                <template #cell="{ record }">
                  <a-tag :color="criticalityColor(record.criticality)">{{ record.criticality || 'medium' }}</a-tag>
                </template>
              </a-table-column>
            </template>
          </a-table>
        </a-card>

        <a-card :bordered="false" title="笔记" class="section-card">
          <a-form :model="noteForm" layout="vertical" class="note-form">
            <a-form-item field="title" label="标题">
              <a-input v-model="noteForm.title" allow-clear placeholder="输入笔记标题" />
            </a-form-item>
            <a-form-item field="content" label="内容">
              <a-textarea v-model="noteForm.content" :auto-size="{ minRows: 3, maxRows: 5 }" placeholder="记录业务处置、变更或观察" />
            </a-form-item>
            <a-button type="primary" long :loading="noteSaving" :disabled="pageUnauthorized" @click="submitNote">保存笔记</a-button>
          </a-form>
          <a-list v-if="notes.length" :bordered="false" size="small" class="note-list">
            <a-list-item v-for="note in notes" :key="note.id">
              <a-list-item-meta :title="note.title || formatTime(note.occurred_at)" :description="note.content" />
            </a-list-item>
          </a-list>
        </a-card>

        <a-card :bordered="false" title="关联知识" class="section-card">
          <a-form :model="documentForm" layout="vertical" class="document-form">
            <a-form-item field="title" label="标题">
              <a-input v-model="documentForm.title" allow-clear placeholder="知识库条目或外部文档标题" />
            </a-form-item>
            <a-form-item field="url" label="链接">
              <a-input v-model="documentForm.url" allow-clear placeholder="https:// 或知识库访问地址" />
            </a-form-item>
            <a-form-item field="link_type" label="类型">
              <a-select v-model="documentForm.link_type">
                <a-option value="knowledge">知识库</a-option>
                <a-option value="runbook">应急预案</a-option>
                <a-option value="external">外部文档</a-option>
              </a-select>
            </a-form-item>
            <a-button type="primary" long :loading="documentSaving" :disabled="pageUnauthorized" @click="submitDocument">新增链接</a-button>
          </a-form>
          <a-list v-if="documents.length" :bordered="false" size="small">
            <a-list-item v-for="item in documents" :key="item.id">
              <a-list-item-meta :title="item.title" :description="`${item.link_type} / ${item.url}`" />
            </a-list-item>
          </a-list>
          <a-empty v-else description="暂无关联知识" />
        </a-card>
      </a-col>
    </a-row>
    </PageState>
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, reactive, ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { Message } from '@arco-design/web-vue'
import { IconApps, IconRefresh } from '@arco-design/web-vue/es/icon'
import {
  createBusinessDocumentLink,
  createBusinessNote,
  fetchBusinessDocumentLinks,
  fetchBusinessHealth,
  fetchBusinessMembers,
  fetchBusinessNotes,
  fetchBusinessSystemDetail,
  fetchBusinessTimeline,
  fetchBusinessTopology,
  type BusinessDocumentLink,
  type BusinessHealth,
  type BusinessNote,
  type BusinessResourceMember,
  type BusinessSystemItem,
  type BusinessTimelineItem,
  type BusinessTopology,
} from '@/api/ops/businessSystem'

const route = useRoute()
const router = useRouter()
const system = ref<BusinessSystemItem | null>(null)
const health = ref<BusinessHealth | null>(null)
const topology = ref<BusinessTopology | null>(null)
const loading = ref(false)
const errorMessage = ref('')
const pageUnauthorized = ref(false)
const members = ref<BusinessResourceMember[]>([])
const timeline = ref<BusinessTimelineItem[]>([])
const notes = ref<BusinessNote[]>([])
const documents = ref<BusinessDocumentLink[]>([])
const noteSaving = ref(false)
const documentSaving = ref(false)

const noteForm = reactive({
  title: '',
  content: '',
})

const documentForm = reactive({
  title: '',
  url: '',
  link_type: 'knowledge',
})

const businessSystemID = computed(() => {
  const raw = Array.isArray(route.query.id) ? route.query.id[0] : route.query.id
  const id = Number(raw)
  return Number.isFinite(id) && id > 0 ? id : 0
})

const topologyNodes = computed(() => topology.value?.nodes || [])
const topologyLinks = computed(() => topology.value?.links || [])
const businessDependencies = computed(() => topology.value?.dependencies || [])
const healthScore = computed(() => health.value?.health?.score ?? 100)
const healthFactors = computed(() => {
  const deductions = health.value?.health?.deductions || {}
  const labels: Record<string, string> = {
    incidents: '活跃 Incident',
    resources: '资源健康',
    url_probes: 'URL 探测',
    sla: 'SLA 状态',
  }
  return Object.entries(deductions)
    .filter(([, value]) => value > 0)
    .map(([key, value]) => ({
      key,
      value,
      label: labels[key] || key,
      description: `${labels[key] || key} 影响健康分 ${value} 分`,
    }))
})

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

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

const setLoadError = (error: any, fallback: string) => {
  if (isForbidden(error)) {
    pageUnauthorized.value = true
    errorMessage.value = '当前账号没有访问业务系统详情的权限。'
    return
  }
  errorMessage.value = error?.message || fallback
}

const scoreValue = (score?: number) => Math.max(0, Math.min(100, Number(score ?? 100)))
const scoreText = (score?: number) => `${scoreValue(score)}`

const healthClass = (score?: number) => {
  const value = scoreValue(score)
  if (value >= 85) return 'health-good'
  if (value >= 65) return 'health-warn'
  return 'health-bad'
}

const healthTagColor = (score?: number) => {
  const value = scoreValue(score)
  if (value >= 85) return 'green'
  if (value >= 65) return 'orange'
  return 'red'
}

const statusColor = (status?: string) => {
  const map: Record<string, string> = {
    online: 'green',
    active: 'green',
    healthy: 'green',
    warning: 'orange',
    degraded: 'orange',
    offline: 'red',
    error: 'red',
    critical: 'red',
    unknown: 'gray',
  }
  return map[status || 'unknown'] || 'gray'
}

const criticalityColor = (value?: string) => {
  const map: Record<string, string> = {
    high: 'red',
    critical: 'red',
    medium: 'orange',
    low: 'gray',
  }
  return value ? map[value] || 'gray' : 'gray'
}

const nodeStatusClass = (status?: string) => {
  const color = statusColor(status)
  if (color === 'green') return 'node-good'
  if (color === 'orange') return 'node-warn'
  if (color === 'red') return 'node-bad'
  return 'node-unknown'
}

const sourceText = (source?: string) => {
  const map: Record<string, string> = {
    raw_event: '原始事件',
    alert: '告警',
    incident: 'Incident',
    ticket: '工单',
    note: '笔记',
    document: '知识',
  }
  return source ? map[source] || source : '-'
}

const sourceColor = (source?: string) => {
  const map: Record<string, string> = {
    raw_event: 'gray',
    alert: 'orange',
    incident: 'red',
    ticket: 'blue',
    note: 'arcoblue',
    document: 'green',
  }
  return source ? map[source] || 'gray' : 'gray'
}

const formatTime = (value?: string) => {
  if (!value) return '-'
  const date = new Date(value)
  if (Number.isNaN(date.getTime())) return value
  return date.toLocaleString('zh-CN')
}

const timelineResourceUID = (item: BusinessTimelineItem) => {
  const value = item.metadata?.resource_uid
  return typeof value === 'string' ? value : ''
}

const fetchAll = async () => {
  const id = businessSystemID.value
  if (!id) {
    errorMessage.value = '缺少业务系统 ID'
    Message.error(errorMessage.value)
    return
  }
  loading.value = true
  errorMessage.value = ''
  pageUnauthorized.value = false
  try {
    const [detailRes, healthRes, membersRes, topologyRes, timelineRes, notesRes, documentsRes] = await Promise.all([
      fetchBusinessSystemDetail(id),
      fetchBusinessHealth(id),
      fetchBusinessMembers(id),
      fetchBusinessTopology(id),
      fetchBusinessTimeline(id, { limit: 100 }),
      fetchBusinessNotes(id),
      fetchBusinessDocumentLinks(id),
    ])
    system.value = detailRes.details || null
    health.value = healthRes.details || null
    members.value = membersRes.details?.list || []
    topology.value = topologyRes.details || null
    timeline.value = timelineRes.details?.list || []
    notes.value = notesRes.details?.list || []
    documents.value = documentsRes.details?.list || []
  } catch (error) {
    console.error('获取业务系统详情失败:', error)
    setLoadError(error, '获取业务系统详情失败')
    Message.error('获取业务系统详情失败')
  } finally {
    loading.value = false
  }
}

const submitNote = async () => {
  const id = businessSystemID.value
  if (!id) return
  if (!noteForm.title.trim() || !noteForm.content.trim()) {
    Message.warning('请填写笔记标题和内容')
    return
  }
  noteSaving.value = true
  try {
    await createBusinessNote(id, {
      title: noteForm.title.trim(),
      content: noteForm.content.trim(),
    })
    noteForm.title = ''
    noteForm.content = ''
    Message.success('笔记已保存')
    const [notesRes, timelineRes] = await Promise.all([fetchBusinessNotes(id), fetchBusinessTimeline(id, { limit: 100 })])
    notes.value = notesRes.details?.list || []
    timeline.value = timelineRes.details?.list || []
  } catch (error) {
    console.error('保存笔记失败:', error)
    Message.error('保存笔记失败')
  } finally {
    noteSaving.value = false
  }
}

const submitDocument = async () => {
  const id = businessSystemID.value
  if (!id) return
  if (!documentForm.title.trim() || !documentForm.url.trim()) {
    Message.warning('请填写文档标题和链接')
    return
  }
  documentSaving.value = true
  try {
    await createBusinessDocumentLink(id, {
      title: documentForm.title.trim(),
      url: documentForm.url.trim(),
      link_type: documentForm.link_type,
    })
    documentForm.title = ''
    documentForm.url = ''
    documentForm.link_type = 'knowledge'
    Message.success('文档链接已新增')
    const documentsRes = await fetchBusinessDocumentLinks(id)
    documents.value = documentsRes.details?.list || []
  } catch (error) {
    console.error('新增文档链接失败:', error)
    Message.error('新增文档链接失败')
  } finally {
    documentSaving.value = false
  }
}

const goBack = () => {
  router.push('/business-system')
}

onMounted(fetchAll)
</script>

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

<style scoped lang="less">
.business-system-detail-page {
  padding: 16px;
}

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

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

.summary-label {
  color: var(--color-text-3);
  font-size: 13px;
  margin-bottom: 8px;
}

.summary-value {
  color: var(--color-text-1);
  font-size: 26px;
  font-weight: 600;
  line-height: 1.2;
}

.summary-value.danger {
  color: rgb(var(--red-6));
}

.summary-hint {
  margin-top: 8px;
  color: var(--color-text-3);
}

.health-summary {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 14px;
}

.health-summary span:first-child {
  font-size: 28px;
  font-weight: 700;
}

.health-track {
  height: 9px;
  overflow: hidden;
  background: var(--color-fill-3);
  border-radius: 5px;
}

.health-track span {
  display: block;
  height: 100%;
  border-radius: 5px;
}

.health-good {
  color: rgb(var(--green-6));
  background: rgb(var(--green-6));
}

.health-warn {
  color: rgb(var(--orange-6));
  background: rgb(var(--orange-6));
}

.health-bad {
  color: rgb(var(--red-6));
  background: rgb(var(--red-6));
}

.section-card {
  margin-bottom: 16px;
}

.topology-panel {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 12px;
}

.topology-node {
  display: grid;
  grid-template-columns: 36px minmax(0, 1fr) auto;
  gap: 10px;
  align-items: center;
  min-height: 70px;
  padding: 12px;
  border: 1px solid var(--color-border-2);
  border-radius: 6px;
  background: var(--color-fill-1);
}

.node-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 6px;
  color: #fff;
}

.node-good {
  background: rgb(var(--green-6));
}

.node-warn {
  background: rgb(var(--orange-6));
}

.node-bad {
  background: rgb(var(--red-6));
}

.node-unknown {
  background: rgb(var(--gray-6));
}

.node-content {
  min-width: 0;
}

.node-title {
  overflow: hidden;
  color: var(--color-text-1);
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.node-meta {
  overflow: hidden;
  margin-top: 4px;
  color: var(--color-text-3);
  font-size: 12px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.timeline-title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 600;
}

.timeline-message {
  margin-top: 6px;
  color: var(--color-text-2);
  word-break: break-word;
}

.timeline-resource {
  display: inline-block;
  margin-top: 6px;
}

.note-form {
  margin-bottom: 12px;
}

.document-form {
  margin-bottom: 12px;
}

.note-list {
  margin-top: 12px;
}

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

  .topology-panel {
    grid-template-columns: 1fr;
  }

  .topology-node {
    grid-template-columns: 32px minmax(0, 1fr);
  }

  .topology-node .arco-tag {
    grid-column: 2;
    width: fit-content;
  }

  .timeline-title {
    align-items: flex-start;
    flex-direction: column;
  }

  :deep(.arco-page-header-wrapper) {
    padding-right: 0;
    padding-left: 0;
  }

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