<template>
  <wd-root-portal>
    <wd-config-provider :theme-vars="themeVars">
      <wd-popup v-model="dialogVisible" position="center" z-index="1099" modal-style="z-index:1000"
        :close-on-click-modal="false" custom-style="width: 80%; border-radius: 16rpx; overflow: hidden;">
        <view class="message">
          <view class="message-title">{{ apiTitle || title || '提示' }}</view>
          <view class="message-content">
            <slot />
            <view v-if="apiContent || content">
              {{ apiContent || content }}
            </view>
            <view v-if="apiShowInput" class="message-input">
              <input 
                class="message-input-field" 
                v-model="apiInputValue" 
                :placeholder="apiInputPlaceholder"
                @input="inputErrorVisible = false"
              />
              <view v-if="inputErrorVisible" class="message-input-error">{{ apiInputError }}</view>
              <view v-if="apiTips.length > 0" class="message-input-tips">
                <text v-for="(tip, index) in apiTips" :key="index" class="message-input-tip">{{ tip }}</text>
              </view>
            </view>
          </view>
        </view>
        <view class="message-bt">
          <wd-button v-if="!apiHideCancel && !hideCancel" :loading="cancelLoading" plain block custom-class="message-bt-item"
            @click="handleCancel">
            {{ apiTextCancel || textCancel || '取消' }}
          </wd-button>
          <wd-button v-if="showGetPhoneNumber" :loading="okLoading" block custom-class="message-bt-item"
            open-type="getPhoneNumber" @getphonenumber="handleGetPhoneNumber">
            {{ apiTextOk || textOk || '确认' }}
          </wd-button>
          <wd-button v-if="!hideOk && !showGetPhoneNumber" :loading="okLoading" block custom-class="message-bt-item"
            @click="handleOk">
            {{ apiTextOk || textOk || '确认' }}
          </wd-button>
        </view>
      </wd-popup>
    </wd-config-provider>

  </wd-root-portal>
</template>

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

const props = defineProps<{
  title?: string;
  content?: string;
  onOk?: () => Promise<void> | void;
  onCancel?: () => Promise<void> | void;
  onGetPhoneNumber?: (e: any) => Promise<void> | void;
  textOk?: string;
  textCancel?: string;
  /** 是否显示获取手机号按钮，默认 false */
  showGetPhoneNumber?: boolean;
  /** 是否隐藏确认按钮，默认 false */
  hideOk?: boolean;
  /** 是否隐藏取消按钮，默认 false */
  hideCancel?: boolean;
}>();

interface MessageOptions {
  title?: string;
  msg?: string;
  confirmButtonText?: string;
  cancelButtonText?: string;
  inputType?: string;
  inputValue?: string;
  inputPlaceholder?: string;
  inputPattern?: RegExp;
  inputError?: string;
  /** 输入框下的提示信息数组 */
  tips?: string[];
  /** 确认前的回调，返回 Promise 则等待完成，期间显示 loading */
  beforeClose?: (action: string, value?: string) => Promise<void> | void;
}

const okLoading = ref(false);
const cancelLoading = ref(false);
const dialogVisible = ref(false);
const apiContent = ref('');
const apiTitle = ref('');
const apiTextOk = ref('');
const apiTextCancel = ref('');
const apiHideCancel = ref(false);
const apiShowInput = ref(false);
const apiInputValue = ref('');
const apiInputPlaceholder = ref('');
const apiInputPattern = ref<RegExp | null>(null);
const apiInputError = ref('');
const inputErrorVisible = ref(false);
const apiTips = ref<string[]>([]);
const apiBeforeClose = ref<((action: string, value?: string) => Promise<void> | void) | null>(null);

const result = ref<{ action: string; value?: string } | undefined>();
const themeVars = reactive({
  buttonPrimaryBgColor: '#FFA007',
  buttonPrimaryColor: '#000',
  colorTheme: '#FFA007',
});

const handleOk = async () => {
  // 如果有输入框，验证输入
  if (apiShowInput.value && apiInputPattern.value) {
    if (!apiInputPattern.value.test(apiInputValue.value)) {
      inputErrorVisible.value = true;
      return;
    }
  }
  
  okLoading.value = true;
  try {
    // 执行 props 的 onOk
    await props.onOk?.();
    // 执行 API 调用的 beforeClose
    if (apiBeforeClose.value) {
      await apiBeforeClose.value('confirm', apiInputValue.value);
    }
    dialogVisible.value = false;
    result.value = { action: 'confirm', value: apiInputValue.value };
  } finally {
    okLoading.value = false;
  }
};

const handleGetPhoneNumber = async (e: any) => {
  okLoading.value = true;
  try {
    await props.onGetPhoneNumber?.(e);
    dialogVisible.value = false;
    result.value = { action: 'confirm' };
  } finally {
    okLoading.value = false;
  }
};

const handleCancel = async () => {
  cancelLoading.value = true;
  try {
    await props.onCancel?.();
    dialogVisible.value = false;
    result.value = { action: 'cancel' };
  } finally {
    cancelLoading.value = false;
  }
};

const resetState = () => {
  apiContent.value = '';
  apiTitle.value = '';
  apiTextOk.value = '';
  apiTextCancel.value = '';
  apiHideCancel.value = false;
  apiShowInput.value = false;
  apiInputValue.value = '';
  apiInputPlaceholder.value = '';
  apiInputPattern.value = null;
  apiInputError.value = '';
  inputErrorVisible.value = false;
  apiTips.value = [];
  apiBeforeClose.value = null;
  result.value = undefined;
};

const showWithOptions = (options: MessageOptions, hideCancel = false, showInput = false) => {
  resetState();
  apiTitle.value = options.title || '提示';
  apiContent.value = options.msg || '';
  apiTextOk.value = options.confirmButtonText || '确认';
  apiTextCancel.value = options.cancelButtonText || '取消';
  apiHideCancel.value = hideCancel;
  apiShowInput.value = showInput;
  if (showInput) {
    apiInputValue.value = options.inputValue || '';
    apiInputPlaceholder.value = options.inputPlaceholder || '请输入';
    apiInputPattern.value = options.inputPattern || null;
    apiInputError.value = options.inputError || '输入格式不正确';
    apiTips.value = options.tips || [];
  }
  apiBeforeClose.value = options.beforeClose || null;
  dialogVisible.value = true;
  
  return new Promise<{ action: string; value?: string }>((resolve) => {
    const stopWatch = watch(result, (val) => {
      if (val !== undefined) {
        stopWatch();
        resolve(val);
      }
    });
  });
};

defineExpose({
  showDialog: (_content?: string) => {
    apiContent.value = _content || '';
    result.value = undefined;
    dialogVisible.value = true;
    return new Promise<boolean | undefined>((resolve) => {
      const stopWatch = watch(result, (val) => {
        if (val !== undefined) {
          stopWatch();
          resolve(val?.action === 'confirm');
        }
      });
    });
  },
  hideDialog: () => {
    dialogVisible.value = false;
  },
  alert: (options: MessageOptions) => showWithOptions(options, true, false),
  confirm: (options: MessageOptions) => showWithOptions(options, false, false),
  prompt: (options: MessageOptions) => showWithOptions(options, false, true),
  close: () => {
    dialogVisible.value = false;
  }
});
</script>

<style lang="scss" scoped>
.message {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16rpx;
  padding: 32rpx;
  box-sizing: border-box;

  &-title {
    width: 100%;
    text-align: center;
    font-size: 32rpx;
    font-weight: 500;
    padding-bottom: 16rpx;
    border-bottom: 1px solid #eeeeee;
  }

  &-content {
    width: 100%;
    padding: 16rpx 0;
    font-size: 28rpx;
    color: #666666;
    text-align: center;
    line-height: 1.6;
  }

  &-input {
    width: 100%;
    margin-top: 16rpx;

    &-field {
      width: 100%;
      height: 72rpx;
      padding: 0 20rpx;
      border: 1px solid #ddd;
      border-radius: 8rpx;
      font-size: 28rpx;
      box-sizing: border-box;
    }

    &-error {
      margin-top: 8rpx;
      font-size: 24rpx;
      color: #f56c6c;
      text-align: left;
    }

    &-tips {
      display: flex;
      flex-direction: column;
      margin-top: 16rpx;
      padding: 16rpx;
      background-color: #f5f5f5;
      border-radius: 8rpx;
      gap: 8rpx;
    }

    &-tip {
      font-size: 24rpx;
      color: #999;
      text-align: left;
      line-height: 1.5;
    }
  }
}

.message-bt {
  display: flex;
  padding: 0 32rpx 32rpx;
  gap: 24rpx;
  justify-content: center;
  align-items: center;

  :deep(.message-bt-item) {
    flex: 1;
  }
}
</style>
