<script lang="ts" setup>
import { ref, computed } from 'vue';

import { useVbenModal } from '@vben/common-ui';

import dayjs from 'dayjs';

import {
  Alert,
  Descriptions,
  DescriptionsItem as DescItem,
  Tag,
  Timeline,
  TimelineItem,
  TypographyParagraph,
  TypographyText,
  TypographyTitle,
} from 'ant-design-vue';

/**
 * OA 机器人「测试发送结果」独立弹窗
 *
 * 设计要点：
 * - 顶部 Descriptions：全局上下文（机器人、平台、时间、测试内容、@）
 * - 底部 Timeline：每种消息类型一个节点，展示成功/失败 + 真实请求体 + 响应体
 * - 请求体来自后端 results[].request（渠道 buildPayload 的真实 HTTP body，已脱敏）
 * - 暗色模式全部走 antd 原生组件 + CSS 变量
 *
 * 数据来源：modalApi.getData()，由 test-send-modal.vue 的 onFinished 注入
 */

interface TestResultItem {
  message_type: string;
  name: string;
  success: boolean;
  message: string;
  /** 真实 HTTP 请求体（后端脱敏后） */
  request?: any;
  response: any;
  cost_ms: number;
}

/** 测试结果列表（由外部传入） */
const testResults = ref<TestResultItem[]>([]);
/** 测试汇总提示（由外部传入） */
const testSummary = ref('');
/** 机器人名称（上下文展示） */
const robotName = ref('');
/** 机器人 ID（上下文展示） */
const robotId = ref<number>();
/** 平台编码（上下文展示） */
const platformCode = ref('');
/** 测试内容（上下文展示） */
const testContent = ref('');
/** 是否 @ 全员（上下文展示） */
const testAtAll = ref(false);
/** @ 手机号列表（上下文展示） */
const testMobiles = ref<string[]>([]);
/** 发送完成时间戳（秒，上下文展示） */
const sentAt = ref<number>();

/**
 * @ 配置摘要（Descriptions 一行展示用）
 */
const atSummary = computed(() => {
  if (testAtAll.value) return '@ 全员';
  if (testMobiles.value.length === 0) return '无';
  return testMobiles.value.join('、');
});

/**
 * 格式化时间戳为可读字符串（秒级 → dayjs）
 */
function formatTime(ts?: number): string {
  return ts ? dayjs(ts * 1000).format('YYYY-MM-DD HH:mm:ss') : '-';
}

/**
 * 把对象格式化为可读 JSON 字符串（空对象显示「无」）
 * 用于请求体 / 响应体的 <pre> 展示
 */
function formatJson(data: any): string {
  if (data === null || data === undefined) return '无';
  if (typeof data === 'string') {
    // 后端偶发已是 JSON 字符串，尝试美化
    try {
      return JSON.stringify(JSON.parse(data), null, 2);
    } catch {
      return data || '无';
    }
  }
  if (typeof data === 'object' && Object.keys(data).length === 0) return '无';
  try {
    return JSON.stringify(data, null, 2);
  } catch {
    return String(data);
  }
}

const [Modal, modalApi] = useVbenModal({
  fullscreenButton: false,
  draggable: true,
  onCancel() {
    modalApi.close();
  },
  onConfirm: async () => {
    modalApi.close();
  },
  onOpenChange(isOpen: boolean) {
    if (isOpen) {
      const data = modalApi.getData<any>();
      testResults.value = data?.results ?? [];
      testSummary.value = data?.summary ?? '';
      robotName.value = data?.robotName ?? '';
      robotId.value = data?.robotId;
      platformCode.value = data?.platformCode ?? '';
      testContent.value = data?.testContent ?? '';
      testAtAll.value = !!data?.testAtAll;
      testMobiles.value = data?.testMobiles ?? [];
      sentAt.value = data?.sentAt;
      const suffix = robotName.value ? ` - ${robotName.value}` : '';
      modalApi.setState({
        title: `测试发送结果${suffix}`,
        confirmText: '知道了',
      });
    }
  },
});
</script>

<template>
  <Modal title="测试发送结果" class="w-[56%]">
    <!-- 1. 汇总提示 -->
    <Alert
      v-if="testSummary"
      :type="
        testResults.length === 0
          ? 'info'
          : testResults.every((r) => r.success)
            ? 'success'
            : testResults.some((r) => r.success)
              ? 'warning'
              : 'error'
      "
      :message="testSummary"
      show-icon
      style="margin-bottom: 16px"
    />

    <!-- 2. 发送详情（全局上下文） -->
    <Descriptions
      title="发送详情"
      :column="1"
      size="small"
      bordered
      style="margin-bottom: 16px"
    >
      <DescItem label="机器人">
        {{ robotName || '-' }}
        <span v-if="robotId" style="color: var(--ant-color-text-tertiary)">
          (id: {{ robotId }})
        </span>
      </DescItem>
      <DescItem label="平台">
        <Tag v-if="platformCode" color="processing">{{ platformCode }}</Tag>
        <span v-else>-</span>
      </DescItem>
      <DescItem label="发送时间">{{ formatTime(sentAt) }}</DescItem>
      <DescItem label="测试内容">
        <TypographyParagraph
          style="margin: 0; white-space: pre-wrap; word-break: break-all"
        >
          {{ testContent || '-' }}
        </TypographyParagraph>
      </DescItem>
      <DescItem label="@ 配置">{{ atSummary }}</DescItem>
    </Descriptions>

    <!-- 3. 各类型发送结果（含真实请求体 / 响应体） -->
    <TypographyTitle :level="5" style="margin-bottom: 12px">
      消息类型发送结果
    </TypographyTitle>
    <Timeline v-if="testResults.length > 0">
      <TimelineItem
        v-for="(item, idx) in testResults"
        :key="`${item.message_type}-${idx}`"
        :color="item.success ? 'green' : 'red'"
      >
        <!-- 标题行：名称 + 类型 Tag + 成功/失败 Tag + 耗时 -->
        <div class="timeline-row">
          <span class="timeline-name">{{ item.name }}</span>
          <Tag class="timeline-type">{{ item.message_type }}</Tag>
          <Tag :color="item.success ? 'success' : 'error'">
            {{ item.success ? '成功' : '失败' }}
          </Tag>
          <span v-if="item.cost_ms" class="timeline-cost">
            {{ item.cost_ms }}ms
          </span>
        </div>

        <!-- 渠道返回文案（成功 errmsg / 失败原因） -->
        <div v-if="item.message" class="timeline-msg" :class="{ error: !item.success }">
          {{ item.message }}
        </div>

        <!-- 真实请求体（渠道 buildPayload 结果，已脱敏） -->
        <div class="payload-block">
          <TypographyText type="secondary" class="payload-label">
            请求体
          </TypographyText>
          <pre class="payload-pre">{{ formatJson(item.request) }}</pre>
        </div>

        <!-- 第三方响应体 -->
        <div class="payload-block">
          <TypographyText type="secondary" class="payload-label">
            响应体
          </TypographyText>
          <pre class="payload-pre">{{ formatJson(item.response) }}</pre>
        </div>
      </TimelineItem>
    </Timeline>
    <TypographyText v-else type="secondary">
      无发送结果
    </TypographyText>
  </Modal>
</template>

<style scoped lang="scss">
/*
 * 暗色适配：颜色一律用 antd CSS 变量
 * pre 限高 + overflow，避免超长 JSON（尤其 image base64 截断前）撑爆弹窗
 */
.timeline-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.timeline-name {
  font-weight: 500;
  color: var(--ant-color-text, #1d2129);
}

.timeline-type {
  margin: 0;
}

.timeline-cost {
  color: var(--ant-color-text-tertiary, #86909c);
  font-size: 12px;
}

.timeline-msg {
  margin-top: 4px;
  font-size: 12px;
  line-height: 1.5;
  word-break: break-all;
  color: var(--ant-color-text-secondary, #4e5969);

  &.error {
    color: var(--ant-color-error, #f53f3f);
  }
}

.payload-block {
  margin-top: 8px;
}

.payload-label {
  display: block;
  font-size: 12px;
  margin-bottom: 4px;
}

.payload-pre {
  margin: 0;
  padding: 8px 10px;
  max-height: 180px;
  overflow: auto;
  font-size: 12px;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-all;
  border-radius: 4px;
  border: 1px solid var(--ant-color-border, #d9d9d9);
  background: var(--ant-color-fill-quaternary, rgba(0, 0, 0, 0.02));
  color: var(--ant-color-text, #1d2129);
}

/* 暗色：强制浅色字，避免 CSS 变量未注入时落入 #1d2129 黑底黑字 */
html.dark .payload-pre,
.dark .payload-pre {
  color: rgba(255, 255, 255, 0.88);
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(255, 255, 255, 0.16);
}

html.dark .timeline-name,
.dark .timeline-name {
  color: rgba(255, 255, 255, 0.88);
}

html.dark .timeline-msg:not(.error),
.dark .timeline-msg:not(.error) {
  color: rgba(255, 255, 255, 0.65);
}
</style>
