import type { DmsPrintConfig } from '#/components/GlobalOfficeDocumentModal/types';

import { v4 as uuidv4 } from 'uuid';

import { defHttp } from '#/api/request';

export interface DmsPrintBatch {
  id: string;
  pages: number[];
  items: number[];
  state: 'READY' | 'SENDING' | 'SUBMITTED';
  token?: string;
}

export interface DmsPrintAttempt {
  id: string;
  tenantId: string;
  userId: string;
  taskId: string;
  fileVersionId: string;
  copies: number;
  state: 'OPEN' | 'CONFIRMED' | 'CLOSED';
  batchesJson: string;
  numbersJson: string;
}

const endpoint = '/api/dms/biz/wenjian/dayin/renwu/';
async function request<T>(path: string, data: unknown): Promise<T> {
  const response = await defHttp.post<{ code: number; data: T; msg?: string }>({ url: endpoint + path, data }, { errorMessageMode: 'none' });
  if (response.code !== 200) throw new Error(response.msg || '保存打印发送进度失败');
  return response.data;
}

/** Reuse fixed task numbers; the online form controls barcode display text. */
export async function loadDmsPrintPreviewNumber(taskId: string, fileVersionId: string) {
  return request<import('./dmsPrintBarcode').DmsFixedPrintNumber>('yulan-canshu', { taskId, fileVersionId });
}

export function prepareDmsPrintAttempt(config: DmsPrintConfig, copies: number) {
  return request<DmsPrintAttempt>('zhunbei-fasong', {
    requestId: uuidv4(),
    taskId: config.printTaskId,
    fileVersionId: config.fileVersionId,
    copies,
  });
}

export function attemptContext(attempt: DmsPrintAttempt) {
  return { requestId: attempt.id, taskId: attempt.taskId, fileVersionId: attempt.fileVersionId, copies: attempt.copies };
}

export function updateDmsPrintAttempt(attempt: DmsPrintAttempt, action: string, data: Record<string, unknown> = {}) {
  return request<DmsPrintAttempt>(action, { ...attemptContext(attempt), ...data });
}

export function attemptBatches(attempt: DmsPrintAttempt): DmsPrintBatch[] {
  return JSON.parse(attempt.batchesJson);
}

export async function confirmDmsPrintAttempt(attempt: DmsPrintAttempt) {
  await request('queren-fasong', { ...attemptContext(attempt), clientResult: 'SUBMITTED' });
}

export async function finishDmsPrintAttempt(attempt: DmsPrintAttempt) {
  await confirmDmsPrintAttempt(attempt);
  await request('jieshu-fasong', attemptContext(attempt));
}

function receiptKey(attempt: DmsPrintAttempt, batchId: string) {
  return `dms-print-receipt:${encodeURIComponent(attempt.tenantId)}:${encodeURIComponent(attempt.userId)}:${attempt.id}:${batchId}`;
}

/** 只有实际成功回调才能写入此 outbox；按租户/账号隔离，恢复时仍由服务端核对令牌。 */
export async function recordDmsBatchSubmitted(attempt: DmsPrintAttempt, batch: DmsPrintBatch, token: string) {
  const key = receiptKey(attempt, batch.id);
  try {
    localStorage.setItem(key, token);
  } catch {
    /* 服务端仍为权威；本地存储不可用时不能假定成功。 */
  }
  const saved = await updateDmsPrintAttempt(attempt, 'queren-pici', { batchId: batch.id, token });
  try {
    localStorage.removeItem(key);
  } catch {
    /* 重复回执由服务端幂等处理。 */
  }
  // 晚回传同样可推进正式确认，即使原页面等待已经超时。
  if (attemptBatches(saved).every((item) => item.state === 'SUBMITTED')) await confirmDmsPrintAttempt(saved);
  return saved;
}

export async function recoverDmsBatchReceipts(attempt: DmsPrintAttempt) {
  let saved = attempt;
  for (const batch of attemptBatches(attempt)) {
    let token: null | string = null;
    try {
      token = localStorage.getItem(receiptKey(attempt, batch.id));
    } catch {
      /* 不具备本地证据时保持未知。 */
    }
    if (token) saved = await recordDmsBatchSubmitted(saved, batch, token);
  }
  return saved;
}
