<script setup lang="ts">
import mermaid from 'mermaid';
import { computed, onMounted, ref, watch } from 'vue';

const props = defineProps<{
  chart: string;
}>();

const svg = ref('');
const error = ref('');

let initialized = false;
let diagramId = 0;

function initMermaid() {
  if (initialized) {
    return;
  }

  mermaid.initialize({
    startOnLoad: false,
    theme: 'neutral',
    securityLevel: 'strict',
    fontFamily: 'Inter, Arial, sans-serif',
    flowchart: {
      useMaxWidth: true,
      htmlLabels: true,
    },
  });

  initialized = true;
}

const source = computed(() => props.chart.trim());

async function renderDiagram() {
  if (!import.meta.client) {
    return;
  }

  try {
    initMermaid();
    error.value = '';
    diagramId += 1;
    const { svg: result } = await mermaid.render(`mermaid-diagram-${diagramId}`, source.value);
    svg.value = result;
  } catch (cause) {
    svg.value = '';
    error.value = cause instanceof Error ? cause.message : 'Failed to render Mermaid diagram.';
  }
}

onMounted(() => {
  void renderDiagram();
});

watch(source, () => {
  void renderDiagram();
});
</script>

<template>
  <div class="mermaid-diagram">
    <div v-if="error" class="mermaid-diagram__error">{{ error }}</div>
    <div v-else class="mermaid-diagram__canvas" v-html="svg" />
  </div>
</template>

<style scoped>
.mermaid-diagram {
  margin: 1.25rem 0 1.75rem;
  border: 1px solid #d9dee7;
  border-radius: 20px;
  background: #fff;
  overflow: hidden;
}

.mermaid-diagram__canvas {
  padding: 1rem;
}

.mermaid-diagram__canvas :deep(svg) {
  display: block;
  width: 100%;
  height: auto;
}

.mermaid-diagram__error {
  padding: 1rem 1.25rem;
  color: #b42318;
  background: #fef3f2;
  font-size: 0.95rem;
}
</style>
