/**
 * pres/typography — type scales per theme family.
 *
 * Six named roles every theme defines, so archetypes can ask for
 * "display" or "caption" without thinking about points. The agent
 * never picks font size or font face — only the theme does.
 *
 * Font choices are deliberately conservative: each is either a
 * Windows/Mac default or has a sensible substitution. The user's
 * PowerPoint will best-effort substitute if missing, but starting
 * from defaults means the deck looks the same to ~95% of viewers.
 */

/** Typography scale shape. */
export const ROLES = ['display', 'title', 'subtitle', 'body', 'caption', 'mono'];

/**
 * Build a typography scale from a theme's font pair + base sizes.
 * Lets each theme override only what differs from the family default.
 *
 *   buildScale({
 *     display: 'Georgia',
 *     body:    'Calibri',
 *     mono:    'Consolas',
 *     sizes: { display: 60, title: 36, subtitle: 18, body: 14, caption: 11, mono: 12 },
 *   })
 */
export function buildScale({
  display,
  body,
  mono,
  sizes = {},
  weights = {},
  letterSpacing = {},
  textColor = null,
}) {
  const s = {
    display:  sizes.display  ?? 56,
    title:    sizes.title    ?? 34,
    subtitle: sizes.subtitle ?? 18,
    body:     sizes.body     ?? 14,
    caption:  sizes.caption  ?? 11,
    mono:     sizes.mono     ?? 12,
  };
  return {
    display: {
      fontFace: display,
      fontSize: s.display,
      bold: weights.display === 'bold' || weights.display === undefined,
      charSpacing: letterSpacing.display ?? -1, // tight tracking on huge text
    },
    title: {
      fontFace: display,
      fontSize: s.title,
      bold: weights.title !== 'normal',
      charSpacing: letterSpacing.title ?? 0,
    },
    subtitle: {
      fontFace: body,
      fontSize: s.subtitle,
      bold: weights.subtitle === 'bold',
      charSpacing: letterSpacing.subtitle ?? 0,
    },
    body: {
      fontFace: body,
      fontSize: s.body,
      charSpacing: letterSpacing.body ?? 0,
    },
    caption: {
      fontFace: body,
      fontSize: s.caption,
      charSpacing: letterSpacing.caption ?? 0.5, // a bit looser for small text
    },
    mono: {
      fontFace: mono,
      fontSize: s.mono,
    },
    /** Big-stat numeric override that data-heavy themes can opt into. */
    stat: {
      fontFace: display,
      fontSize: sizes.stat ?? 96,
      bold: true,
      charSpacing: -2,
    },
    /** Tiny pill / eyebrow label sitting above titles. */
    eyebrow: {
      fontFace: body,
      fontSize: sizes.eyebrow ?? 10,
      bold: true,
      charSpacing: 2,
    },
    /** Optional default text colour the archetype falls back to when
     *  the palette doesn't dictate. */
    defaultColor: textColor,
  };
}

/**
 * Merge a role's base style with overrides (colour, alignment, etc.)
 * the archetype passes through. Used in every archetype so the agent
 * never sets font/size directly.
 */
export function textStyle(scale, role, overrides = {}) {
  const base = scale[role] || scale.body;
  return {
    fontFace: base.fontFace,
    fontSize: base.fontSize,
    bold: base.bold,
    italic: base.italic,
    charSpacing: base.charSpacing,
    ...overrides,
  };
}
