<template>
  <slot 
    name="button" 
    :loading="loading" 
    :text="text"
    :count="count"
    :touchable="count <= 0"
    :onClick="onClick"
  >
    <Button 
      v-bind="$attrs" 
      :text="text" 
      :loading="loading" 
      :touchable="count <= 0"
      @click="onClick"
    />
  </slot>
</template>

<script setup lang="ts">
import { computed, onBeforeUnmount, onMounted, ref } from 'vue';
import { SimpleTimer } from '@imengyu/imengyu-utils';
import type { TextProps } from '@/components/basic/Text.vue';
import Button from '@/components/basic/Button.vue';

export interface CountDownButtonProps extends TextProps {
  /**
   * 倒计时时长，单位秒
   * @default 60
   */
  time?: number;
  /**
   * 保存倒计时状态的key，用于在页面刷新后恢复倒计时状态
   */
  saveState?: string;
  /**
   * 倒计时时显示的文本
   * @default '%d 秒后重新获取'
   */
  countDownText?: string;
  /**
   * 在未倒计时时显示的文本
   * @default '获取验证码'
   */
  defaultText?: string;

  /**
   * 发送验证码函数
   */
  send: () => Promise<void>;
}

const props = withDefaults(defineProps<CountDownButtonProps>(), {
  time: 60,
  countDownText: '%d 秒后重新获取',
  defaultText: '获取验证码',
});

const loading = ref(false);
const count = ref(0);

const text = computed(() => {
  if (count.value > 0)
    return props.countDownText.replace('%d', count.value.toString());
  return props.defaultText;
});

const timer = new SimpleTimer(undefined, () => {
  if (count.value <= 0) {
    timer.stop();
    loading.value = false;
    return;
  }
  count.value--;
}, 1000);

function saveState() {
  if (props.saveState) {
    uni.setStorageSync('CountDownButtonState' + props.saveState, new Date().getTime());
  }
}
function loadState() {
  if (props.saveState) {
    const lastSendTime = uni.getStorageSync('CountDownButtonState' + props.saveState) || 0;
    count.value = Math.floor(Math.max(0, props.time - (new Date().getTime() - lastSendTime) / 1000));
    if (count.value > 0)
      timer.start();
  }
}

async function onClick() {
  if (loading.value || count.value > 0)
    return;

  loading.value = true;
  props.send()
    .then(() => {
      count.value = props.time || 0;
      timer.start();
      saveState();
    })
    .finally(() => {
      loading.value = false;
    })
}


onMounted(() => {
  loadState();
});
onBeforeUnmount(() => {
  timer.stop();
});

</script>