<template>
  <view>
    <template v-if="loading">
      <slot name="loading-top" />
      <component v-if="theme" :is="components[theme]" :size="size" :count="count" />
      <slot name="loading-bottom" />
    </template>
    <template v-else>
      <slot v-if="data" name="content" :data="data"  />
      <slot v-else name="error" />
    </template>
  </view>
</template>

<script lang="ts" setup>
import { ref, onMounted, computed } from 'vue'
import ImageText from './templates/ImageText.vue'
import LineList from './templates/LineList.vue'
import BookCard from './templates/BookCard.vue'
import ImageCard from './templates/ImageCard.vue'
import BookInfo from './templates/BookInfo.vue'

// 注册组件
const components = {
  'none': () => null,
  'image-text': ImageText,
  'line-list': LineList,
  'image-card': ImageCard,
  'book-card': BookCard,
  'book-info': BookInfo,
}

type RequestFn = () => Promise<any>
type ThemeType = keyof typeof components

const props = withDefaults(defineProps<{
  theme?: ThemeType
  request: RequestFn | RequestFn[]
  auto?: boolean,
  size?: 'small' | 'medium' | 'large' | any[]
  count?: number
}>(), {
  theme: 'none',
  auto: true,
  count: 1
})

const emit = defineEmits(['success', 'error', 'complete'])

const requestFnType = ref('single')
const requestList = computed<RequestFn[]>(() => {
  if (Array.isArray(props.request)) {
    requestFnType.value = 'multi'
    return props.request
  }
  requestFnType.value = 'single'
  return [props.request]
})

const loading = ref(true)
const data = ref<any>(null)

const run = async (methods?: RequestFn[]) => {
  loading.value = true
  const reqMethods = methods || requestList.value
  try {
    // await new Promise(resolve => setTimeout(resolve, 3000))
    const results = await Promise.all(
      reqMethods.map(fn => fn())
    )
    // 将每个请求的结果处理成 key-value 格式
    const resolvedData: Record<string, any> = {}
    reqMethods.forEach((fn, index) => {
      const key = fn.name || `request_${index}`
      resolvedData[key] = results[index]
    })
    data.value = requestFnType.value === 'single' ? results[0] : resolvedData
    emit('success', data.value)
  } catch (err) {
    emit('error', err)
  } finally {
    loading.value = false
  }
}

const reload = (methods?: RequestFn[]) => {
  run(methods)
}

onMounted(() => {
  if (props.auto) {
    run()
  }
})

defineExpose({
  reload,
  loading
})
</script>

<style lang="scss" scoped>
</style>