import type { AuditEventListDTO, AuditOperation, AuditPageQuery } from './types';

const actionCodeLabels: Record<string, string> = {
  CREATE: '新增',
  DELETE: '删除',
  PRINT: '发起打印',
  READ: '查询',
  SIGN: '电子签名',
  UPDATE: '修改',
};

const eventTypeLabels: Record<string, string> = {
  BIZ_ACTION: '业务动作',
  DATA_CHANGE: '数据变更',
  E_SIGNATURE: '电子签名',
  PRINT: '打印日志',
};

const sourceLayerLabels: Record<number, string> = {
  0: '在线表单',
  1: '数据库变更',
  2: '业务动作',
  3: '电子签名',
};

/** Normalize one BUSINESS row and its related physical signature events. */
export function normalizeOperation(main: AuditEventListDTO): AuditOperation {
  const subEvents = Array.isArray(main.subEvents) ? main.subEvents : [];
  const eventIds = [main.id, ...subEvents.map((event) => event.id)];
  const layers = [...new Set([main, ...subEvents].flatMap((event) => (typeof event.sourceLayer === 'number' ? [event.sourceLayer] : [])))];
  const diffCount = toDiffCount(main.diffCount);
  const hasElectronicSignature = main.eventType === 'E_SIGNATURE' || subEvents.some((event) => event.eventType === 'E_SIGNATURE');

  return {
    ...main,
    correlationKey: main.operationId ?? main.clientEventId ?? `event:${main.id}`,
    diffCount,
    eventIds,
    layers,
    sourceSummary: getSourceSummary(layers, diffCount, main.eventType, hasElectronicSignature),
    subEvents,
  };
}

/** Timeline uses the same operation-level display contract as the page endpoint. */
export function groupTimelineOperations(events: AuditEventListDTO[]): AuditOperation[] {
  return events.map((event) => normalizeOperation(event));
}

/**
 * 动作名优先按 actionCode 映射：层 0 的基础三动作有稳定语义，映射后历史数据
 * （actionLabel 是 "LIMS-请验单 新建" 这种旧格式）也立刻显示对。
 * 层 2 事件的动作词是业务自定义的（"请验单 撤回"），映射表命不中，回落 actionLabel。
 */
export function getAuditActionLabel(event: Pick<AuditEventListDTO, 'actionCode' | 'actionLabel' | 'bizType'>): string {
  if (event.bizType === 'DMS_FOLDER' && event.actionLabel) return event.actionLabel;
  const mapped = event.actionCode ? actionCodeLabels[event.actionCode] : undefined;
  return mapped || event.actionLabel || event.actionCode || '未标记操作';
}

export function getAuditEventTypeLabel(eventType?: string): string {
  if (!eventType) return '未标记类型';
  return eventTypeLabels[eventType] || eventType;
}

export function getSourceLayerLabel(sourceLayer?: number, eventType?: string): string {
  if (eventType === 'PRINT') return '打印日志';
  if (sourceLayer === 3 && eventType !== 'E_SIGNATURE') return '业务埋点';
  if (sourceLayer === undefined) return '未知来源';
  return sourceLayerLabels[sourceLayer] || `采集层 ${sourceLayer}`;
}

export function getSourceSummary(layers: number[], diffCount: number, eventType?: string, hasElectronicSignature = eventType === 'E_SIGNATURE'): string {
  if (eventType === 'PRINT') return '打印日志';
  const hasBusinessAction = layers.includes(2);
  if (hasBusinessAction) {
    return ['业务动作', hasElectronicSignature ? '电子签名' : '', diffCount > 0 ? '字段变更' : ''].filter(Boolean).join(' + ');
  }
  if (hasElectronicSignature && diffCount > 0) return '电子签名 + 字段变更';
  if (hasElectronicSignature) return '电子签名';
  if (layers.includes(3) && diffCount > 0) return '业务埋点 + 字段变更';
  if (layers.includes(3)) return '业务埋点';
  if (layers.length === 1 && layers[0] === 0) return '在线表单';
  if (layers.length === 1 && layers[0] === 1) return '数据库变更';
  if (layers.includes(0) && layers.includes(1)) return '在线表单 + 数据库变更';
  return '未知来源';
}

export interface PrintAuditTarget {
  bizCode?: string;
  id: string;
  title?: string;
}

export function parsePrintAuditTargets(extra?: string): { parseError: boolean; targets: PrintAuditTarget[] } {
  if (!extra) return { parseError: false, targets: [] };
  try {
    const parsed = JSON.parse(extra);
    if (!Array.isArray(parsed?.printTargets)) return { parseError: false, targets: [] };
    const targets = parsed.printTargets.flatMap((item: unknown) => {
      if (!item || typeof item !== 'object') return [];
      const raw = item as Record<string, unknown>;
      const id = toOptionalText(raw.id);
      if (!id) return [];
      return [{ id, bizCode: toOptionalText(raw.bizCode), title: toOptionalText(raw.title) }];
    });
    return { parseError: false, targets };
  } catch {
    return { parseError: true, targets: [] };
  }
}

export function normalizeAuditPageQuery(query: Record<string, unknown>): AuditPageQuery {
  const normalized: Record<string, unknown> = {};
  for (const [key, value] of Object.entries(query)) {
    const nextValue = typeof value === 'string' ? value.trim() : value;
    if (nextValue !== '' && nextValue !== undefined && nextValue !== null) normalized[key] = nextValue;
  }
  return normalized as unknown as AuditPageQuery;
}

function toDiffCount(value?: number): number {
  return Number.isFinite(value) && Number(value) > 0 ? Number(value) : 0;
}

function toOptionalText(value: unknown): string | undefined {
  if (value === undefined || value === null) return;
  const text = String(value).trim();
  return text || undefined;
}
