/**
 * 画布文字与业务属性的双向同步
 * <p>
 * 用户在画布内直接改文字，改的是组件的 content；在属性面板改值，改的是 data-qc-* 属性。
 * 保存时以属性为准，不打通的话画布里的修改会在下一次保存时被静默丢弃。
 */
import type { Component, Editor } from 'grapesjs';

import { QUALITY_TYPE_ATTR, propAttrName } from './attrs';
import { buildQualityTraits } from './factory';
import { definitionOf } from './lookup';

/**
 * 载入模板后重建属性面板字段。
 * <p>
 * traits 不参与 GrapesJS 项目数据的序列化，保存再打开时组件只剩框架自带的 id/title 两个字段，
 * 这里按 data-quality-type 从注册表重建。属性值仍以组件上的 data-qc-* 为准
 * （trait 初始化优先读组件属性，读不到才用默认值），所以不会把用户改过的值冲掉。
 */
export function restoreQualityTraits(editor: Editor): void {
  editor
    .getWrapper()
    ?.find(`[${QUALITY_TYPE_ATTR}]`)
    .forEach((component) => {
      const definition = definitionOf(component);
      if (definition) {
        component.setTraits(buildQualityTraits(definition));
      }
    });
}

export function bindQualityCanvasSync(editor: Editor): void {
  // 画布内改文字 → 回写业务属性
  editor.on('component:update:content', (component: Component) => {
    const contentKey = definitionOf(component)?.contentKey;
    if (!contentKey) {
      return;
    }
    const text = component.get('content');
    if (typeof text !== 'string') {
      return;
    }
    const attrName = propAttrName(contentKey);
    if (component.getAttributes()[attrName] === text) {
      return;
    }
    component.addAttributes({ [attrName]: text });
  });

  // 属性面板改值 → 同步画布可见文字
  editor.on('trait:value', ({ component, trait, value }) => {
    const contentKey = definitionOf(component)?.contentKey;
    if (!contentKey || typeof value !== 'string') {
      return;
    }
    if (trait?.getName() !== propAttrName(contentKey)) {
      return;
    }
    if (component.get('content') === value) {
      return;
    }
    component.set('content', value);
  });
}