import {
  WAREHOUSE_TYPES,
  WAREHOUSE_YARD_TYPES,
  WAREHOUSE_ZONE_TYPES,
  WAREHOUSE_STATUSES,
  INVENTORY_STATUSES,
} from '@/types/warehouse';

export const humanizeEnum = (value: string) =>
  value
    .toLowerCase()
    .split('_')
    .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
    .join(' ');

const toOptions = (values: readonly string[]) =>
  values.map((value) => ({ value, label: humanizeEnum(value) }));

export const warehouseTypeOptions = toOptions(WAREHOUSE_TYPES);
export const yardTypeOptions = toOptions(WAREHOUSE_YARD_TYPES);
export const zoneTypeOptions = toOptions(WAREHOUSE_ZONE_TYPES);
export const statusOptions = toOptions(WAREHOUSE_STATUSES);
export const inventoryStatusOptions = toOptions(INVENTORY_STATUSES);

export const formatNumber = (value: number | null | undefined) => {
  if (value === null || value === undefined) return '—';
  const num = Number(value);
  if (Number.isNaN(num)) return '—';
  return num.toLocaleString(undefined, { maximumFractionDigits: 3 });
};

export const formatCapacity = (current: number, capacity: number | null | undefined) => {
  const cur = formatNumber(current);
  if (capacity === null || capacity === undefined) return cur;
  return `${cur} / ${formatNumber(capacity)}`;
};

/** A day count as a short, human duration: "0.2d" / "3.5 days" / "—". */
export const formatDays = (value: number | null | undefined) => {
  if (value === null || value === undefined || Number.isNaN(Number(value))) return '—';
  const num = Number(value);
  const rounded = Math.round(num * 10) / 10;
  return `${rounded} ${rounded === 1 ? 'day' : 'days'}`;
};

export const formatDate = (value: string | null | undefined) => {
  if (!value) return '—';
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return '—';
  return date.toLocaleString(undefined, {
    year: 'numeric',
    month: 'short',
    day: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
  });
};

// Name fields (warehouse / fee rule / allocation rule) accept letters and spaces only — no numbers.
export const lettersOnly = (value: string) => value.replace(/[^A-Za-z\s]/g, '');

export const extractErrorMessage = (error: unknown, fallback = 'Something went wrong') => {
  const responseData = (error as { response?: { data?: unknown } })?.response?.data;
  const data = responseData && typeof responseData === 'object' ? (responseData as Record<string, unknown>) : undefined;
  const rawMessage = data?.message ?? data?.error ?? (error as Error)?.message;
  return Array.isArray(rawMessage) ? rawMessage.join(', ') : rawMessage ? String(rawMessage) : fallback;
};

/**
 * Error extractor for blob-download requests. When `responseType: 'blob'`, axios
 * delivers the JSON error body as a Blob, so `extractErrorMessage` can't read
 * `.message`. Decode the Blob to text, parse it, then fall back to the sync path.
 */
export const extractDownloadErrorMessage = async (error: unknown, fallback = 'Something went wrong') => {
  const responseData = (error as { response?: { data?: unknown } })?.response?.data;
  if (responseData instanceof Blob) {
    try {
      const text = await responseData.text();
      const parsed = JSON.parse(text) as Record<string, unknown>;
      const raw = parsed?.message ?? parsed?.error;
      if (Array.isArray(raw)) return raw.join(', ');
      if (raw) return String(raw);
    } catch {
      /* not JSON — fall through */
    }
  }
  return extractErrorMessage(error, fallback);
};
