// Tailwind v4 emitter — CSS-first configuration.
//
// Tailwind v4 moved away from the JS config file in favour of a CSS-native
// `@theme { ... }` block. This emitter produces that block plus a `@layer
// base` reset wired to the extracted brand. Drop the file at the top of
// your `tailwind.css`, import Tailwind under it, done.
//
// See: https://tailwindcss.com/blog/tailwindcss-v4

import { rgbToHsl } from '../utils.js';

function scaleFromHex(hex, parsed) {
  const { h, s } = parsed.hsl ?? rgbToHsl(parsed.rgb);
  const levels = [
    ['50', 97], ['100', 94], ['200', 86], ['300', 76], ['400', 64],
    ['500', 50], ['600', 40], ['700', 32], ['800', 24], ['900', 16], ['950', 10],
  ];
  return Object.fromEntries(levels.map(([name, l]) => [name, `hsl(${h} ${s}% ${l}%)`]));
}

function kvBlock(prefix, obj) {
  return Object.entries(obj)
    .map(([k, v]) => `  ${prefix}-${k}: ${v};`)
    .join('\n');
}

export function formatTailwindV4(design) {
  const lines = [
    '/* ──────────────────────────────────────────────────────────────',
    '   Tailwind v4 @theme — generated by designlang',
    `   site: ${design.meta?.title || design.meta?.url || '—'}`,
    `   ${new Date().toISOString()}`,
    '   Drop this above `@import "tailwindcss";`.',
    '   ────────────────────────────────────────────────────────────── */',
    '',
    '@import "tailwindcss";',
    '',
    '@theme {',
  ];

  const tokens = {};

  // brand colours with generated scales
  for (const role of ['primary', 'secondary', 'accent']) {
    const c = design.colors?.[role];
    if (!c?.hex) continue;
    const scale = scaleFromHex(c.hex, c);
    for (const [step, val] of Object.entries(scale)) tokens[`color-${role}-${step}`] = val;
    tokens[`color-${role}`] = c.hex;
  }

  // neutrals
  (design.colors?.neutrals || []).slice(0, 10).forEach((n, i) => {
    tokens[`color-neutral-${i * 100 || 50}`] = n.hex;
  });
  if (design.colors?.backgrounds?.[0]) tokens['color-background'] = design.colors.backgrounds[0];
  if (design.colors?.text?.[0]) tokens['color-foreground'] = design.colors.text[0];

  // typography
  const fams = design.typography?.families || [];
  if (fams[0]) tokens['font-sans'] = `"${fams[0].name || fams[0]}", system-ui, sans-serif`;
  const mono = fams.find((f) => /mono|code|courier/i.test(f.name || f));
  if (mono) tokens['font-mono'] = `"${mono.name || mono}", ui-monospace, monospace`;

  // spacing
  (design.spacing?.scale || []).slice(0, 12).forEach((px, i) => {
    tokens[`spacing-${i + 1}`] = `${px}px`;
  });

  // radii
  const radii = design.borders?.radii || [];
  const radiusNames = ['sm', 'md', 'lg', 'xl', '2xl', 'full'];
  radii.slice(0, radiusNames.length).forEach((r, i) => {
    const px = typeof r === 'object' ? r.value : r;
    tokens[`radius-${radiusNames[i]}`] = px >= 999 ? '9999px' : `${px}px`;
  });

  // shadows
  const shadows = design.shadows?.values || design.shadows || [];
  (Array.isArray(shadows) ? shadows : []).slice(0, 4).forEach((sh, i) => {
    const value = typeof sh === 'object' ? sh.value || sh.raw : sh;
    tokens[`shadow-${['sm', 'md', 'lg', 'xl'][i]}`] = String(value);
  });

  // motion
  const durations = design.motion?.durations || [];
  durations.slice(0, 4).forEach((d, i) => {
    tokens[`animate-duration-${['fast', 'base', 'slow', 'slower'][i]}`] = typeof d === 'object' ? d.value : `${d}ms`;
  });

  for (const [k, v] of Object.entries(tokens)) {
    lines.push(`  --${k}: ${v};`);
  }

  lines.push('}', '');
  lines.push('/* Optional base reset that maps body/heading to the extracted tokens. */');
  lines.push('@layer base {');
  lines.push('  html { font-family: var(--font-sans); }');
  if (tokens['color-background']) lines.push('  body { background-color: var(--color-background); color: var(--color-foreground, currentColor); }');
  lines.push('}');
  lines.push('');

  return lines.join('\n');
}
