import { PagedResult, PageMeta } from './paging';

/**
 * Normalizes various pagination response formats into a unified PagedResult<T>.
 * Automatically merges any extra statistical fields inside `meta`.
 */
export function normalizePage<T>(raw: any, reqPage: number, perPage: number): PagedResult<T> {
  // 🟩 Case 1 — Spring Data style: { content, totalElements, number, size }
  if (raw && Array.isArray(raw.content) && typeof raw.totalElements === 'number') {
    return {
      data: raw.content as T[],
      meta: {
        page: (raw.number ?? 0) + 1,
        perPage: raw.size ?? perPage,
        total: raw.totalElements,
        ...(raw.meta ?? {}), // merge extra meta if provided
      } as PageMeta,
    };
  }

  // 🟩 Case 2 — API or local mock: { data, meta: { total, ...extra } }
  if (raw && Array.isArray(raw.data) && raw.meta?.total != null) {
    return {
      data: raw.data as T[],
      meta: {
        page: raw.meta.page ?? reqPage,
        perPage: raw.meta.perPage ?? perPage,
        total: raw.meta.total,
        ...raw.meta, // keep any custom stats
      } as PageMeta,
    };
  }

  // 🟩 Case 3 — Generic REST: { items, total | total_count, ...extra }
  if (raw && Array.isArray(raw.items) && (raw.total != null || raw.total_count != null)) {
    const total = raw.total ?? raw.total_count;
    return {
      data: raw.items as T[],
      meta: {
        page: reqPage,
        perPage,
        total,
        ...raw.meta, // optional
      } as PageMeta,
    };
  }

  // 🟩 Case 4 — Direct array (no meta)
  if (Array.isArray(raw)) {
    const start = (reqPage - 1) * perPage;
    const data = (raw as T[]).slice(start, start + perPage);
    return {
      data,
      meta: {
        page: reqPage,
        perPage,
        total: (raw as T[]).length,
      } as PageMeta,
    };
  }

  // 🟩 Fallback — ensure consistency even with minimal info
  const data = Array.isArray(raw?.data) ? (raw.data as T[]) : [];
  const total = typeof raw?.total === 'number' ? raw.total : data.length ?? 0;

  return {
    data,
    meta: {
      page: raw?.meta?.page ?? reqPage,
      perPage: raw?.meta?.perPage ?? perPage,
      total,
      ...raw?.meta, // merge additional stats safely
    } as PageMeta,
  };
}
