import type { MetadataRoute } from 'next';
import {
  listBrands,
  listCategoryTree,
  searchProducts,
  type CategoryTreeNodeDto,
  type ProductSummaryDto,
} from '@/lib/api';
import { absoluteUrl } from '@/lib/seo';

export const revalidate = 300;

const STATIC_ROUTES = ['/', '/products/search'] as const;

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  const [products, categories, brands] = await Promise.all([
    listActiveProducts(),
    listSafe(() => listCategoryTree()),
    listSafe(() => listBrands()),
  ]);

  const urls = new Set<string>();
  for (const route of STATIC_ROUTES) urls.add(route);
  for (const product of products) urls.add(product.url);
  for (const category of flattenCategories(categories)) urls.add(category.url);
  for (const brand of brands) urls.add(brand.url);

  return [...urls].map((path) => ({
    url: absoluteUrl(path),
    changeFrequency: path === '/' ? 'daily' : 'weekly',
    priority: path === '/' ? 1 : 0.7,
  }));
}

async function listActiveProducts(): Promise<ProductSummaryDto[]> {
  const all: ProductSummaryDto[] = [];
  const limit = 100;
  for (let offset = 0; offset <= 10_000; offset += limit) {
    const page = await searchProducts({ limit, offset }).catch(() => []);
    all.push(...page);
    if (page.length < limit) break;
  }
  return all;
}

async function listSafe<T>(loader: () => Promise<T[]>): Promise<T[]> {
  try {
    return await loader();
  } catch {
    return [];
  }
}

function flattenCategories(categories: readonly CategoryTreeNodeDto[]): CategoryTreeNodeDto[] {
  return categories.flatMap((category) => [category, ...flattenCategories(category.children)]);
}
