<script lang="ts" setup>
/**
 * OA 机器人行级测试发送弹窗
 * work_wechat_app：必须选接收员工或群聊；客户群需再选确认发送员工
 * webhook：沿用 @ 全员 / 手机号
 */
import { ref, computed, watch } from 'vue';

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

import { Alert, message, Radio, RadioGroup, Select, Switch, Textarea } from 'ant-design-vue';

import { getOaChatListByPlatform } from '#/views/system/oa-chat/api';
import { getOaWwUserList } from '#/views/system/oa-chat/api/org';
import {
  getOaRobotBoundScenes,
  testSendOaRobot,
} from '#/views/system/oa-robot/api';
import { isWorkWechatApp } from '#/views/system/oa-robot/config/form';

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;
}

interface OnFinishedPayload {
  results: TestResultItem[];
  summary: string;
  robotName?: string;
  robotId?: number;
  platformCode?: string;
  testContent?: string;
  testAtAll?: boolean;
  testMobiles?: string[];
  sentAt?: number;
}

const isFeishu = computed(() => currentRobot.value?.platform_code === 'feishu');
const isApp = computed(() =>
  isWorkWechatApp(currentRobot.value?.platform_code),
);

const currentRobot = ref<RobotRow | null>(null);
const testing = ref(false);
const testContent = ref('萧康云医 OA 测试消息');
const testAtAll = ref(false);
const testMobiles = ref<string[]>([]);
/** 应用 API：person | group */
const targetMode = ref<'person' | 'group'>('person');
const testUserid = ref<string | undefined>(undefined);
const testChatId = ref<number | undefined>(undefined);
const testSenderUserid = ref<string | undefined>(undefined);
const userOptions = ref<{ label: string; value: string }[]>([]);
const chatOptions = ref<
  { label: string; value: number; chat_kind: number }[]
>([]);
/** 该机器人已绑定的场景（可选：选中则只发场景配置类型） */
const boundScenes = ref<{ id: number; scene_code: string; scene_name: string }[]>(
  [],
);
const selectedSceneId = ref<number | undefined>(undefined);
const onFinished = ref<((payload: OnFinishedPayload) => void) | null>(null);

const selectedChatKind = computed(() => {
  const hit = chatOptions.value.find((c) => c.value === testChatId.value);
  return hit?.chat_kind ?? 0;
});

const [Modal, modalApi] = useVbenModal({
  fullscreenButton: false,
  draggable: true,
  onCancel() {
    modalApi.close();
  },
  onConfirm: async () => {
    await handleTestSend();
  },
  onOpenChange(isOpen: boolean) {
    if (isOpen) {
      const data = modalApi.getData<{
        row: RobotRow;
        onFinished?: (payload: OnFinishedPayload) => void;
      }>();
      currentRobot.value = data?.row ?? null;
      onFinished.value = data?.onFinished ?? null;
      testContent.value = '萧康云医 OA 测试消息';
      testAtAll.value = false;
      testMobiles.value = [];
      targetMode.value = 'person';
      testUserid.value = undefined;
      testChatId.value = undefined;
      testSenderUserid.value = undefined;
      selectedSceneId.value = undefined;
      boundScenes.value = [];
      if (currentRobot.value) {
        modalApi.setState({
          title: `测试发送 - ${currentRobot.value.name}`,
          confirmLoading: false,
        });
        loadBoundScenes(currentRobot.value.id);
        if (isWorkWechatApp(currentRobot.value.platform_code)) {
          loadAppOptions();
        }
      }
    }
  },
});

watch(testAtAll, (val) => {
  if (val) {
    testMobiles.value = [];
  }
});

watch(targetMode, () => {
  testUserid.value = undefined;
  testChatId.value = undefined;
  testSenderUserid.value = undefined;
});

async function loadBoundScenes(robotId: number) {
  try {
    const res = await getOaRobotBoundScenes(robotId);
    const list = Array.isArray(res) ? res : (res as any)?.data || [];
    boundScenes.value = (Array.isArray(list) ? list : []).map((s: any) => ({
      id: Number(s.id),
      scene_code: String(s.scene_code || ''),
      scene_name: String(s.scene_name || ''),
    }));
  } catch (e) {
    console.error(e);
    boundScenes.value = [];
  }
}

async function loadAppOptions() {
  try {
    const [userRes, chatRes] = await Promise.all([
      getOaWwUserList({
        platform_code: 'work_wechat_app',
        page: 1,
        pageSize: 200,
      }),
      getOaChatListByPlatform(),
    ]);
    const userData = userRes?.data ?? userRes ?? {};
    const items = Array.isArray(userData.items) ? userData.items : [];
    userOptions.value = items.map((u: any) => ({
      label: u.name ? `${u.name}（${u.userid}）` : u.userid,
      value: String(u.userid),
    }));
    const grouped = chatRes?.data ?? chatRes ?? {};
    const list = grouped.work_wechat_app || [];
    chatOptions.value = (Array.isArray(list) ? list : []).map((c: any) => ({
      label: `${c.name}${Number(c.chat_kind) === 2 ? '（客户群·需确认）' : '（应用群）'}`,
      value: Number(c.id),
      chat_kind: Number(c.chat_kind ?? 2),
    }));
  } catch (e) {
    console.error(e);
    userOptions.value = [];
    chatOptions.value = [];
  }
}

async function handleTestSend() {
  if (!currentRobot.value?.id) {
    message.warning('机器人信息缺失');
    return;
  }
  if (!testContent.value.trim()) {
    message.warning('请填写测试内容');
    return;
  }
  if (isApp.value) {
    // 选了场景时后端优先用场景 targets，可不强制弹窗选人/选群
    if (!selectedSceneId.value) {
      if (targetMode.value === 'person' && !testUserid.value) {
        message.warning('请选择接收员工');
        return;
      }
      if (targetMode.value === 'group' && !testChatId.value) {
        message.warning('请选择接收群聊');
        return;
      }
      if (
        targetMode.value === 'group' &&
        selectedChatKind.value === 2 &&
        !testSenderUserid.value
      ) {
        message.warning('客户群请选择确认发送员工');
        return;
      }
    }
  }
  testing.value = true;
  modalApi.setState({ confirmLoading: true });
  try {
    const payload: Record<string, any> = {
      id: currentRobot.value.id,
      platform_code: currentRobot.value.platform_code,
      test_content: testContent.value,
      test_at_all: testAtAll.value,
      test_mobiles: isFeishu.value ? [] : testMobiles.value,
    };
    if (selectedSceneId.value) {
      payload.scene_id = selectedSceneId.value;
    }
    if (isApp.value) {
      if (targetMode.value === 'person') {
        payload.test_userid = testUserid.value;
      } else {
        payload.test_chat_id = testChatId.value;
        if (selectedChatKind.value === 2) {
          payload.test_sender_userid = testSenderUserid.value;
        }
      }
    }
    const result = await testSendOaRobot(payload);

    let results: TestResultItem[] = [];
    let summary = '';
    if (Array.isArray(result?.results)) {
      results = 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;
      summary = selectedSceneId.value
        ? `按场景发送：共 ${total} 条，成功 ${succ}，失败 ${fail}`
        : `共 ${total} 种类型，成功 ${succ} 种，失败 ${fail} 种`;
    } else if (result?.success !== undefined) {
      results = [
        {
          message_type: 'text',
          name: '文本消息',
          success: result.success,
          message: result.message || '',
          response: result.response,
          cost_ms: 0,
        },
      ];
      summary = result.success ? '测试发送成功' : '测试发送失败';
    }

    modalApi.close();
    if (onFinished.value) {
      onFinished.value({
        results,
        summary,
        robotName: currentRobot.value.name,
        robotId: currentRobot.value.id,
        platformCode: currentRobot.value.platform_code,
        testContent: testContent.value,
        testAtAll: testAtAll.value,
        testMobiles: isFeishu.value ? [] : testMobiles.value,
        sentAt: Math.floor(Date.now() / 1000),
      });
    }
  } finally {
    testing.value = false;
    modalApi.setState({ confirmLoading: false });
  }
}
</script>

<template>
  <Modal title="测试发送" class="w-[42%]">
    <div class="test-form">
      <div class="form-item">
        <label class="form-label">测试内容</label>
        <Textarea
          v-model:value="testContent"
          :rows="2"
          placeholder="请输入测试内容（如：萧康云医 OA 测试消息）"
        />
      </div>

      <!-- 绑定场景：选中后只发场景配置的消息类型，不循环全类型 -->
      <div v-if="boundScenes.length > 0" class="form-item">
        <label class="form-label">按场景发送（可选）</label>
        <Select
          v-model:value="selectedSceneId"
          allow-clear
          show-search
          class="w-full"
          placeholder="不选则测试该平台全部消息类型"
          :options="
            boundScenes.map((s) => ({
              label: `${s.scene_name}（${s.scene_code}）`,
              value: s.id,
            }))
          "
          :filter-option="
            (input: string, option: any) =>
              String(option?.label || '')
                .toLowerCase()
                .includes(input.toLowerCase())
          "
        />
        <div v-if="selectedSceneId" class="form-hint">
          将只发送该场景已配置的消息类型与内容（可用上方测试内容覆盖正文）
        </div>
      </div>

      <!-- 应用 API：必选投递目标（选场景时可作兜底） -->
      <template v-if="isApp && !selectedSceneId">
        <div class="form-item">
          <label class="form-label">接收对象</label>
          <RadioGroup v-model:value="targetMode">
            <Radio value="person">员工（个人消息）</Radio>
            <Radio value="group">群聊</Radio>
          </RadioGroup>
        </div>
        <div v-if="targetMode === 'person'" class="form-item">
          <label class="form-label">接收员工</label>
          <Select
            v-model:value="testUserid"
            show-search
            allow-clear
            :options="userOptions"
            placeholder="选择企微员工 userid"
            class="w-full"
            :filter-option="
              (input: string, option: any) =>
                String(option?.label || '')
                  .toLowerCase()
                  .includes(input.toLowerCase())
            "
          />
        </div>
        <div v-else class="form-item">
          <label class="form-label">接收群聊</label>
          <Select
            v-model:value="testChatId"
            show-search
            allow-clear
            :options="chatOptions"
            placeholder="选择群聊"
            class="w-full"
            :filter-option="
              (input: string, option: any) =>
                String(option?.label || '')
                  .toLowerCase()
                  .includes(input.toLowerCase())
            "
          />
        </div>
        <div v-if="targetMode === 'group' && selectedChatKind === 2" class="form-item">
          <label class="form-label">确认发送员工</label>
          <Select
            v-model:value="testSenderUserid"
            show-search
            allow-clear
            :options="userOptions"
            placeholder="客户群群发需员工在企微确认"
            class="w-full"
            :filter-option="
              (input: string, option: any) =>
                String(option?.label || '')
                  .toLowerCase()
                  .includes(input.toLowerCase())
            "
          />
          <span class="form-hint">对应企微 add_msg_template.sender，非实时</span>
        </div>
        <Alert
          type="info"
          show-icon
          message="应用 API 测试请在本弹窗选择接收对象；保存机器人仅配置凭证"
          class="form-alert"
        />
      </template>

      <template v-else>
        <div class="form-item">
          <label class="form-label">@ 所有人</label>
          <Switch v-model:checked="testAtAll" />
          <span class="form-hint">开启后所有消息类型都按 @ 全员发送</span>
        </div>
        <div v-if="!isFeishu" class="form-item">
          <label class="form-label">@ 手机号</label>
          <Select
            v-model:value="testMobiles"
            mode="tags"
            :disabled="testAtAll"
            placeholder="输入手机号后回车添加"
            :token-separators="[',', ' ']"
            class="w-full"
          />
        </div>
        <Alert
          v-if="isFeishu"
          type="info"
          show-icon
          message="飞书 webhook 不支持手机号 @，仅 @ 所有人有效"
          class="form-alert"
        />
      </template>
    </div>
  </Modal>
</template>

<style scoped lang="scss">
.test-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.form-item {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.form-label {
  font-weight: 500;
  color: var(--ant-color-text, #1d2129);
  font-size: 13px;
}
.form-hint {
  color: var(--ant-color-text-tertiary, #86909c);
  font-size: 12px;
}
.form-alert {
  margin-top: 4px;
}
</style>
