<script lang="ts" setup>
import { camelCase, kebabCase, upperFirst } from 'scule'
import FileTypeVue from '../icon/VscodeIconsFileTypeVue.vue'
import FileTypeTypescript from '../icon/VscodeIconsFileTypeTypescriptOfficial.vue'
import FileTypeJavascript from '../icon/VscodeIconsFileTypeJsOfficial.vue'
import TablerTerminal from '../icon/TablerTerminal.vue'

const route = useRoute()

const IconComponents = {
  'vue': FileTypeVue,
  'vue-html': FileTypeVue,
  'sh': TablerTerminal,
  'ts': FileTypeTypescript,
  'js': FileTypeJavascript,
}

const props = defineProps({
  slug: {
    type: String,
    default: '',
  },
  props: {
    type: Object,
    default: () => ({}),
  },
  slots: {
    type: Object,
    default: () => ({}),
  },
  filename: {
    type: String,
    default: '',
  },
  lang: {
    type: String as PropType<keyof typeof IconComponents>,
    default: '',
  },
})

const componentName = props.slug || `Ray${upperFirst(camelCase(route.params.slug[route.params.slug.length - 1]))}`
const componentProps = reactive({ ...props.props })

const code = computed(() => {
  let code = `\`\`\`html
<template>
  <${componentName}`

  for (const [k, v] of Object.entries(componentProps)) {
    code += ` ${typeof v === 'boolean' || typeof v === 'number' || typeof v === 'object' ? ':' : ''}${kebabCase(k)}="${typeof v === 'object' ? renderObject(v) : v}"`
  }

  code += `/>\n</template>
\`\`\`
  `
  return code
})

const { data: codeRender, error: codeRenderError } = await useAsyncData(`${componentName}-renderer-${JSON.stringify({ slots: props.slots, code: code.value })}`, async () => {
  let formatted = ''
  try {
    // @ts-ignore
    formatted = await $prettier.format(code.value, {
      trailingComma: 'none',
      semi: false,
      singleQuote: true,
    })
  }
  catch {
    formatted = code.value
  }

  return parseMarkdown(formatted, {
  })
}, {
  watch: [code],
})
</script>

<template>
  <div class="border border-neutral-200 dark:border-neutral-700 rounded-lg not-prose my-2 overflow-hidden">
    <div v-if="filename" class="p-4 py-2 border-b border-neutral-200 dark:border-neutral-700">
      <span class="flex items-center gap-1">
        <component :is="IconComponents[lang]" v-if="lang" class="inline" />
        <span class="text-sm text-neutral-500 dark:text-neutral-400">{{ filename }}</span>
      </span>
    </div>

    <div :class="['p-4 overflow-auto', !!codeRender ? 'border-b border-neutral-200 dark:border-neutral-700' : '']">
      <component :is="componentName" v-bind="componentProps">
        <slot />
      </component>
    </div>

    <template v-if="codeRender || codeRenderError">
      <div class="overflow-auto">
        <ContentRenderer v-if="codeRender" :value="codeRender" class="p-4 bg-neutral-50 dark:bg-neutral-800/50" />
        <pre v-if="codeRenderError" class="p-4">{{ codeRenderError }}</pre>
      </div>
    </template>
  </div>
</template>

<style scoped></style>