<script setup lang="ts">
import type { BlockInstance, BlockSchema, FixedField, FormFieldSchema } from './types';

import { computed, watch } from 'vue';

import { Empty, Input, InputNumber, Radio, RadioGroup, Select, Textarea } from 'ant-design-vue';

import GalleryPickLink from '#/components/form/components/gallery-pick-link.vue';

/**
 * 右侧属性面板：根据选中块的字段 schema 渲染表单
 * - 顶层固定字段（fixedFields）：渲染在顶部，不可删除
 * - 选中块的 fields：渲染在下方
 * - 图片类型字段用 GalleryPickLink（透传 acceptTypes）
 */
const props = defineProps<{
  /** 顶层固定字段定义 */
  fixedFields?: FixedField[];
  /** 顶层固定字段当前值 */
  fixedValues?: Record<string, any>;
  /** 当前选中的块定义（可能为空） */
  selectedBlockSchema?: BlockSchema;
  /** 当前选中的块实例（可能为空） */
  selectedInstance?: BlockInstance;
}>();

const emit = defineEmits<{
  /** 顶层固定字段值变化 */
  'update:fixedValues': [value: Record<string, any>];
  /** 选中块实例数据变化 */
  'update:instance': [instance: BlockInstance];
}>();

/**
 * 设置顶层固定字段的值
 * 支持 a.b.c 嵌套路径
 */
function setFixedValue(path: string, value: any) {
  const next = { ...(props.fixedValues || {}) };
  setByPath(next, path, value);
  emit('update:fixedValues', next);
}

/**
 * 设置选中块实例的字段值
 */
function setInstanceValue(path: string, value: any) {
  if (!props.selectedInstance) return;
  const nextData = { ...props.selectedInstance.data };
  setByPath(nextData, path, value);
  emit('update:instance', {
    ...props.selectedInstance,
    data: nextData,
  });
}

/**
 * 按 a.b.c 路径设置对象嵌套属性（不可变更新）
 */
function setByPath(obj: Record<string, any>, path: string, value: any) {
  const keys = path.split('.');
  let cursor: any = obj;
  for (let i = 0; i < keys.length - 1; i++) {
    const k = keys[i]!;
    if (!cursor[k] || typeof cursor[k] !== 'object') {
      cursor[k] = {};
    } else {
      cursor[k] = { ...cursor[k] };
    }
    cursor = cursor[k];
  }
  cursor[keys[keys.length - 1]!] = value;
}

/**
 * 按 a.b.c 路径读取对象嵌套属性
 */
function getByPath(obj: Record<string, any> | undefined, path: string): any {
  if (!obj) return undefined;
  const keys = path.split('.');
  let cursor: any = obj;
  for (const k of keys) {
    if (cursor == null) return undefined;
    cursor = cursor[k];
  }
  return cursor;
}

const hasAnyField = computed(() => {
  return (
    (props.fixedFields && props.fixedFields.length > 0) ||
    (props.selectedBlockSchema && props.selectedBlockSchema.fields.length > 0)
  );
});

// 当选中的块变化时，触发 watch 让父级感知（用于属性面板切换的动画/数据初始化）
watch(
  () => props.selectedInstance?.id,
  () => {
    // 仅做依赖追踪，实际更新在用户交互时通过 emit 触发
  },
);
</script>

<template>
  <div class="property-panel">
    <div class="panel-header">
      <span class="title">属性</span>
      <span v-if="selectedBlockSchema" class="hint">{{ selectedBlockSchema.label }}</span>
    </div>
    <div class="panel-body">
      <!-- 顶层固定字段 -->
      <div v-if="fixedFields && fixedFields.length > 0" class="field-section">
        <div class="section-title">基础信息</div>
        <div
          v-for="field in fixedFields"
          :key="field.name"
          class="form-row"
        >
          <label class="form-label">
            {{ field.label }}
            <span v-if="field.required" class="required">*</span>
          </label>
          <!-- 文本 -->
          <Input
            v-if="!field.type || field.type === 'string' || field.type === 'url'"
            :value="getByPath(fixedValues, field.name)"
            :placeholder="field.placeholder"
            allow-clear
            size="small"
            @update:value="setFixedValue(field.name, $event)"
          />
          <!-- 数字 -->
          <InputNumber
            v-else-if="field.type === 'number'"
            :value="getByPath(fixedValues, field.name)"
            :placeholder="field.placeholder"
            size="small"
            style="width: 100%"
            @update:value="setFixedValue(field.name, $event)"
          />
          <!-- 多行文本 -->
          <Textarea
            v-else-if="field.type === 'textarea'"
            :value="getByPath(fixedValues, field.name)"
            :placeholder="field.placeholder"
            :rows="3"
            size="small"
            @update:value="setFixedValue(field.name, $event)"
          />
          <!-- 下拉选择 -->
          <Select
            v-else-if="field.type === 'select'"
            :value="getByPath(fixedValues, field.name)"
            :options="field.options"
            :placeholder="field.placeholder"
            size="small"
            @update:value="setFixedValue(field.name, $event)"
          />
          <!-- 单选 -->
          <RadioGroup
            v-else-if="field.type === 'radio'"
            :value="getByPath(fixedValues, field.name)"
            size="small"
            @update:value="setFixedValue(field.name, $event)"
          >
            <Radio
              v-for="opt in field.options"
              :key="String(opt.value)"
              :value="opt.value"
            >
              {{ opt.label }}
            </Radio>
          </RadioGroup>
          <!-- 图片素材 -->
          <div v-else-if="field.type === 'image'" class="image-picker-row">
            <Input
              :value="getByPath(fixedValues, field.name)"
              :placeholder="field.placeholder || '从素材库选择图片'"
              size="small"
              read-only
            />
            <GalleryPickLink
              :accept-types="field.acceptTypes || [0]"
              @select="(urls) => setFixedValue(field.name, urls[0] || '')"
            />
          </div>
        </div>
      </div>

      <!-- 选中块的属性字段 -->
      <div v-if="selectedBlockSchema && selectedInstance" class="field-section">
        <div class="section-title">{{ selectedBlockSchema.label }}属性</div>
        <div
          v-for="field in selectedBlockSchema.fields"
          :key="field.name"
          class="form-row"
        >
          <label class="form-label">
            {{ field.label }}
            <span v-if="field.required" class="required">*</span>
          </label>
          <Input
            v-if="!field.type || field.type === 'string' || field.type === 'url'"
            :value="getByPath(selectedInstance.data, field.name)"
            :placeholder="field.placeholder"
            allow-clear
            size="small"
            @update:value="setInstanceValue(field.name, $event)"
          />
          <InputNumber
            v-else-if="field.type === 'number'"
            :value="getByPath(selectedInstance.data, field.name)"
            :placeholder="field.placeholder"
            size="small"
            style="width: 100%"
            @update:value="setInstanceValue(field.name, $event)"
          />
          <Textarea
            v-else-if="field.type === 'textarea'"
            :value="getByPath(selectedInstance.data, field.name)"
            :placeholder="field.placeholder"
            :rows="3"
            size="small"
            @update:value="setInstanceValue(field.name, $event)"
          />
          <Select
            v-else-if="field.type === 'select'"
            :value="getByPath(selectedInstance.data, field.name)"
            :options="field.options"
            :placeholder="field.placeholder"
            size="small"
            @update:value="setInstanceValue(field.name, $event)"
          />
          <RadioGroup
            v-else-if="field.type === 'radio'"
            :value="getByPath(selectedInstance.data, field.name)"
            size="small"
            @update:value="setInstanceValue(field.name, $event)"
          >
            <Radio
              v-for="opt in field.options"
              :key="String(opt.value)"
              :value="opt.value"
            >
              {{ opt.label }}
            </Radio>
          </RadioGroup>
          <div v-else-if="field.type === 'image'" class="image-picker-row">
            <Input
              :value="getByPath(selectedInstance.data, field.name)"
              :placeholder="field.placeholder || '从素材库选择图片'"
              size="small"
              read-only
            />
            <GalleryPickLink
              :accept-types="field.acceptTypes || [0]"
              @select="(urls) => setInstanceValue(field.name, urls[0] || '')"
            />
          </div>
        </div>
      </div>

      <!-- 未选中任何块时的提示 -->
      <Empty
        v-if="!hasAnyField"
        description="点击画布中的块以编辑属性"
        :image-style="{ height: '60px' }"
        style="margin-top: 60px"
      />
    </div>
  </div>
</template>

<style scoped lang="scss">
.property-panel {
  display: flex;
  flex-direction: column;
  width: 280px;
  height: 100%;
  border-left: 1px solid var(--ant-color-border-secondary, #e5e6eb);
  background: var(--ant-color-bg-container, #fff);
}

.panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  border-bottom: 1px solid var(--ant-color-border-secondary, #e5e6eb);
  font-size: 13px;

  .title {
    font-weight: 600;
    color: var(--ant-color-text, #1d2129);
  }

  .hint {
    color: var(--ant-color-text-tertiary, #86909c);
    font-size: 11px;
    max-width: 120px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
}

.panel-body {
  flex: 1;
  overflow-y: auto;
  padding: 16px;
}

.field-section {
  margin-bottom: 24px;
}

.section-title {
  margin-bottom: 12px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--ant-color-split, #f2f3f5);
  font-size: 12px;
  font-weight: 600;
  color: var(--ant-color-text-secondary, #4e5969);
}

.form-row {
  margin-bottom: 12px;
}

.form-label {
  display: block;
  margin-bottom: 4px;
  font-size: 12px;
  color: var(--ant-color-text-secondary, #4e5969);

  .required {
    margin-left: 2px;
    color: var(--ant-color-error, #f53f3f);
  }
}

.image-picker-row {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
</style>
