export const AUDIT_BIZ_SIGN_HEADER = 'X-Audit-Biz-Sign';

const EVENT_TIMEOUT_MS = 5 * 60 * 1000;
const SIGN_PATTERN = /^[\w-]{1,40}$/;

interface AuditBizSignEvent {
  bizSign: string;
  expiresAt: number;
  timeout: ReturnType<typeof setTimeout>;
  token: symbol;
}

let activeEvent: AuditBizSignEvent | undefined;
let eventQueue: Promise<void> = Promise.resolve();

export async function runWithAuditBizSignEvent<T>(bizSign: unknown, submit: () => Promise<T> | T): Promise<T> {
  const normalizedBizSign = normalizeBizSign(bizSign);
  if (!normalizedBizSign) throw new Error('电子签名认证结果无效');

  const previousEvent = eventQueue;
  let releaseEvent!: () => void;
  eventQueue = new Promise<void>((resolve) => {
    releaseEvent = resolve;
  });
  await previousEvent;

  const token = Symbol('audit-biz-sign-event');
  const timeout = setTimeout(() => clearEvent(token), EVENT_TIMEOUT_MS);
  activeEvent = {
    bizSign: normalizedBizSign,
    expiresAt: Date.now() + EVENT_TIMEOUT_MS,
    timeout,
    token,
  };

  try {
    return await submit();
  } finally {
    clearEvent(token);
    releaseEvent();
  }
}

export function getActiveAuditBizSign(): string {
  if (!activeEvent) return '';
  if (activeEvent.expiresAt <= Date.now()) {
    clearEvent(activeEvent.token);
    return '';
  }
  return activeEvent.bizSign;
}

export function applyActiveAuditBizSign(headers: Record<string, any>, url: string | undefined, method: string | undefined, apiBaseUrl = ''): void {
  const bizSign = getActiveAuditBizSign();
  if (!bizSign || hasHeader(headers, AUDIT_BIZ_SIGN_HEADER) || !shouldAttachAuditBizSign(url, method, apiBaseUrl)) return;
  headers[AUDIT_BIZ_SIGN_HEADER] = bizSign;
}

export function shouldAttachAuditBizSign(url: string | undefined, method: string | undefined, apiBaseUrl = ''): boolean {
  if (!['delete', 'patch', 'post', 'put'].includes(String(method || '').toLowerCase())) return false;
  if (!url || url.startsWith('//')) return false;

  try {
    const browserOrigin = globalThis.location?.origin || 'http://audit.local';
    const resolved = new URL(url, browserOrigin);
    const configuredApi = new URL(apiBaseUrl || '/', browserOrigin);
    if (resolved.origin !== configuredApi.origin) return false;
    const pathname = stripApiBasePath(resolved.pathname, configuredApi.pathname);
    if (!pathname.startsWith('/api/')) return false;
    return !isExcludedPath(pathname);
  } catch {
    return false;
  }
}

function hasHeader(headers: Record<string, any>, name: string): boolean {
  if (typeof headers?.has === 'function' && headers.has(name)) return true;
  return Object.keys(headers || {}).some((key) => key.toLowerCase() === name.toLowerCase());
}

function normalizeBizSign(value: unknown): string {
  const normalized = value == null ? '' : String(value).trim();
  return SIGN_PATTERN.test(normalized) ? normalized : '';
}

function stripApiBasePath(pathname: string, apiBasePath: string): string {
  const normalizedBasePath = apiBasePath.replace(/\/$/, '');
  if (!normalizedBasePath || normalizedBasePath === '/') return pathname;
  if (pathname === normalizedBasePath) return '/';
  return pathname.startsWith(`${normalizedBasePath}/`) ? pathname.slice(normalizedBasePath.length) : pathname;
}

function clearEvent(token: symbol) {
  if (activeEvent?.token !== token) return;
  clearTimeout(activeEvent.timeout);
  activeEvent = undefined;
}

function isExcludedPath(pathname: string): boolean {
  return (
    /\/sign\/(?:init-all|modify-password|verify|verify_user)\/?$/i.test(pathname) ||
    /^\/api\/oauth(?:\/|$)/i.test(pathname) ||
    /^\/api\/audit(?:\/|$)/i.test(pathname)
  );
}
