/**
 * packages/extract/src/token-source/serialize.ts — DTCG JSON payload builder.
 * Exports: buildDTCGPayload.
 * Groups parsed tokens by category then nests by dash-separated name segments.
 */

import type { ParsedToken } from './types.js';

function stripCategoryPrefix(rawName: string, category: string) {
  const normalizedName = rawName.toLowerCase();
  const normalizedCategory = category.toLowerCase();

  for (const separator of ['-', '.']) {
    const prefix = `${normalizedCategory}${separator}`;
    if (normalizedName.startsWith(prefix)) {
      return rawName.slice(category.length + separator.length);
    }
  }

  return rawName;
}

export function buildDTCGPayload(tokens: ParsedToken[]) {
  const root: Record<string, unknown> = {};

  for (const token of tokens) {
    const category = token.category;
    const rawName = token.name.replace(/^--|^\$/, '');
    const nameWithoutCategoryPrefix = stripCategoryPrefix(rawName, category);
    const segments = nameWithoutCategoryPrefix.split(/[.-]/).filter(Boolean);
    if (segments.length === 0) segments.push(rawName);

    if (!(category in root)) root[category] = {};
    let node = root[category] as Record<string, unknown>;
    for (let i = 0; i < segments.length - 1; i++) {
      const segment = segments[i];
      if (!(segment in node)) {
        node[segment] = {};
      } else if (typeof node[segment] !== 'object' || node[segment] === null) {
        node[segment] = {};
      }
      node = node[segment] as Record<string, unknown>;
    }

    const leafKey = segments[segments.length - 1];
    const tokenValue = {
      $value: token.value,
      $extensions: {
        fragments: {
          originalName: token.name,
          ...(token.tier !== 'unknown' ? { tier: token.tier } : {}),
        },
      },
    };
    const existing = node[leafKey];
    if (
      existing &&
      typeof existing === 'object' &&
      !('$value' in (existing as Record<string, unknown>))
    ) {
      (existing as Record<string, unknown>).$value = token.value;
      (existing as Record<string, unknown>).$extensions =
        tokenValue.$extensions;
    } else {
      node[leafKey] = tokenValue;
    }
  }

  return JSON.stringify(root, null, 2);
}
