<script setup lang="ts">
import { computed, provide } from 'vue'
import { Position } from '@vue-flow/core'
import { nodeMap } from '@repo/nodes'

import CanvasHandle from '../handles/CanvasHandle.vue'
import NodeRenderer from './render-types/NodeRenderer.vue'
import CanvasNodeToolBar from './CanvasNodeToolBar.vue'

import type { NodeProps } from '@vue-flow/core'
import type {
	IWorkflowNode,
	CanvasConnectionPort,
	CanvasElementPortWithRenderData
} from '../../../Interface'

type Props = NodeProps<IWorkflowNode['data']> & {
	readOnly?: boolean
	hovered?: boolean
}

const props = defineProps<Props>()

const emit = defineEmits<{
	update: [id: string, parameters: Record<string, unknown>]
	move: [id: string, position: { x: number; y: number }]
	delete: [id: string]
	run: [id: string]
}>()

/**
 * 处理节点
 */
const createEndpoint = (data: {
	port: CanvasConnectionPort
	index: number
	count: number
	offsetAxis: 'top' | 'left'
	position: Position
	type: 'source' | 'target'
}): CanvasElementPortWithRenderData => {
	const { port, index, count, offsetAxis, position, type } = data
	console.log(port, 'port')

	return {
		...port,
		handleId: port?.id || type,
		position,
		connectionsCount: count,
		isConnecting: false,
		offset: {
			[offsetAxis]: `${(100 / (count + 1)) * (index + 1)}%`
		}
	}
}

/**
 * Inputs
 */
const inputs = computed(() => {
	const getInputs = nodeMap[props.data.nodeType]?.inputs
	const inputs = typeof getInputs === 'function' ? getInputs(props.data?.data) : getInputs || []

	return (inputs as CanvasConnectionPort[]).map((target, index) =>
		createEndpoint({
			port: target,
			index,
			count: inputs.length,
			offsetAxis: 'top',
			position: Position.Left,
			type: 'target'
		})
	)
})

/**
 * Outputs
 */
const outputs = computed(() => {
	const getOutputs = nodeMap[props.data.nodeType]?.outputs
	const outputs = typeof getOutputs === 'function' ? getOutputs(props.data?.data) : getOutputs || []
	return (outputs as CanvasConnectionPort[]).map((target, index) =>
		createEndpoint({
			port: target,
			index,
			count: outputs.length,
			offsetAxis: 'top',
			position: Position.Right,
			type: 'source'
		})
	)
})

const onUpdate = (prop: Record<string, unknown>) => {
	emit('update', props.id, prop)
}

const onDelete = () => {
	emit('delete', props.id)
}

const onRun = () => {
	emit('run', props.id)
}

provide('canvas-node-data', {
	props,
	inputs,
	outputs
})
</script>

<template>
	<div class="relative">
		<NodeRenderer v-bind="$attrs" @update="onUpdate" />

		<template v-for="target in inputs" :key="'handle-inputs-port' + target.index">
			<CanvasHandle v-bind="target" type="target" />
		</template>

		<template v-for="source in outputs" :key="'handle-outputs-port' + source.index">
			<CanvasHandle v-bind="source" type="source" />
		</template>

		<CanvasNodeToolBar @delete="onDelete" @run="onRun" />
	</div>
</template>
