<script setup lang="ts">
import { ref, watch } from 'vue'
import { marked } from 'marked'
import DOMPurify from 'dompurify'
import yaml from 'js-yaml'
import { useAuthStore } from '@/stores/auth'
import { previewSpec } from '@/api/editor'
import { statusBadgeClass } from '@/utils/status'

const props = defineProps<{
  content: string
  mode: 'fast' | 'full'
  owner: string
  repo: string
  hideHeader?: boolean
}>()

const auth = useAuthStore()
const renderedHtml = ref('')
let debounceTimer: ReturnType<typeof setTimeout> | null = null

// Frontmatter extracted for the styled header
const frontmatter = ref<Record<string, unknown> | null>(null)

/**
 * Strip YAML frontmatter from markdown content.
 * Handles various line-ending styles and optional trailing newlines.
 * Returns the body without the delimited block and parses
 * the frontmatter into a plain object for the styled header.
 */
function stripFrontmatter(content: string): string {
  // Normalize line endings, trim leading whitespace
  const normalized = content.replace(/\r\n/g, '\n').replace(/^\s*/, '')
  // Match opening --- on its own line, YAML block, closing --- on its own line
  const match = normalized.match(/^---[ \t]*\n([\s\S]*?)\n---[ \t]*(?:\n|$)/)
  if (!match) {
    frontmatter.value = null
    return content
  }

  try {
    const parsed = yaml.load(match[1])
    if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
      const fm = parsed as Record<string, unknown>
      frontmatter.value = fm.title ? fm : null
    } else {
      frontmatter.value = null
    }
  } catch {
    frontmatter.value = null
  }

  return normalized.slice(match[0].length)
}

function buildFrontmatterHtml(fm: Record<string, unknown>): string {
  const title = DOMPurify.sanitize(String(fm.title || ''))
  const status = String(fm.status || 'draft')
  const badgeClass = statusBadgeClass(status)
  const parts: string[] = []

  parts.push(`<h1 class="mt-0 mb-1">${title}</h1>`)

  const meta: string[] = []
  meta.push(`<span class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium ${badgeClass}">${DOMPurify.sanitize(status.replace(/_/g, ' '))}</span>`)
  if (fm.review_status) {
    meta.push(`<span class="text-xs text-slate-500">${DOMPurify.sanitize(String(fm.review_status).replace(/_/g, ' '))}</span>`)
  }
  if (fm.owner) {
    meta.push(`<span class="text-xs text-slate-500">Owner: ${DOMPurify.sanitize(String(fm.owner))}</span>`)
  }
  if (fm.team) {
    meta.push(`<span class="text-xs text-slate-500">Team: ${DOMPurify.sanitize(String(fm.team))}</span>`)
  }
  if (fm.tags && Array.isArray(fm.tags) && fm.tags.length > 0) {
    const tagHtml = fm.tags
      .map((t: unknown) => `<span class="inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-blue-50 text-blue-600">${DOMPurify.sanitize(String(t))}</span>`)
      .join(' ')
    meta.push(tagHtml)
  }

  parts.push(`<div class="flex gap-2 items-center flex-wrap mb-4">${meta.join('<span class="text-slate-300"> | </span>')}</div>`)
  parts.push('<hr class="border-0 border-t border-gray-200 mt-0 mb-4" />')

  return parts.join('\n')
}

function renderFast(content: string) {
  const body = stripFrontmatter(content)
  const raw = marked.parse(body, { async: false }) as string
  const headerHtml = !props.hideHeader && frontmatter.value ? buildFrontmatterHtml(frontmatter.value) : ''
  renderedHtml.value = DOMPurify.sanitize(headerHtml + raw, {
    ADD_ATTR: ['class'],
  })
}

async function renderFull(content: string) {
  try {
    const result = await previewSpec(auth.org, props.owner, props.repo, { content })
    renderedHtml.value = DOMPurify.sanitize(result.html)
    frontmatter.value = null // full mode handles its own header
  } catch {
    // Fallback to fast mode on error
    renderFast(content)
  }
}

watch(
  () => [props.content, props.mode],
  () => {
    if (debounceTimer) clearTimeout(debounceTimer)
    debounceTimer = setTimeout(() => {
      if (props.mode === 'fast') {
        renderFast(props.content)
      } else {
        renderFull(props.content)
      }
    }, 300)
  },
  { immediate: true },
)
</script>

<template>
  <div class="h-full flex flex-col border border-border-light dark:border-slate-700 rounded-lg bg-surface-light dark:bg-surface-alt overflow-hidden">
    <div class="flex-none px-3 py-1.5 border-b border-border-light/60 dark:border-slate-700 bg-surface-light-alt dark:bg-surface-alt">
      <span class="text-[11px] font-medium text-slate-400 uppercase tracking-wider">
        {{ mode === 'fast' ? 'Live Preview' : 'Spec Preview' }}
      </span>
    </div>
    <div class="flex-1 overflow-y-auto p-5">
      <div v-if="!content.trim()" class="text-sm text-slate-400 text-center py-8">
        Start typing to see preview...
      </div>
      <!-- eslint-disable-next-line vue/no-v-html -->
      <div v-else class="spec-prose" v-html="renderedHtml"></div>
    </div>
  </div>
</template>
