import type { OnlyOfficeContentControl } from './types';

export function disableTrackRevisionsCommand(): string {
  try {
    if (!Asc.scope.elnTemplateReview) {
      throw new Error('缺少修订配置');
    }
    const doc = Api.GetDocument();
    if (typeof doc.SetTrackRevisions !== 'function') {
      throw new Error('当前编辑器不支持关闭修订');
    }
    if (doc.SetTrackRevisions(false) === 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 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';

      return {
        Alias: String(control.GetAlias?.() ?? ''),
        ControlType: controlType,
        InternalId: String(control.GetInternalId?.() ?? ''),
        Tag: String(control.GetTag?.() ?? ''),
      };
    });

    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 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}失败`);
    }
  }

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

    const doc = Api.GetDocument();
    let control: OnlyOfficeContentControl | null = null;
    let isBlock = false;

    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('当前编辑器不支持日期控件');
      }
      control = Api.CreateDatePickerContentControl({
        format: 'yyyy-MM-dd',
        lang: 'zh-CN',
      });
      if (spec.defaultValue) {
        const dateParts = spec.defaultValue.split('-');
        requireMethod(control, 'SetDate', '设置日期默认值');
        requireSuccess(control.SetDate!(new Date(Number(dateParts[0]), Number(dateParts[1]) - 1, Number(dateParts[2]))), '设置日期默认值');
      }
    } 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('不支持的字段控件类型');
    }

    requireMethod(control, 'SetTag', '设置 Tag');
    requireMethod(control, 'SetAlias', '设置字段名称');
    requireMethod(control, 'SetLock', '设置控件锁定状态');
    requireMethod(control, 'SetAppearance', '设置控件外观');
    requireSuccess(control.SetTag!(spec.tag), '设置 Tag');
    requireSuccess(control.SetAlias!(spec.alias), '设置字段名称');
    requireSuccess(control.SetLock!('unlocked'), '设置控件锁定状态');
    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) {
      requireSuccess(doc.InsertContent!([control], false), '插入内容控件');
    } else {
      const container = Api.CreateParagraph();
      container.AddInlineLvlSdt(control);
      requireSuccess(doc.InsertContent!([container], true), '插入内容控件');
    }

    return JSON.stringify({
      ok: true,
      controlType: spec.controlType,
    });
  } catch (error: unknown) {
    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]!;
    const run = Api.CreateRun();
    requireMethod(run, 'AddText', '写入文本默认值');
    requireMethod(control, 'RemoveAllElements', '写入文本默认值');
    requireMethod(control, 'AddElement', '写入文本默认值');
    requireMethod(control, 'GetRange', '回读文本默认值');
    requireSuccess(run.AddText!(spec.value), '写入文本默认值');
    control.RemoveAllElements!();
    requireSuccess(control.AddElement!(run, 0), '写入文本默认值');
    const range = control.GetRange!();
    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),
    });
  }
}
