const HISTORY_DEBUG_BUILD = 'history-diagnostics-clean-2026-05-19';
const PERF_2D_DEBUG_BUILD = '2d-perf-diagnostics-2026-05-21';
const HISTORY_DEBUG_PREFIX = `[AsukaHistory:${HISTORY_DEBUG_BUILD}]`;

function readFlag(value: unknown): boolean | null {
  if (value === true) return true;
  if (value === false) return false;
  if (value == null) return null;
  const normalized = String(value).trim().toLowerCase();
  if (!normalized) return null;
  if (['0', 'false', 'off', 'no', 'disabled'].includes(normalized)) return false;
  if (['1', 'true', 'on', 'yes', 'enabled'].includes(normalized)) return true;
  return null;
}

export function isAsukaHistoryDebugEnabled(): boolean {
  try {
    const g: any = globalThis as any;
    const globalFlag = readFlag(g?.__ASUKA_DEBUG_HISTORY__);
    if (globalFlag !== null) return globalFlag;

    const win: any = typeof window !== 'undefined' ? window : null;
    const search = String(win?.location?.search ?? '');
    if (search) {
      const params = new URLSearchParams(search);
      const queryFlag = readFlag(params.get('asukaDebugHistory') ?? params.get('askDebugHistory'));
      if (queryFlag !== null) return queryFlag;
    }

    const storageFlag = readFlag(
      win?.localStorage?.getItem?.('asuka:debug:history') ??
      win?.sessionStorage?.getItem?.('asuka:debug:history')
    );
    if (storageFlag !== null) return storageFlag;
  } catch {}

  return false;
}


export function isAsuka2DPerfDebugEnabled(): boolean {
  try {
    const g: any = globalThis as any;
    const globalFlag = readFlag(g?.__ASUKA_DEBUG_2D_PERF__ ?? g?.__ASUKA_DEBUG_FABRIC_PERF__ ?? g?.__ASUKA_PERF_DEBUG__);
    if (globalFlag !== null) return globalFlag;

    const win: any = typeof window !== 'undefined' ? window : null;
    const search = String(win?.location?.search ?? '');
    if (search) {
      const params = new URLSearchParams(search);
      const queryFlag = readFlag(
        params.get('asukaDebug2DPerf') ??
        params.get('askDebug2DPerf') ??
        params.get('asukaDebugFabricPerf') ??
        params.get('askDebugFabricPerf') ??
        params.get('asukaPerf2D') ??
        params.get('asukaDebugHistory') ??
        params.get('askDebugHistory')
      );
      if (queryFlag !== null) return queryFlag;
    }

    const storageFlag = readFlag(
      win?.localStorage?.getItem?.('asuka:debug:2d-perf') ??
      win?.sessionStorage?.getItem?.('asuka:debug:2d-perf') ??
      win?.localStorage?.getItem?.('asuka:debug:fabric-perf') ??
      win?.sessionStorage?.getItem?.('asuka:debug:fabric-perf') ??
      win?.localStorage?.getItem?.('asuka:debug:history') ??
      win?.sessionStorage?.getItem?.('asuka:debug:history')
    );
    if (storageFlag !== null) return storageFlag;
  } catch {}

  return false;
}

export function getAsukaDebugPayloadSize(value: unknown): number | null {
  if (!isAsuka2DPerfDebugEnabled()) return null;
  try {
    const text = JSON.stringify(value ?? null);
    return typeof text === 'string' ? text.length : null;
  } catch {
    return null;
  }
}


export function asuka2DPerfDebug(phase: string, payload?: Record<string, unknown> | null): void {
  if (!isAsuka2DPerfDebugEnabled()) return;
  try {
    const logger = (console as any)?.debug ?? (console as any)?.log;
    if (!logger) return;
    logger.call(console, `[Asuka2DPerf:${PERF_2D_DEBUG_BUILD}] ${phase}`, sanitizePayload(payload ?? {}));
  } catch {}
}

function limitString(value: string, max = 180): string {
  return value.length > max ? `${value.slice(0, max)}…` : value;
}

export function summarizeHistoryTrack(track: any): Record<string, unknown> | null {
  if ((!isAsukaHistoryDebugEnabled() && !isAsuka2DPerfDebugEnabled()) || !track || typeof track !== 'object') return null;
  const snapshots = Array.isArray(track?.snapshots) ? track.snapshots : [];
  const index = Number(track?.index ?? -1);
  return {
    engine: track?.engine ?? null,
    scope: track?.scope ?? null,
    viewId: track?.viewId ?? null,
    length: snapshots.length,
    index,
    canUndo: index > 0,
    canRedo: index >= 0 && index < snapshots.length - 1,
    maxSnapshots: track?.maxSnapshots ?? null,
    hasLastSignature: Boolean(track?.lastSignature),
  };
}

export function summarizeHistoryInfo(info: any): Record<string, unknown> | null {
  if ((!isAsukaHistoryDebugEnabled() && !isAsuka2DPerfDebugEnabled()) || !info || typeof info !== 'object') return null;
  return {
    engine: info?.engine ?? null,
    scope: info?.scope ?? null,
    viewId: info?.viewId ?? null,
    index: Number(info?.index ?? -1),
    length: Number(info?.length ?? 0),
    canUndo: Boolean(info?.canUndo),
    canRedo: Boolean(info?.canRedo),
    maxSnapshots: Number(info?.maxSnapshots ?? 0) || null,
    reason: info?.reason ?? null,
  };
}

export function summarize3DScene(scene: any): Record<string, unknown> | null {
  if ((!isAsukaHistoryDebugEnabled() && !isAsuka2DPerfDebugEnabled()) || !scene || typeof scene !== 'object') return null;
  return {
    products: Array.isArray(scene?.products) ? scene.products.length : 0,
    productsWithModel: Array.isArray(scene?.products) ? scene.products.filter((product: any) => Boolean(product?.model?.url)).length : 0,
    decorations: Array.isArray(scene?.decorations) ? scene.decorations.length : 0,
    printAreas: Array.isArray(scene?.printAreas) ? scene.printAreas.length : 0,
    parts: Array.isArray(scene?.products)
      ? scene.products.reduce((count: number, product: any) => count + (Array.isArray(product?.parts) ? product.parts.length : 0), 0)
      : 0,
    activePrintAreaId: scene?.activePrintAreaId ?? null,
    selectedPartId: scene?.selectedPartId ?? null,
    selectedObjectId: scene?.selectedObjectId ?? null,
  };
}

function sanitizePayload(value: any, depth = 0): any {
  if (value == null) return value;
  if (depth > 4) return '[depth-limit]';
  const type = typeof value;
  if (type === 'string') return limitString(value);
  if (type === 'number' || type === 'boolean') return value;
  if (type === 'function') return `[function ${value.name || 'anonymous'}]`;
  if (Array.isArray(value)) {
    if (value.length > 12) return [...value.slice(0, 12).map((item) => sanitizePayload(item, depth + 1)), `…+${value.length - 12}`];
    return value.map((item) => sanitizePayload(item, depth + 1));
  }
  if (type === 'object') {
    if (typeof Element !== 'undefined' && value instanceof Element) {
      return { tagName: value.tagName, id: value.id || null, className: String((value as any).className ?? '') || null };
    }
    const out: Record<string, any> = {};
    let count = 0;
    for (const [key, entry] of Object.entries(value)) {
      if (count >= 30) {
        out.__truncated = true;
        break;
      }
      if (key === 'snapshots') {
        out.snapshots = summarizeHistoryTrack(value)?.length ?? 0;
      } else if (key.toLowerCase().includes('texture') || key.toLowerCase().includes('dataurl')) {
        out[key] = '[omitted]';
      } else {
        out[key] = sanitizePayload(entry, depth + 1);
      }
      count += 1;
    }
    return out;
  }
  return String(value);
}

export function asukaHistoryDebug(phase: string, payload?: Record<string, unknown> | null): void {
  if (!isAsukaHistoryDebugEnabled()) return;
  try {
    const logger = (console as any)?.debug ?? (console as any)?.log;
    if (!logger) return;
    logger.call(console, `${HISTORY_DEBUG_PREFIX} ${phase}`, sanitizePayload(payload ?? {}));
  } catch {}
}

export function getAsukaHistoryDebugBuild(): string {
  return HISTORY_DEBUG_BUILD;
}
