import type { OnlyOfficeContentControl, OnlyOfficeParagraph, UpdateControlSpec } from './types';

export function setFormulaResultLockCommand(): string {
  try {
    const spec = Asc.scope.elnTemplateFormulaLocks;
    if (!spec || !['lock', 'restore', 'unlock', 'verify'].includes(spec.mode)) throw new Error('缺少公式结果锁配置');
    const primaryTag = spec.mode === 'restore' ? spec.snapshot?.primaryTag : spec.primaryTag;
    if (!primaryTag || !primaryTag.startsWith('eln.field.')) throw new Error('公式结果主控件 Tag 无效');
    const fieldCode = primaryTag.slice('eln.field.'.length);
    if (!fieldCode) throw new Error('公式结果主控件 Tag 无效');
    const controls = Api.GetDocument().GetAllContentControls();
    const matches = controls.filter((control) => {
      const tag = String(control.GetTag?.() ?? '');
      return tag === primaryTag || tag.startsWith(`eln.ref.${fieldCode}.`);
    });
    if (matches.filter((control) => String(control.GetTag?.() ?? '') === primaryTag).length !== 1) throw new Error('无法按 Tag 定位唯一结果主控件');
    const snapshot =
      spec.mode === 'restore'
        ? spec.snapshot
        : {
            primaryTag,
            locks: matches.map((control) => ({ tag: String(control.GetTag?.() ?? ''), lock: String(control.GetLock?.() ?? '') })),
          };
    if (!snapshot || !Array.isArray(snapshot.locks) || snapshot.locks.length !== matches.length) throw new Error('公式结果锁快照不完整');
    const mode: string = spec.mode;
    const expected = new Map(
      snapshot.locks.map((item) => [item.tag, mode === 'lock' || mode === 'verify' ? 'sdtContentLocked' : mode === 'unlock' ? 'unlocked' : item.lock]),
    );
    if (expected.size !== matches.length || matches.some((control) => !expected.has(String(control.GetTag?.() ?? ''))))
      throw new Error('公式结果锁快照与文档不一致');
    if (spec.mode !== 'verify') {
      const original = matches.map((control) => ({ control, lock: String(control.GetLock?.() ?? '') }));
      try {
        for (const control of matches) {
          const tag = String(control.GetTag?.() ?? '');
          if (control.SetLock?.(expected.get(tag)!) !== true) throw new Error('设置公式结果控件锁失败');
        }
      } catch (error) {
        for (const item of original) item.control.SetLock?.(item.lock);
        throw error;
      }
    }
    for (const control of matches) {
      const tag = String(control.GetTag?.() ?? '');
      if (String(control.GetLock?.() ?? '') !== expected.get(tag)) throw new Error('公式结果控件锁回读不一致');
    }
    return JSON.stringify({ ok: true, snapshot });
  } catch (error: unknown) {
    return JSON.stringify({ ok: false, error: error && (error as { message?: unknown }).message ? (error as { message: unknown }).message : String(error) });
  }
}

export function disableTrackRevisionsCommand(): string {
  try {
    if (!Asc.scope.elnTemplateReview) {
      throw new Error('缺少修订配置');
    }
    const doc = Api.GetDocument();
    if (typeof doc.AcceptAllRevisionChanges !== 'function') {
      throw new Error('当前编辑器不支持接受修订');
    }
    if (typeof doc.SetTrackRevisions !== 'function') {
      throw new Error('当前编辑器不支持关闭修订');
    }
    if (typeof doc.IsTrackRevisions !== 'function') {
      throw new Error('当前编辑器不支持确认修订状态');
    }
    if (typeof doc.Document?.HaveRevisionChanges !== 'function') {
      throw new Error('当前编辑器不支持确认历史修订状态');
    }
    if (typeof doc.Document.SetTrackRevisions !== 'function') {
      throw new Error('当前编辑器不支持关闭本地修订');
    }
    if (doc.AcceptAllRevisionChanges() === false) {
      throw new Error('接受历史修订失败');
    }
    if (doc.Document.HaveRevisionChanges(true) !== false) {
      throw new Error('历史修订仍未全部接受');
    }
    if (doc.SetTrackRevisions(false) === false) {
      throw new Error('关闭修订失败');
    }
    doc.Document.SetTrackRevisions(false);
    if (doc.IsTrackRevisions() !== false) {
      throw new Error('修订跟踪仍处于开启状态');
    }
    return JSON.stringify({ ok: true });
  } catch (error: unknown) {
    return JSON.stringify({
      ok: false,
      error: error && (error as { message?: unknown }).message ? (error as { message: unknown }).message : String(error),
    });
  }
}

export function readTrackRevisionsStateCommand(): string {
  try {
    if (!Asc.scope.elnTemplateReviewState) {
      throw new Error('缺少修订状态读取配置');
    }
    const doc = Api.GetDocument();
    if (typeof doc.IsTrackRevisions !== 'function') {
      throw new Error('当前编辑器不支持确认修订状态');
    }
    if (typeof doc.Document?.HaveRevisionChanges !== 'function') {
      throw new Error('当前编辑器不支持确认历史修订状态');
    }
    return JSON.stringify({
      hasRevisionChanges: doc.Document.HaveRevisionChanges(true),
      ok: true,
      trackRevisions: doc.IsTrackRevisions(),
    });
  } catch (error: unknown) {
    return JSON.stringify({
      ok: false,
      error: error && (error as { message?: unknown }).message ? (error as { message: unknown }).message : String(error),
    });
  }
}

export function listContentControlsCommand(): string {
  try {
    if (!Asc.scope.elnTemplateList) {
      throw new Error('缺少内容控件列表配置');
    }

    const controls = Api.GetDocument().GetAllContentControls();
    const result = controls.map((control) => {
      let controlType = 'text';
      if (control.IsCheckBox?.()) controlType = 'checkbox';
      else if (control.IsComboBox?.() || control.IsDropDownList?.()) controlType = 'dropdown';
      else if (control.IsDatePicker?.()) controlType = 'date';
      else if (control.IsBlockLevel?.()) controlType = 'multiline';

      const tag = String(control.GetTag?.() ?? '');
      const controlRole = tag.startsWith('eln.ref.')
        ? 'REFERENCE'
        : tag.startsWith('eln.field.')
          ? 'PRIMARY'
          : tag.startsWith('eln.repeat.')
            ? 'REPEAT'
            : 'UNKNOWN';
      const config: Record<string, unknown> = {};
      const placeholder = String(control.GetPlaceholderText?.() ?? '');
      if (controlType === 'dropdown') {
        const items = control.GetDropdownList?.().GetAllItems?.();
        if (!Array.isArray(items)) throw new Error('无法读取下拉控件选项');
        const options = items.map((item) => ({ display: String(item.GetText?.() ?? ''), value: String(item.GetValue?.() ?? '') }));
        config.options = options;
        config.placeholder = placeholder;
        if (controlRole === 'PRIMARY') {
          const currentText = String(control.GetRange?.()?.GetText?.() ?? '');
          const selected =
            currentText && currentText !== placeholder ? options.find((option) => option.display === currentText || option.value === currentText) : undefined;
          if (currentText && currentText !== placeholder && !selected) throw new Error('下拉控件当前值不在选项中');
          config.defaultValue = selected?.value ?? '';
        }
      } else if (controlType === 'checkbox') {
        if (typeof control.IsCheckBoxChecked !== 'function') throw new Error('无法读取复选框状态');
        config.defaultChecked = Boolean(control.IsCheckBoxChecked());
      } else if (controlType === 'date') {
        const json = control.ToJSON?.(false);
        if (typeof json !== 'string') throw new Error('无法读取日期控件格式');
        let dateFormat: unknown;
        try {
          dateFormat = (JSON.parse(json) as { sdtPr?: { date?: { dateFormat?: unknown } } }).sdtPr?.date?.dateFormat;
        } catch {
          throw new Error('日期控件结构数据无效');
        }
        if (typeof dateFormat !== 'string' || !dateFormat) throw new Error('无法读取日期控件格式');
        config.dateFormat = dateFormat;
        config.placeholder = placeholder;
      } else {
        config.placeholder = placeholder;
      }

      return {
        Alias: String(control.GetAlias?.() ?? ''),
        ControlConfig: config,
        ControlRole: controlRole,
        ControlType: controlType,
        InternalId: String(control.GetInternalId?.() ?? ''),
        Lock: String(control.GetLock?.() ?? ''),
        Tag: tag,
      };
    });

    return JSON.stringify({ ok: true, controls: result });
  } catch (error: unknown) {
    return JSON.stringify({
      ok: false,
      error: error && (error as { message?: unknown }).message ? (error as { message: unknown }).message : String(error),
    });
  }
}

export function readControlTextCommand(): string {
  try {
    const spec = Asc.scope.elnTemplateReadText;
    if (!spec) throw new Error('缺少文本读取配置');
    const matches = Api.GetDocument()
      .GetAllContentControls()
      .filter((control) => control.GetTag() === spec.tag);
    if (matches.length !== 1) throw new Error('无法按 Tag 定位唯一主字段控件');
    const range = matches[0]!.GetRange?.();
    if (!range || typeof range.GetText !== 'function') throw new Error('当前编辑器不支持读取控件文本');
    return JSON.stringify({ ok: true, text: String(range.GetText()) });
  } catch (error: unknown) {
    return JSON.stringify({ ok: false, error: error && (error as { message?: unknown }).message ? (error as { message: unknown }).message : String(error) });
  }
}

export function updateControlSpecCommand(): string {
  function requireSuccess(result: unknown, label: string): void {
    if (result !== true) throw new Error(`${label}失败`);
  }

  function typeOf(control: OnlyOfficeContentControl): string {
    if (control.IsCheckBox?.()) return 'CHECKBOX';
    if (control.IsComboBox?.() || control.IsDropDownList?.()) return 'DROPDOWN';
    if (control.IsDatePicker?.()) return 'DATE';
    if (control.IsBlockLevel?.()) return 'MULTILINE';
    return 'TEXT';
  }

  function optionsOf(config: Record<string, unknown>): Array<{ display: string; value: string }> {
    if (!Array.isArray(config.options)) return [];
    return config.options.map((option) => {
      if (typeof option === 'object' && option && 'display' in option && 'value' in option) {
        return { display: String(option.display), value: String(option.value) };
      }
      return { display: String(option), value: String(option) };
    });
  }

  function controlOptions(control: OnlyOfficeContentControl): Array<{ display: string; value: string }> {
    const items = control.GetDropdownList?.().GetAllItems?.();
    if (!Array.isArray(items)) throw new Error('无法读取下拉控件选项');
    return items.map((item) => ({ display: String(item.GetText?.() ?? ''), value: String(item.GetValue?.() ?? '') }));
  }

  function dateFormatOf(control: OnlyOfficeContentControl): string {
    const json = control.ToJSON?.(false);
    if (typeof json !== 'string') throw new Error('无法读取日期控件格式');
    let value: unknown;
    try {
      value = (JSON.parse(json) as { sdtPr?: { date?: { dateFormat?: unknown } } }).sdtPr?.date?.dateFormat;
    } catch {
      throw new Error('日期控件结构数据无效');
    }
    if (value === undefined) return 'yyyy-MM-dd';
    if (typeof value !== 'string' || !value) throw new Error('无法读取日期控件格式');
    return value;
  }

  function snapshot(control: OnlyOfficeContentControl) {
    const controlType = typeOf(control);
    return {
      alias: String(control.GetAlias?.() ?? ''),
      checked: controlType === 'CHECKBOX' ? Boolean(control.IsCheckBoxChecked?.()) : false,
      control,
      controlType,
      currentText: String(control.GetRange?.()?.GetText?.() ?? ''),
      dateFormat: controlType === 'DATE' ? dateFormatOf(control) : '',
      lock: String(control.GetLock?.() ?? ''),
      options: controlType === 'DROPDOWN' ? controlOptions(control) : [],
      placeholder: String(control.GetPlaceholderText?.() ?? ''),
      tag: String(control.GetTag()),
    };
  }

  function rollbackCall(action: () => unknown): boolean {
    try {
      return action() === true;
    } catch {
      return false;
    }
  }

  function restore(original: ReturnType<typeof snapshot>): boolean {
    const control = original.control;
    let restored = true;
    const apply = (action: () => unknown) => {
      if (!rollbackCall(action)) restored = false;
    };
    apply(() => control.SetTag?.(original.tag));
    apply(() => control.SetAlias?.(original.alias));
    apply(() => control.SetLock?.(original.lock));
    if (original.controlType !== 'CHECKBOX') apply(() => control.SetPlaceholderText?.(original.placeholder));
    if (original.controlType === 'DROPDOWN') {
      const list = control.GetDropdownList?.();
      apply(() => list?.Clear?.());
      for (const option of original.options) apply(() => list?.Add?.(option.display, option.value));
      const selected = original.options.find((option) => option.display === original.currentText || option.value === original.currentText);
      if (selected) apply(() => control.SelectListItem?.(selected.value));
    } else if (original.controlType === 'CHECKBOX') {
      apply(() => control.SetCheckBoxChecked?.(original.checked));
    } else if (original.controlType === 'DATE') {
      apply(() => control.SetDateFormat?.(original.dateFormat));
    }
    return restored;
  }

  function configure(control: OnlyOfficeContentControl, item: UpdateControlSpec, currentText: string): void {
    const config = item.controlConfig || {};
    requireSuccess(control.SetTag?.(item.tag), '设置 Tag');
    requireSuccess(control.SetAlias?.(item.alias), '设置字段名称');
    requireSuccess(control.SetLock?.(item.lock), '设置控件锁定状态');
    const placeholder = typeof config.placeholder === 'string' ? config.placeholder : '';
    if (placeholder && item.controlType !== 'CHECKBOX') requireSuccess(control.SetPlaceholderText?.(placeholder), '设置占位文本');
    if (item.controlType === 'DROPDOWN') {
      const list = control.GetDropdownList?.();
      if (!list || typeof list.Clear !== 'function' || typeof list.Add !== 'function') throw new Error('当前编辑器不支持更新下拉选项');
      requireSuccess(list.Clear(), '清空下拉选项');
      const options = optionsOf(config);
      for (const option of options) requireSuccess(list.Add(option.display, option.value), '写入下拉选项');
      const selected = options.find((option) => option.display === currentText || option.value === currentText);
      if (selected && typeof control.SelectListItem === 'function') requireSuccess(control.SelectListItem(selected.value), '恢复下拉当前值');
    } else if (item.controlType === 'DATE') {
      const format = typeof config.dateFormat === 'string' ? config.dateFormat : 'yyyy-MM-dd';
      requireSuccess(control.SetDateFormat?.(format), '设置日期格式');
    }
  }

  try {
    const spec = Asc.scope.elnTemplateUpdateControls;
    if (!spec || !Array.isArray(spec.updates)) throw new Error('缺少控件更新配置');
    const removals = spec.removals ?? [];
    if (!Array.isArray(removals)) throw new Error('控件删除配置无效');
    if (removals.length > 1) throw new Error('当前阶段不支持一次删除多个控件');
    const controls = Api.GetDocument().GetAllContentControls();
    const updateTags = new Set<string>();
    const removalTags = new Set<string>();
    const prepared = spec.updates.map((item) => {
      if (updateTags.has(item.currentTag)) throw new Error('同一控件不能重复更新');
      updateTags.add(item.currentTag);
      const matches = controls.filter((control) => control.GetTag() === item.currentTag);
      if (matches.length !== 1) throw new Error('无法按 Tag 定位唯一待更新控件');
      return { item, original: snapshot(matches[0]!) };
    });
    for (const { item, original } of prepared) {
      const config = item.controlConfig || {};
      if (item.controlType !== 'CHECKBOX' && config.placeholder === '' && original.placeholder !== '') {
        throw new Error('当前编辑器不支持清空已有占位文本');
      }
      if (item.controlType !== 'CHECKBOX' && typeof config.placeholder === 'string' && config.placeholder !== '' && original.placeholder === '') {
        throw new Error('当前编辑器不支持为已有控件设置占位文本');
      }
      if (item.controlType === 'DROPDOWN' && original.currentText && original.currentText !== original.placeholder) {
        const options = optionsOf(config);
        if (!options.some((option) => option.display === original.currentText || option.value === original.currentText)) {
          throw new Error('下拉控件当前值不在新选项中');
        }
      }
    }
    const removalControls = removals.map((tag) => {
      if (removalTags.has(tag)) throw new Error('同一控件不能重复删除');
      removalTags.add(tag);
      if (updateTags.has(tag)) throw new Error('同一控件不能同时更新和删除');
      const matches = controls.filter((control) => control.GetTag() === tag);
      if (matches.length !== 1) throw new Error('无法按 Tag 定位唯一待删除控件');
      return matches[0]!;
    });
    const finalTags = new Set(
      controls.filter((control) => !updateTags.has(control.GetTag()) && !removalTags.has(control.GetTag())).map((control) => control.GetTag()),
    );
    for (const { item } of prepared) {
      if (finalTags.has(item.tag)) throw new Error('更新后的控件 Tag 重复');
      finalTags.add(item.tag);
    }
    const rebuilds = prepared.filter(({ item, original }) => original.controlType !== item.controlType);
    if (rebuilds.length) throw new Error('当前阶段不支持修改已有控件类型');

    const promotion = removalControls.length === 1 ? prepared.find(({ item }) => item.tag === removals[0]) : undefined;
    let temporaryTag = '';
    if (promotion) {
      let suffix = 0;
      do {
        temporaryTag = `eln.tmp.${Date.now().toString(36)}.${suffix}`;
        suffix += 1;
      } while (controls.some((control) => control.GetTag() === temporaryTag));
    }

    const applied: Array<ReturnType<typeof snapshot>> = [];
    let promotionTagAttempted = false;
    let updated = 0;
    try {
      if (promotion) {
        promotionTagAttempted = true;
        requireSuccess(removalControls[0]!.SetTag?.(temporaryTag), '暂存旧主控件 Tag');
      }
      for (const { item, original } of prepared) {
        applied.push(original);
        configure(original.control, item, original.currentText);
        updated += 1;
      }
      for (const control of removalControls) requireSuccess(control.Delete?.(false), '删除旧控件');
    } catch (error: unknown) {
      let rollbackFailed = false;
      for (let index = applied.length - 1; index >= 0; index -= 1) {
        if (!restore(applied[index]!)) rollbackFailed = true;
      }
      if (promotionTagAttempted && !rollbackCall(() => removalControls[0]!.SetTag?.(removals[0]!))) rollbackFailed = true;
      if (rollbackFailed) {
        const message = error && (error as { message?: unknown }).message ? (error as { message: unknown }).message : String(error);
        throw new Error(`${message}；文档回滚失败`);
      }
      throw error;
    }
    return JSON.stringify({ ok: true, updated });
  } catch (error: unknown) {
    return JSON.stringify({ ok: false, error: error && (error as { message?: unknown }).message ? (error as { message: unknown }).message : String(error) });
  }
}

export function insertTypedControlCommand(): string {
  const spec = Asc.scope.elnTemplateInsert;

  function requireMethod(target: unknown, name: string, label: string): void {
    if (!target || typeof (target as Record<string, unknown>)[name] !== 'function') {
      throw new Error(`当前编辑器不支持${label}`);
    }
  }

  function requireSuccess(result: unknown, label: string): void {
    if (result !== true) {
      throw new Error(`${label}失败`);
    }
  }

  function debug(event: string, details: Record<string, unknown>): void {
    if (spec?.debug && typeof console !== 'undefined') {
      console.info('[ELN annotator command]', new Date().toISOString(), 'insertTypedControlCommand', event, details);
    }
  }

  try {
    if (!spec) {
      throw new Error('缺少字段控件配置');
    }

    debug('start', { controlType: spec.controlType, tag: spec.tag });
    const doc = Api.GetDocument();
    const selectedTextPr = doc.GetRangeBySelect?.()?.GetTextPr?.() ?? doc.GetCurrentRun?.()?.GetTextPr?.();
    let control: OnlyOfficeContentControl | null = null;
    let inlineContainer: OnlyOfficeParagraph | null = null;
    let isBlock = false;

    if (spec.controlType === 'text') {
      if (typeof Api.CreateInlineLvlSdt !== 'function') {
        throw new Error('当前编辑器不支持单行文本控件');
      }
      control = Api.CreateInlineLvlSdt();
    } else if (spec.controlType === 'dropdown') {
      if (typeof Api.CreateComboBoxContentControl !== 'function') {
        throw new Error('当前编辑器不支持下拉控件');
      }
      control = Api.CreateComboBoxContentControl(spec.options, spec.selectedIndex);
    } else if (spec.controlType === 'checkbox') {
      if (typeof Api.CreateCheckBoxContentControl !== 'function') {
        throw new Error('当前编辑器不支持复选框控件');
      }
      control = Api.CreateCheckBoxContentControl({
        checked: Boolean(spec.defaultChecked),
        checkedSymbol: 0x2611,
        uncheckedSymbol: 0x2610,
      });
    } else if (spec.controlType === 'date') {
      if (typeof Api.CreateDatePickerContentControl !== 'function') {
        throw new Error('当前编辑器不支持日期控件');
      }
      const format = typeof spec.dateFormat === 'string' && spec.dateFormat ? spec.dateFormat : 'yyyy-MM-dd';
      control = Api.CreateDatePickerContentControl({
        format,
        lang: 'zh-CN',
      });
      if (spec.defaultValue) {
        const parts = /^(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2})(?::(\d{2}))?)?$/.exec(spec.defaultValue);
        if (!parts) throw new Error('日期默认值格式无效');
        const values = parts.slice(1).map((item) => Number(item || 0));
        const value = new Date(values[0], values[1] - 1, values[2], values[3], values[4], values[5]);
        if (
          value.getFullYear() !== values[0] ||
          value.getMonth() !== values[1] - 1 ||
          value.getDate() !== values[2] ||
          value.getHours() !== values[3] ||
          value.getMinutes() !== values[4] ||
          value.getSeconds() !== values[5]
        ) {
          throw new Error('日期默认值无效');
        }
        requireMethod(control, 'SetDate', '设置日期默认值');
        requireSuccess(control.SetDate!(value), '设置日期默认值');
      } else {
        requireMethod(control, 'RemoveAllElements', '清空日期默认值');
        requireSuccess(control.RemoveAllElements!(), '清空日期默认值');
      }
    } else if (spec.controlType === 'multiline') {
      if (typeof Api.CreateBlockLvlSdt !== 'function') {
        throw new Error('当前编辑器不支持多行文本控件');
      }
      control = Api.CreateBlockLvlSdt();
      isBlock = true;

      if (spec.defaultValue) {
        requireMethod(control, 'RemoveAllElements', '写入多行默认值');
        requireSuccess(control.RemoveAllElements!(), '清空多行默认值');
        spec.defaultValue.split(/\r?\n/).forEach((text, index) => {
          const paragraph = Api.CreateParagraph();
          paragraph.AddText(text);
          requireMethod(control, 'AddElement', '写入多行默认值');
          requireSuccess(control!.AddElement!(paragraph, index), '写入多行默认值');
        });
      }
    } else {
      throw new Error('不支持的字段控件类型');
    }

    if (!isBlock) {
      inlineContainer = Api.CreateParagraph();
      requireMethod(inlineContainer, 'AddInlineLvlSdt', '将文本控件挂入段落');
      inlineContainer.AddInlineLvlSdt(control);
      debug('attached-to-paragraph', { controlType: spec.controlType, tag: spec.tag });
    }

    if (spec.controlType === 'text' && spec.defaultValue) {
      const run = Api.CreateRun();
      requireMethod(run, 'AddText', '写入文本默认值');
      requireMethod(control, 'RemoveAllElements', '写入文本默认值');
      requireMethod(control, 'AddElement', '写入文本默认值');
      requireSuccess(run.AddText!(spec.defaultValue), '写入文本默认值');
      requireSuccess(control.RemoveAllElements!(), '清空文本默认值');
      requireSuccess(control.AddElement!(run, 0), '写入文本默认值');
    }

    requireMethod(control, 'SetTag', '设置 Tag');
    requireMethod(control, 'SetAlias', '设置字段名称');
    requireMethod(control, 'SetLock', '设置控件锁定状态');
    requireMethod(control, 'SetAppearance', '设置控件外观');
    const tagResult = control.SetTag!(spec.tag);
    debug('set-tag', { result: tagResult, tag: spec.tag });
    requireSuccess(tagResult, '设置 Tag');
    const aliasResult = control.SetAlias!(spec.alias);
    debug('set-alias', { result: aliasResult });
    requireSuccess(aliasResult, '设置字段名称');
    const lockResult = control.SetLock!(spec.lock ?? 'unlocked');
    debug('set-lock', { result: lockResult });
    requireSuccess(lockResult, '设置控件锁定状态');
    control.SetAppearance!('boundingBox');

    if (spec.color) {
      requireMethod(Api, 'CreateRGBColor', '创建控件颜色');
      requireMethod(control, 'SetColor', '设置控件颜色');
      requireSuccess(control.SetColor!(Api.CreateRGBColor!(spec.color.R, spec.color.G, spec.color.B)), '设置控件颜色');
    }

    const hasDefault = spec.controlType === 'dropdown' ? spec.selectedIndex >= 0 : Boolean(spec.defaultValue);

    if (spec.controlType !== 'checkbox' && !hasDefault && spec.placeholder) {
      requireMethod(control, 'SetPlaceholderText', '设置占位文本');
      requireSuccess(control.SetPlaceholderText!(spec.placeholder), '设置占位文本');
    }

    requireMethod(doc, 'InsertContent', '插入内容控件');
    if (isBlock) {
      const insertResult = doc.InsertContent!([control], false);
      debug('insert-content', { isBlock, result: insertResult });
      requireSuccess(insertResult, '插入内容控件');
    } else {
      const insertResult = doc.InsertContent!([inlineContainer!], true);
      debug('insert-content', { isBlock, result: insertResult });
      requireSuccess(insertResult, '插入内容控件');
    }

    if (selectedTextPr) {
      const insertedControls = doc.GetAllContentControls().filter((item) => item.GetTag() === spec.tag);
      if (insertedControls.length !== 1) {
        throw new Error('无法按 Tag 定位唯一的新控件');
      }
      const insertedControl = insertedControls[0]!;
      requireMethod(insertedControl, 'GetRange', '读取新控件格式范围');
      const controlRange = insertedControl.GetRange!();
      requireMethod(controlRange, 'SetTextPr', '继承选区格式');
      if (!controlRange.SetTextPr!(selectedTextPr)) {
        throw new Error('继承选区格式失败');
      }
    }

    return JSON.stringify({
      ok: true,
      controlType: spec.controlType,
    });
  } catch (error: unknown) {
    debug('error', { error: error && (error as { message?: unknown }).message ? String((error as { message: unknown }).message) : String(error) });
    return JSON.stringify({
      ok: false,
      error: error && (error as { message?: unknown }).message ? (error as { message: unknown }).message : String(error),
    });
  }
}

export function writeTextDefaultCommand(): string {
  const spec = Asc.scope.elnTemplateTextDefault;

  function requireMethod(target: unknown, name: string, label: string): void {
    if (!target || typeof (target as Record<string, unknown>)[name] !== 'function') {
      throw new Error(`当前编辑器不支持${label}`);
    }
  }

  function requireSuccess(result: unknown, label: string): void {
    if (result !== true) {
      throw new Error(`${label}失败`);
    }
  }

  try {
    if (!spec) {
      throw new Error('缺少文本默认值配置');
    }

    const controls = Api.GetDocument().GetAllContentControls();
    const matches: OnlyOfficeContentControl[] = [];

    for (let index = 0; index < controls.length; index += 1) {
      if (controls[index]!.GetTag() === spec.tag) {
        matches.push(controls[index]!);
      }
    }

    if (matches.length !== 1) {
      throw new Error('无法按 Tag 定位唯一控件');
    }

    const control = matches[0]!;
    requireMethod(control, 'GetRange', '读取文本默认值');
    const originalTextPr = control.GetRange!().GetTextPr?.();
    const run = Api.CreateRun();
    requireMethod(run, 'AddText', '写入文本默认值');
    requireMethod(control, 'RemoveAllElements', '写入文本默认值');
    requireMethod(control, 'AddElement', '写入文本默认值');
    requireSuccess(run.AddText!(spec.value), '写入文本默认值');
    control.RemoveAllElements!();
    requireSuccess(control.AddElement!(run, 0), '写入文本默认值');
    const range = control.GetRange!();
    if (originalTextPr) {
      requireMethod(range, 'SetTextPr', '保留文本格式');
      if (!range.SetTextPr!(originalTextPr)) {
        throw new Error('保留文本格式失败');
      }
    }
    requireMethod(range, 'GetText', '回读文本默认值');
    if (range.GetText!() !== spec.value) {
      throw new Error('文本默认值回读不一致');
    }

    return JSON.stringify({ ok: true });
  } catch (error: unknown) {
    return JSON.stringify({
      ok: false,
      error: error && (error as { message?: unknown }).message ? (error as { message: unknown }).message : String(error),
    });
  }
}
