<template>
  <div class="code-block relative overflow-visible my-4">
    <div
      class="code-block-header sticky top-0 z-10 flex items-center justify-between rounded-tl-md rounded-tr-md px-2 py-1 bg-gray-800 text-xs font-medium text-gray-300"
    >
      <span class="text-xs capitalize text-gray-300">{{ displayLanguage }}</span>
      <button
        class="copy-btn text-xs px-2 py-0.5 rounded border border-gray-600 bg-gray-700 hover:bg-gray-600 transition-all"
        @click="copyCode"
      >
        {{ copied ? 'Copied!' : 'Copy' }}
      </button>
    </div>
    <div
      class="overflow-x-auto code-block-body whitespace-pre-wrap break-words p-3 bg-gray-900 rounded-b-md m-0"
    >
      <pre
        tabindex="0"
      ><code ref="codeElement" :class="`language-${language}`" class="w-full">{{ code }}</code></pre>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, watch } from 'vue'
import Prism from 'prismjs'
import 'prismjs/components/prism-sql'
import 'prismjs/components/prism-python'
import 'prismjs/components/prism-typescript'
import 'prismjs/components/prism-javascript'
import 'prismjs/components/prism-json'
import 'prismjs/components/prism-yaml'
import 'prismjs/components/prism-bash'
import 'prismjs/components/prism-markdown'

const props = defineProps<{
  code: string
  language?: string
  type?: string
}>()

const codeElement = ref<HTMLElement | null>(null)
const copied = ref(false)

const language = ref('markup')
const displayLanguage = ref('text')

// Map source types to Prism language identifiers
const typeToLanguageMap: Record<string, string> = {
  GENERATED_SQL_QUERY: 'sql',
  SQL: 'sql',
  PYTHON: 'python',
  JAVASCRIPT: 'javascript',
  TYPESCRIPT: 'typescript',
  JSON: 'json',
  YAML: 'yaml',
  BASH: 'bash',
  MARKDOWN: 'markdown',
}

function determineLanguage() {
  // First try to use the type prop
  if (props.type && typeToLanguageMap[props.type]) {
    language.value = typeToLanguageMap[props.type]
    displayLanguage.value = language.value
    return
  }

  // Then try the language prop
  if (props.language && Prism.languages[props.language]) {
    language.value = props.language
    displayLanguage.value = props.language
    return
  }

  // Default to markup
  language.value = 'markup'
  displayLanguage.value = 'text'
}

function highlightCode() {
  if (codeElement.value && Prism.languages[language.value]) {
    const highlighted = Prism.highlight(props.code, Prism.languages[language.value], language.value)
    codeElement.value.innerHTML = highlighted
  }
}

function copyCode() {
  navigator.clipboard
    .writeText(props.code)
    .then(() => {
      copied.value = true
      setTimeout(() => {
        copied.value = false
      }, 1500)
    })
    .catch((err) => {
      console.error('Failed to copy code:', err)
    })
}

onMounted(() => {
  determineLanguage()
  highlightCode()
})

watch(
  () => [props.code, props.language, props.type],
  () => {
    determineLanguage()
    highlightCode()
  }
)
</script>

<style scoped>
.code-block {
  font-family: 'Monaco', 'Menlo', 'Consolas', 'Courier New', monospace;
  font-size: 13px;
  line-height: 1.5;
}

.code-block pre {
  margin: 0;
}

.code-block code {
  font-family: inherit;
  display: block;
}

.code-block-header {
  backdrop-filter: blur(4px);
}
</style>
