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

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

import { Alert, Button, InputPassword, message, Modal as AModal, Tag } from 'ant-design-vue';

import { testSendOaRobot, updateOaRobotWebhook } from '#/views/system/oa-robot/api';

/**
 * OA 机器人「单独编辑推送地址」独立弹窗
 *
 * 设计意图：把 webhook_url 和 secret 的修改从「编辑基础信息」中剥离，
 * 避免用户在编辑名称/备注时无意中触发 webhook 重新加密写入。
 *
 * 关键交互：
 * - 顶部 Alert 警示：修改后立即生效，影响所有绑定该机器人的 OA 场景
 * - webhook_url 必填（不允许 mask）
 * - secret 选填，placeholder 提示「留空 = 清空加签」
 * - 内置「测试发送」按钮：保存前先用新地址测一次，避免改错导致线上通知失效
 * - 提交前 Modal.confirm 二次确认，避免误操作
 */

interface TestResultItem {
  message_type: string;
  name: string;
  success: boolean;
  message: string;
  response: any;
  cost_ms: number;
}

interface RobotRow {
  id: number;
  platform_code: string;
  name: string;
}

/** 当前操作的机器人（由列表行传入） */
const currentRobot = ref<RobotRow | null>(null);
/** webhook_url 输入值 */
const webhookUrl = ref('');
/** secret 输入值（空字符串表示清空） */
const secret = ref('');
/** 测试发送 loading */
const testing = ref(false);
/** 最近一次测试发送的结果列表 */
const testResults = ref<TestResultItem[]>([]);
/** 测试发送结果汇总提示 */
const testSummary = ref('');

/**
 * 测试发送：用「当前填写」的 webhook_url/secret 临时验证（不依赖数据库）
 * 与列表「测试」按钮的区别：列表测试用库里已存的密钥；本弹窗用表单新值
 */
async function handleTestSend() {
  if (!currentRobot.value?.id) {
    message.warning('机器人信息缺失');
    return;
  }
  if (!currentRobot.value.platform_code) {
    message.warning('平台编码缺失');
    return;
  }
  if (!webhookUrl.value || webhookUrl.value === '****') {
    message.warning('请填写 webhook 地址');
    return;
  }
  testing.value = true;
  testResults.value = [];
  testSummary.value = '正在发送测试消息，请稍候（最多 8 种类型）...';
  try {
    const result = await testSendOaRobot({
      // 注意：这里不传 id，强制用表单新值（不走后端兜底取密钥）
      platform_code: currentRobot.value.platform_code,
      webhook_url: webhookUrl.value,
      secret: secret.value || '',
      test_content: '萧康云医 OA 测试消息',
    });
    if (Array.isArray(result?.results)) {
      testResults.value = result.results;
      const total = result.total ?? result.results.length;
      const succ =
        result.success_count ??
        result.results.filter((r: any) => r.success).length;
      const fail = total - succ;
      testSummary.value = `共 ${total} 种类型，成功 ${succ} 种，失败 ${fail} 种`;
      if (fail === 0) {
        message.success(testSummary.value);
      } else if (succ === 0) {
        message.error(testSummary.value);
      } else {
        message.warning(testSummary.value);
      }
    } else if (result?.success !== undefined) {
      testResults.value = [
        {
          message_type: 'text',
          name: '文本消息',
          success: result.success,
          message: result.message || '',
          response: result.response,
          cost_ms: 0,
        },
      ];
      testSummary.value = result.success ? '测试发送成功' : '测试发送失败';
    }
  } finally {
    testing.value = false;
  }
}

const [Modal, modalApi] = useVbenModal({
  fullscreenButton: false,
  draggable: true,
  onCancel() {
    modalApi.close();
  },
  onConfirm: async () => {
    if (!currentRobot.value?.id) {
      message.warning('机器人信息缺失');
      return;
    }
    if (!webhookUrl.value) {
      message.warning('请填写 Webhook 地址');
      return;
    }
    if (webhookUrl.value === '****') {
      message.warning('请填写完整的 Webhook 地址（不允许 mask）');
      return;
    }
    // secret 为 mask 时报错（必须重新输入完整密钥或留空清空）
    if (secret.value && secret.value === '****') {
      message.warning('请填写完整的加签密钥或留空以清空');
      return;
    }
    // 二次确认：避免误改导致线上 OA 通知失效
    AModal.confirm({
      title: '确认修改推送地址？',
      content:
        '修改后将立即生效，会影响所有绑定该机器人的 OA 通知场景。是否继续？',
      okType: 'danger',
      onOk: async () => {
        modalApi.setState({ loading: true, confirmLoading: true });
        try {
          await updateOaRobotWebhook({
            id: currentRobot.value!.id,
            webhook_url: webhookUrl.value,
            secret: secret.value || '',
          });
          message.success('修改成功');
          const grid = modalApi.getData<{ gridApi?: any }>()?.gridApi;
          grid?.query?.();
          modalApi.close();
        } finally {
          modalApi.setState({ loading: false, confirmLoading: false });
        }
      },
    });
  },
  onOpenChange(isOpen: boolean) {
    if (isOpen) {
      const data = modalApi.getData<{ row: RobotRow; gridApi?: any }>();
      currentRobot.value = data?.row ?? null;
      // 每次打开都重置表单（不回显原 webhook/secret，强制用户重新输入，避免误操作）
      webhookUrl.value = '';
      secret.value = '';
      testResults.value = [];
      testSummary.value = '';
      if (currentRobot.value) {
        modalApi.setState({
          title: `编辑推送地址 - ${currentRobot.value.name}`,
          confirmLoading: false,
        });
      }
    }
  },
});
</script>

<template>
  <Modal title="编辑推送地址" class="w-[40%]">
    <!-- 顶部警示：修改后立即生效，影响线上 OA 通知 -->
    <Alert
      type="warning"
      show-icon
      message="修改 Webhook 地址后立即生效"
      description="会影响所有绑定该机器人的 OA 通知场景。建议先点「测试发送」验证新地址可用后再保存。"
      style="margin-bottom: 16px"
    />

    <!-- 表单：webhook_url 必填 + secret 选填 -->
    <div class="webhook-form">
      <div class="form-item">
        <label class="form-label">
          Webhook 地址 <span class="required-mark">*</span>
        </label>
        <InputPassword
          v-model:value="webhookUrl"
          placeholder="请粘贴新的 webhook URL"
          autocomplete="new-password"
        />
        <div class="form-hint">
          为防止误操作，编辑时不回显原地址，需完整粘贴新地址
        </div>
      </div>

      <div class="form-item">
        <label class="form-label">加签密钥</label>
        <InputPassword
          v-model:value="secret"
          placeholder="选填，留空表示清空加签密钥"
          autocomplete="new-password"
        />
        <div class="form-hint">
          若原机器人有加签密钥，请重新输入完整密钥；留空则清空原密钥
        </div>
      </div>
    </div>

    <!-- 测试结果展示区 -->
    <div v-if="testResults.length > 0 || testSummary" class="test-results">
      <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: 12px"
      />

      <div v-if="testResults.length > 0" class="result-list">
        <div
          v-for="item in testResults"
          :key="item.message_type"
          class="result-item"
        >
          <div class="result-header">
            <Tag :color="item.success ? 'success' : 'error'">
              {{ item.success ? '成功' : '失败' }}
            </Tag>
            <span class="result-name">{{ item.name }}</span>
            <span class="result-type">({{ item.message_type }})</span>
            <span v-if="item.cost_ms" class="result-cost">
              {{ item.cost_ms }}ms
            </span>
          </div>
          <div v-if="!item.success && item.message" class="result-error">
            {{ item.message }}
          </div>
        </div>
      </div>
    </div>

    <!-- 底部按钮：取消（默认）/ 测试发送（prepend）/ 确定修改（confirm） -->
    <template #prepend-footer>
      <Button type="default" :loading="testing" @click="handleTestSend">
        测试发送（全部类型）
      </Button>
    </template>
  </Modal>
</template>

<style scoped lang="scss">
/* 暗色适配：全部走 antd CSS 变量 */
.webhook-form {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.form-item {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.form-label {
  font-weight: 500;
  color: var(--ant-color-text, #1d2129);
  font-size: 13px;
}

.required-mark {
  color: var(--ant-color-error, #f53f3f);
  margin-left: 4px;
}

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

.test-results {
  margin-top: 16px;
  padding-top: 12px;
  border-top: 1px dashed var(--ant-color-border-secondary, #e5e6eb);
}

.result-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.result-item {
  padding: 8px 12px;
  border-radius: 4px;
  background: var(--ant-color-fill-quaternary, #f7f8fa);
  font-size: 12px;
}

.result-header {
  display: flex;
  align-items: center;
  gap: 6px;
}

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

.result-type {
  color: var(--ant-color-text-tertiary, #86909c);
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
}

.result-cost {
  margin-left: auto;
  color: var(--ant-color-text-tertiary, #86909c);
}

.result-error {
  margin-top: 4px;
  color: var(--ant-color-error, #f53f3f);
  word-break: break-all;
  line-height: 1.5;
}
</style>
