import type { StandardizeMaterialInput } from '@/services/automationService';

const ONLINE_STANDARDIZATION_QUEUE_KEY = 'autoprocurement.standardization.online-queue';

export type OnlineStandardizationQueueItemStatus = 'queued' | 'submitting' | 'failed';

export interface OnlineStandardizationQueuePayload {
  batchId: string;
  materialIds?: string[];
  materials?: StandardizeMaterialInput[];
  totalRows: number;
}

export interface OnlineStandardizationQueueItem extends OnlineStandardizationQueuePayload {
  id: string;
  fingerprint: string;
  createdAt: string;
  status: OnlineStandardizationQueueItemStatus;
  errorMessage: string;
  blockedUntil: string | null;
}

function readJson<T>(key: string): T | null {
  if (typeof window === 'undefined') {
    return null;
  }

  const rawValue = window.localStorage.getItem(key);
  if (!rawValue) {
    return null;
  }

  try {
    return JSON.parse(rawValue) as T;
  } catch {
    window.localStorage.removeItem(key);
    return null;
  }
}

function writeJson<T>(key: string, value: T) {
  if (typeof window === 'undefined') {
    return;
  }

  window.localStorage.setItem(key, JSON.stringify(value));
}

function normalizeIsoDateString(value: unknown): string | null {
  if (typeof value !== 'string') {
    return null;
  }

  const timestamp = Date.parse(value);
  if (!Number.isFinite(timestamp)) {
    return null;
  }

  return new Date(timestamp).toISOString();
}

function isStandardizeMaterialInput(value: unknown): value is StandardizeMaterialInput {
  if (!value || typeof value !== 'object') {
    return false;
  }

  const material = value as Record<string, unknown>;
  return typeof material.id === 'string'
    && typeof material.material_name === 'string'
    && typeof material.specification === 'string'
    && typeof material.quantity === 'number'
    && typeof material.unit === 'string'
    && typeof material.invoice_type === 'string'
    && typeof material.brand === 'string'
    && typeof material.remarks === 'string'
    && typeof material.delivery_address === 'string';
}

function isStringArray(value: unknown): value is string[] {
  return Array.isArray(value) && value.every((item) => typeof item === 'string');
}

function isOnlineStandardizationQueueItem(value: unknown): value is OnlineStandardizationQueueItem {
  if (!value || typeof value !== 'object') {
    return false;
  }

  const item = value as Record<string, unknown>;
  const validStatus = item.status === 'queued' || item.status === 'submitting' || item.status === 'failed';
  const validMaterials = item.materials === undefined
    || (Array.isArray(item.materials) && item.materials.every(isStandardizeMaterialInput));

  return typeof item.id === 'string'
    && typeof item.fingerprint === 'string'
    && typeof item.batchId === 'string'
    && typeof item.createdAt === 'string'
    && typeof item.totalRows === 'number'
    && validStatus
    && typeof item.errorMessage === 'string'
    && (item.blockedUntil === null || item.blockedUntil === undefined || typeof item.blockedUntil === 'string')
    && (item.materialIds === undefined || isStringArray(item.materialIds))
    && validMaterials;
}

export function buildOnlineStandardizationQueueFingerprint(payload: OnlineStandardizationQueuePayload) {
  const explicitMaterialIds = payload.materialIds?.length
    ? [...payload.materialIds].sort()
    : (payload.materials ?? []).map((item) => item.id).filter(Boolean).sort();
  const scope = explicitMaterialIds.length > 0 ? explicitMaterialIds.join(',') : `all:${payload.totalRows}`;
  return `${payload.batchId}::${scope}`;
}

export function getStoredOnlineStandardizationQueue() {
  const value = readJson<unknown>(ONLINE_STANDARDIZATION_QUEUE_KEY);
  if (!Array.isArray(value) || !value.every(isOnlineStandardizationQueueItem)) {
    if (value !== null && typeof window !== 'undefined') {
      window.localStorage.removeItem(ONLINE_STANDARDIZATION_QUEUE_KEY);
    }
    return [] as OnlineStandardizationQueueItem[];
  }

  return value.map((item) => ({
    ...item,
    materials: undefined as undefined,
    createdAt: normalizeIsoDateString(item.createdAt) ?? new Date().toISOString(),
    status: item.status === 'submitting' ? 'queued' : item.status,
    blockedUntil: normalizeIsoDateString(item.blockedUntil),
    errorMessage: item.errorMessage ?? '',
  }));
}

export function saveStoredOnlineStandardizationQueue(queue: OnlineStandardizationQueueItem[]) {
  writeJson(
    ONLINE_STANDARDIZATION_QUEUE_KEY,
    queue.map((item) => ({
      ...item,
      materials: undefined as undefined,
    })),
  );
}