export const PLUGIN_GUID = 'asc.{C764F7D6-055D-4C7D-97FD-83D2C4440585}';
export const PLUGIN_VERSION = '0.1.0';
export const PLUGIN_BIZ_MODULE = 'dms';
export const PLUGIN_BIZ_SCENE = 'dms.qianpiye';
export const PLUGIN_SCOPE = 'onlyoffice:dms-qianpiye';

interface QianpiyePluginContextBase {
  apiBaseUrl: string;
  bizDataId?: string;
  bizModule: typeof PLUGIN_BIZ_MODULE;
  bizScene: typeof PLUGIN_BIZ_SCENE;
  documentId: string;
  pluginVersion: typeof PLUGIN_VERSION;
}

export type QianpiyePluginContext = QianpiyePluginContextBase & (
  | { canAnnotate: false }
  | { canAnnotate: true; scope: typeof PLUGIN_SCOPE; ticket: string }
);

export type WritableQianpiyePluginContext = Extract<QianpiyePluginContext, { canAnnotate: true }>;

function isRecord(value: unknown): value is Record<string, unknown> {
  return typeof value === 'object' && value !== null && !Array.isArray(value);
}

function isNonEmptyString(value: unknown): value is string {
  return typeof value === 'string' && value.trim().length > 0;
}

function isHttpUrl(value: unknown): value is string {
  if (!isNonEmptyString(value)) return false;
  try {
    const url = new URL(value);
    return ['http:', 'https:'].includes(url.protocol) && !url.username && !url.password && !url.search && !url.hash;
  } catch {
    return false;
  }
}

function parseOptions(options: unknown): unknown {
  if (typeof options !== 'string') return options;
  try {
    return JSON.parse(options) as unknown;
  } catch {
    return undefined;
  }
}

function resolvePluginOptions(options: unknown): unknown {
  const value = parseOptions(options);
  if (!isRecord(value) || 'apiBaseUrl' in value) return value;
  return parseOptions(value[PLUGIN_GUID]);
}

function validationFailure(value: unknown): string | undefined {
  if (!isRecord(value)) return '未收到插件上下文';
  const invalidFields = [
    !isHttpUrl(value.apiBaseUrl) ? 'apiBaseUrl' : '',
    !isNonEmptyString(value.documentId) ? 'documentId' : '',
    value.bizModule !== PLUGIN_BIZ_MODULE ? 'bizModule' : '',
    value.bizScene !== PLUGIN_BIZ_SCENE ? 'bizScene' : '',
    value.pluginVersion !== PLUGIN_VERSION ? 'pluginVersion' : '',
    typeof value.canAnnotate !== 'boolean' ? 'canAnnotate' : '',
    value.bizDataId !== undefined && value.bizDataId !== null && !isNonEmptyString(value.bizDataId)
      ? 'bizDataId'
      : '',
  ].filter(Boolean);
  if (value.canAnnotate === true) {
    if (value.scope !== PLUGIN_SCOPE) invalidFields.push('scope');
    if (!isNonEmptyString(value.ticket)) invalidFields.push('ticket');
  }
  return invalidFields.length > 0 ? `缺少或无效字段：${invalidFields.join(', ')}` : undefined;
}

export function parsePluginContext(options: unknown): QianpiyePluginContext {
  const value = resolvePluginOptions(options);
  if (!isRecord(value)) {
    throw new Error('签批页标注插件运行上下文无效（未收到插件上下文）');
  }
  const failure = validationFailure(value);
  if (failure) {
    throw new Error(`签批页标注插件运行上下文无效（${failure}）`);
  }
  const apiBaseUrl = value.apiBaseUrl;
  const documentId = value.documentId;
  const bizDataId = value.bizDataId;
  const canAnnotate = value.canAnnotate;
  if (!isHttpUrl(apiBaseUrl) || !isNonEmptyString(documentId) || typeof canAnnotate !== 'boolean') {
    throw new Error('签批页标注插件运行上下文无效（字段校验失败）');
  }
  const base: QianpiyePluginContextBase = {
    apiBaseUrl: apiBaseUrl.replace(/\/+$/u, ''),
    documentId,
    ...(isNonEmptyString(bizDataId) ? { bizDataId } : {}),
    bizModule: PLUGIN_BIZ_MODULE,
    bizScene: PLUGIN_BIZ_SCENE,
    pluginVersion: PLUGIN_VERSION,
  };
  if (!canAnnotate) {
    return { ...base, canAnnotate: false };
  }
  const ticket = value.ticket;
  if (value.scope !== PLUGIN_SCOPE || !isNonEmptyString(ticket)) {
    throw new Error('签批页标注插件运行上下文无效（缺少或无效字段：scope, ticket）');
  }
  return {
    ...base,
    canAnnotate: true,
    scope: PLUGIN_SCOPE,
    ticket,
  };
}
