import type { TinyflowOptions } from '@tinyflow-ai/ui';

type TinyflowDataOption = Exclude<
  TinyflowOptions['data'],
  string | undefined
>;
type StructuredCloneFn = <T>(value: T) => T;

function createDataSignature(data: unknown) {
  if (data == null || typeof data === 'string') {
    return String(data ?? '');
  }
  try {
    return JSON.stringify(data);
  } catch {
    return '';
  }
}

function safeDeepClone<T>(value: T): T {
  if (value === null || typeof value !== 'object') {
    return value;
  }

  try {
    const clone = (globalThis as { structuredClone?: StructuredCloneFn })
      .structuredClone;
    if (clone) {
      return clone(value);
    }
  } catch {
    // Fall through to JSON cloning for browsers without native structuredClone.
  }

  try {
    return JSON.parse(JSON.stringify(value));
  } catch {
    console.warn(
      'Failed to clone object, returning original (may cause issues)',
      value,
    );
    return value;
  }
}

/**
 * 维护 Vue 属性数据与 Tinyflow 原生数据之间的同步边界。
 *
 * 原生画布回传的数据会被父组件再次作为属性传入。延迟到属性更新时再比较
 * 两侧签名，可以阻止同一份画布状态被重新深拷贝并整图应用，同时避免在
 * 每一帧提前序列化完整画布。
 */
export function createTinyflowDataSync() {
  let lastAppliedDataSignature = '';
  let lastNativeData: TinyflowOptions['data'] | null = null;

  return {
    cloneExternalDataIfChanged(data: TinyflowOptions['data']) {
      if (data == null || typeof data === 'string') {
        return null;
      }
      const signature = createDataSignature(data);
      if (lastNativeData != null) {
        const nativeSignature = createDataSignature(lastNativeData);
        lastNativeData = null;
        if (signature && signature === nativeSignature) {
          lastAppliedDataSignature = signature;
          return null;
        }
        lastAppliedDataSignature = '';
      }
      if (signature && signature === lastAppliedDataSignature) {
        return null;
      }
      lastAppliedDataSignature = signature;
      return safeDeepClone(data as TinyflowDataOption);
    },
    markNativeData(data: TinyflowOptions['data']) {
      lastNativeData = data;
    },
    reset() {
      lastAppliedDataSignature = '';
      lastNativeData = null;
    },
  };
}
