<template>
  <view class="phone-text-parser">
    <template v-for="(item, index) in parsedContent" :key="index">
      <view v-if="item.type === 'phone'" class="phone-number" @click="callPhone(item.text)">
        {{ item.text }}
      </view>
      <text v-else>{{ item.text }}</text>
    </template>
  </view>
</template>

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

// Props定义
const props = defineProps({
  // 要解析的文本内容
  text: {
    type: String,
    default: '',
    required: true,
  },
  // 是否立即拨打电话(false则需要用户点击确认)
  directCall: {
    type: Boolean,
    default: false,
  },
});

// 定义电话类型
interface TextSegment {
  type: 'text' | 'phone';
  text: string;
}

// 声明uni对象类型
declare const uni: any;

// 电话号码匹配正则表达式
// 匹配规则：
// 1. 手机号码: 1开头的11位数字
// 2. 座机号码: [2-9]开头的7-8位数字，可能有区号(3-4位)前缀，中间可能有-分隔
// 3. 特殊格式: 支持400、800等特殊号码
const phoneRegex = /(?:(?:\+|00)86)?(?:\s)?(?:(?:1[3-9]\d{9})|(?:(?:0\d{2,3}[-\s]?)?[2-9]\d{6,7})|(?:[4|8]00[-\s]?\d{3}[-\s]?\d{4}))/gu;

// 将文本内容解析为普通文本和电话号码的数组
const parsedContent = computed(() => {
  if (!props.text) {
    return [];
  }

  const result: TextSegment[] = [];
  let lastIndex = 0;

  // 为了避免在computed中的副作用，创建正则表达式的新实例
  const regex = new RegExp(phoneRegex.source, 'gu');
  let matchResult;

  while ((matchResult = regex.exec(props.text)) !== null) {
    const { 0: matchedText, index } = matchResult;

    // 添加匹配前的普通文本
    if (index > lastIndex) {
      result.push({
        type: 'text',
        text: props.text.substring(lastIndex, index),
      });
    }

    // 添加电话号码
    result.push({
      type: 'phone',
      text: matchedText,
    });

    // eslint-disable-next-line prefer-destructuring
    lastIndex = regex.lastIndex;
  }

  // 添加最后一部分普通文本
  if (lastIndex < props.text.length) {
    result.push({
      type: 'text',
      text: props.text.substring(lastIndex),
    });
  }

  return result;
});

// 拨打电话
const callPhone = (phoneNumber: string) => {
  // 清理电话号码中的非数字字符，保留+号
  const cleanedNumber = phoneNumber.replace(/[^\d+]/gu, '');

  if (props.directCall) {
    // 直接拨打电话
    uni.makePhoneCall({
      phoneNumber: cleanedNumber,
    });
  } else {
    // 弹窗确认后拨打
    uni.showModal({
      title: '拨打电话',
      content: cleanedNumber,
      confirmText: '拨打',
      cancelText: '取消',
      success(res: { confirm: boolean }) {
        const { confirm } = res;
        if (confirm) {
          uni.makePhoneCall({
            phoneNumber: cleanedNumber,
          });
        }
      },
    });
  }
};

// 暴露方法
defineExpose({
  callPhone,
});
</script>

<style lang="scss" scoped>
.phone-text-parser {
  display: inline;
  word-break: break-word;
}

.phone-number {
  display: inline;
  color: #007AFF;
  cursor: pointer;
  text-decoration: underline;

  &:hover {
    opacity: 0.8;
  }

  &:active {
    opacity: 0.6;
  }
}
</style>
