export interface AnnotationInsertSpec {
  alias: string;
  placeholder: string;
  tag: string;
}

export interface AnnotationInsertResult {
  error?: string;
  ok: boolean;
}

export interface FlowVersionPropertiesSpec {
  newFlowVersionId: string;
  revisionFlowVersionId: string;
}

/**
 * This command is serialized into the ONLYOFFICE editor context. Keep it self-contained:
 * it may access only Api and Asc.scope, not imports or closure state.
 */
export function insertAnnotationControlCommand(): string {
  try {
    const spec = Asc.scope.dmsQianpiyeInsert as AnnotationInsertSpec | undefined;
    if (!spec || typeof spec.tag !== 'string' || !spec.tag || typeof spec.alias !== 'string'
      || typeof spec.placeholder !== 'string' || !spec.placeholder) {
      throw new Error('签批页标注配置无效');
    }
    const document = Api.GetDocument();
    if (!document || typeof document.GetAllContentControls !== 'function') {
      throw new Error('当前编辑器不支持读取内容控件');
    }
    const before = document.GetAllContentControls().filter((control) => control.GetTag?.() === spec.tag);
    if (typeof Api.CreateInlineLvlSdt !== 'function' || typeof Api.CreateRun !== 'function'
      || typeof Api.CreateParagraph !== 'function') {
      throw new Error('当前编辑器不支持签批页标注控件');
    }

    const control = Api.CreateInlineLvlSdt();
    const run = Api.CreateRun();
    const paragraph = Api.CreateParagraph();
    if (!control || !run || !paragraph || run.AddText?.(spec.placeholder) !== true
      || control.AddElement?.(run, 0) !== true || typeof paragraph.AddInlineLvlSdt !== 'function') {
      throw new Error('创建签批页标注失败');
    }
    // AddInlineLvlSdt is a write-only API in ONLYOFFICE 9.4 and returns void.
    paragraph.AddInlineLvlSdt(control);
    if (control.SetTag?.(spec.tag) !== true || control.SetAlias?.(spec.alias) !== true
      || control.SetLock?.('unlocked') !== true) {
      throw new Error('创建签批页标注失败');
    }
    if (typeof control.SetAppearance === 'function') {
      control.SetAppearance('boundingBox');
    }
    if (typeof document.InsertContent !== 'function' || document.InsertContent([paragraph], true) !== true) {
      throw new Error('插入签批页标注失败');
    }

    const after = document.GetAllContentControls().filter((item) => item.GetTag?.() === spec.tag);
    if (after.length !== before.length + 1) {
      throw new Error('签批页标注插入后校验失败');
    }
    return JSON.stringify({ ok: true });
  } catch (error: unknown) {
    return JSON.stringify({
      ok: false,
      error: error instanceof Error ? error.message : String(error),
    });
  }
}

/**
 * Marks the version selection in the in-editor document. ONLYOFFICE 9.4 cannot delete custom
 * properties, so the qianpiye save callback is responsible for the final server-side upsert.
 */
export function stageFlowVersionPropertiesCommand(): string {
  try {
    const spec = Asc.scope.dmsQianpiyeFlowVersionProperties as FlowVersionPropertiesSpec | undefined;
    if (!spec || typeof spec.newFlowVersionId !== 'string' || !spec.newFlowVersionId
      || typeof spec.revisionFlowVersionId !== 'string' || !spec.revisionFlowVersionId) {
      throw new Error('签批页流程版本配置无效');
    }
    const document = Api.GetDocument();
    const properties = document?.GetCustomProperties?.();
    if (!properties || typeof properties.Add !== 'function' || typeof properties.Get !== 'function') {
      throw new Error('当前编辑器不支持保存签批页流程版本');
    }
    for (const [key, value] of [
      ['DMS_NEW_FLOW_VERSION_ID', spec.newFlowVersionId],
      ['DMS_EDIT_FLOW_VERSION_ID', spec.revisionFlowVersionId],
    ]) {
      const existing = properties.Get(key);
      if (existing === value) continue;
      // Add can append a duplicate in ONLYOFFICE 9.4. The qianpiye save callback uses the last
      // value as the requested selection, then writes one canonical property for each key.
      if (properties.Add(key, value) !== true) throw new Error('保存签批页流程版本失败');
    }
    return JSON.stringify({ ok: true });
  } catch (error: unknown) {
    return JSON.stringify({
      ok: false,
      error: error instanceof Error ? error.message : String(error),
    });
  }
}

export function parseInsertResult(value: unknown): AnnotationInsertResult {
  try {
    const result: unknown = JSON.parse(String(value));
    if (typeof result === 'object' && result !== null && !Array.isArray(result)
      && typeof (result as Record<string, unknown>).ok === 'boolean') {
      const item = result as Record<string, unknown>;
      return {
        ok: item.ok as boolean,
        ...(typeof item.error === 'string' ? { error: item.error } : {}),
      };
    }
  } catch {
    // The command result is untrusted editor output; expose a normalized error below.
  }
  return { ok: false, error: '签批页标注命令返回无效' };
}
