<template>
  <div class="node-inspector">
    <template v-if="node">
      <div class="inspector-head">
        <div class="inspector-title">{{ nodeDef?.label ?? node.type }}</div>
        <div class="inspector-id">ID: {{ node.id }}</div>
      </div>

      <el-form label-position="top" size="small" class="inspector-form">
        <el-form-item label="显示名称">
          <el-input v-model="localLabel" @change="emitLabel" />
        </el-form-item>

        <template v-for="field in visibleFields" :key="field.key">
          <el-form-item :label="field.label" :required="field.required">
            <el-input
              v-if="field.type === 'string'"
              :model-value="String(localParams[field.key] ?? '')"
              :placeholder="field.placeholder"
              @update:model-value="(v) => setParam(field.key, v)"
            />
            <el-input-number
              v-else-if="field.type === 'number'"
              :model-value="Number(localParams[field.key] ?? 0)"
              controls-position="right"
              style="width: 100%"
              @update:model-value="(v) => setParam(field.key, v ?? 0)"
            />
            <el-switch
              v-else-if="field.type === 'boolean'"
              class="inspector-switch"
              :model-value="toBool(localParams[field.key])"
              active-text="是"
              inactive-text="否"
              inline-prompt
              @update:model-value="(v) => setParam(field.key, v)"
            />
            <el-select
              v-else-if="field.type === 'select'"
              :model-value="localParams[field.key]"
              style="width: 100%"
              placement="bottom-start"
              teleported
              fit-input-width
              :popper-options="selectPopperOptions"
              @update:model-value="(v) => setParam(field.key, v)"
            >
              <el-option
                v-for="opt in field.options ?? []"
                :key="String(opt.value)"
                :label="opt.label"
                :value="opt.value"
              />
            </el-select>
            <el-input
              v-else-if="field.type === 'textarea'"
              :model-value="String(localParams[field.key] ?? '')"
              type="textarea"
              :rows="3"
              :placeholder="field.placeholder"
              @update:model-value="(v) => setParam(field.key, v)"
            />
          </el-form-item>
        </template>

        <el-empty v-if="visibleFields.length === 0" description="此节点无可配置参数" :image-size="48" />
      </el-form>

      <div class="inspector-actions">
        <el-button type="danger" plain size="small" class="inspector-delete-btn" @click="emit('delete')">
          删除节点
        </el-button>
      </div>
    </template>

    <el-empty v-else description="选中画布上的节点以编辑参数" :image-size="64" />
  </div>
</template>

<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import type { ParamFieldDef, WorkflowNodeDef } from '@/types/workflow'
import { NODE_CATALOG_MAP } from '@/workflow/nodeCatalog'

const props = defineProps<{
  node: WorkflowNodeDef | null
}>()

const emit = defineEmits<{
  update: [patch: Partial<WorkflowNodeDef>]
  delete: []
}>()

const nodeDef = ref(NODE_CATALOG_MAP.get(props.node?.type ?? ''))
const localLabel = ref('')
type ParamValue = string | number | boolean
const localParams = ref<Record<string, ParamValue>>({})

const visibleFields = computed<ParamFieldDef[]>(() => {
  const params = nodeDef.value?.params ?? []
  return params.filter((f) => {
    if (!f.when) return true
    return localParams.value[f.when.key] === f.when.equals
  })
})

/** 右侧面板较窄，禁止 Popper 横向翻转到左侧 */
const selectPopperOptions = {
  modifiers: [
    {
      name: 'flip',
      options: { fallbackPlacements: ['bottom-start', 'top-start'] }
    },
    {
      name: 'preventOverflow',
      options: { boundary: 'viewport', padding: 8 }
    }
  ]
}

watch(
  () => props.node,
  (n) => {
    nodeDef.value = n ? NODE_CATALOG_MAP.get(n.type) : undefined
    localLabel.value = n?.label ?? ''
    localParams.value = n
      ? Object.fromEntries(
          Object.entries(n.params).map(([k, v]) => [k, v as ParamValue])
        )
      : {}
  },
  { immediate: true }
)

function toBool(value: unknown): boolean {
  if (typeof value === 'boolean') return value
  if (value === 'true' || value === 1 || value === '1') return true
  return false
}

function isFieldVisible(field: ParamFieldDef): boolean {
  if (!field.when) return true
  return localParams.value[field.when.key] === field.when.equals
}

function pruneHiddenParams() {
  const fields = nodeDef.value?.params ?? []
  for (const field of fields) {
    if (!isFieldVisible(field)) delete localParams.value[field.key]
  }
}

function setParam(key: string, value: ParamValue) {
  localParams.value[key] = value
  pruneHiddenParams()
  emitParams()
}

function emitLabel() {
  if (!props.node) return
  emit('update', { label: localLabel.value })
}

function emitParams() {
  if (!props.node) return
  emit('update', { params: { ...localParams.value } })
}
</script>

<style scoped>
.node-inspector {
  height: 100%;
  overflow: auto;
  padding: 12px;
  box-sizing: border-box;
}
.inspector-head {
  margin-bottom: 12px;
  padding-bottom: 10px;
  border-bottom: 1px solid #ebeef5;
}
.inspector-title {
  font-size: 15px;
  font-weight: 600;
  color: #303133;
}
.inspector-id {
  font-size: 11px;
  color: #909399;
  margin-top: 4px;
}
.inspector-form :deep(.el-form-item__label) {
  font-weight: 500;
  color: #606266 !important;
}
.inspector-form :deep(.el-input__inner),
.inspector-form :deep(.el-textarea__inner) {
  color: #303133 !important;
}
.inspector-form :deep(.el-input-number .el-input__inner) {
  color: #303133 !important;
}
.inspector-form :deep(.inspector-switch) {
  --el-switch-on-color: #7c3aed;
  --el-switch-off-color: #dcdfe6;
}
.inspector-form :deep(.inspector-switch .el-switch__core) {
  border-color: #dcdfe6;
  background: #dcdfe6;
}
.inspector-form :deep(.inspector-switch.is-checked .el-switch__core) {
  border-color: #7c3aed;
  background: #7c3aed;
}
.inspector-form :deep(.inspector-switch .el-switch__inner) {
  color: #606266 !important;
}
.inspector-form :deep(.inspector-switch.is-checked .el-switch__inner) {
  color: #fff !important;
}
.inspector-form :deep(.el-select-dropdown__item) {
  white-space: normal;
  line-height: 1.4;
  height: auto;
  min-height: 34px;
  padding-top: 6px;
  padding-bottom: 6px;
}
.inspector-actions {
  margin-top: 16px;
  padding-top: 12px;
  border-top: 1px solid #ebeef5;
}
.inspector-delete-btn {
  width: 100%;
}
</style>
