<script setup lang="ts">
import type { Edge, Node } from '@vue-flow/core';

import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue';

import { useVueFlow, VueFlow } from '@vue-flow/core';
import { MiniMap } from '@vue-flow/minimap';

import { workflowEdgeTypes, workflowNodeTypes } from '../../workflow/shared/workflowNodeTypes';

import '@vue-flow/minimap/dist/style.css';
import '@vue-flow/core/dist/style.css';
import '@vue-flow/core/dist/theme-default.css';

const props = defineProps<{
  edges: Edge[];
  fitNodeId?: string;
  nodes: Node[];
}>();

const containerRef = ref<HTMLElement>();
const { fitView } = useVueFlow();

async function refreshView(nodeId?: string) {
  await nextTick();
  if (!containerRef.value?.clientHeight) return;
  if (nodeId) {
    fitView({ nodes: [nodeId], padding: 0.4, duration: 200 });
    return;
  }
  fitView({ padding: 0.2, duration: 200 });
}

function onNodesInitialized() {
  refreshView(props.fitNodeId);
}

watch(
  () => props.fitNodeId,
  (nodeId) => {
    if (nodeId) refreshView(nodeId);
  },
);

watch(
  () => [props.nodes, props.edges],
  () => refreshView(props.fitNodeId),
  { deep: true },
);

let resizeObserver: ResizeObserver | undefined;

onMounted(() => {
  if (!containerRef.value) return;
  resizeObserver = new ResizeObserver(() => {
    if (containerRef.value && containerRef.value.clientHeight > 0) {
      refreshView(props.fitNodeId);
    }
  });
  resizeObserver.observe(containerRef.value);
});

onUnmounted(() => {
  resizeObserver?.disconnect();
});
</script>

<template>
  <div
    ref="containerRef"
    class="workflow-readonly-canvas bg-muted/30 h-full w-full min-h-[320px]"
  >
    <VueFlow
      :nodes="props.nodes"
      :edges="props.edges"
      :node-types="workflowNodeTypes"
      :edge-types="workflowEdgeTypes"
      :nodes-draggable="false"
      :nodes-connectable="false"
      :elements-selectable="false"
      :pan-on-drag="[1, 2]"
      :zoom-on-scroll="true"
      @nodes-initialized="onNodesInitialized"
    >
      <MiniMap pannable zoomable />
    </VueFlow>
  </div>
</template>

<style scoped>
.workflow-readonly-canvas :deep(.vue-flow) {
  width: 100%;
  height: 100%;
}

.workflow-readonly-canvas :deep(.vue-flow__container) {
  width: 100%;
  height: 100%;
}

.workflow-readonly-canvas :deep(.vue-flow__node) {
  cursor: default;
  overflow: visible;
}

.workflow-readonly-canvas :deep(.nopan) {
  pointer-events: all;
}

.workflow-readonly-canvas :deep(.vue-flow__panel.top) {
  display: none;
}

.workflow-readonly-canvas :deep(.vue-flow__edge button) {
  display: none !important;
  pointer-events: none;
}
</style>
