// Reads shared/fabledsword.tokens.json and emits lib/theme/tokens.dart.
// Run via `dart run tool/gen_tokens.dart`. The generated file is
// committed (CI validates it matches the JSON to catch drift).
//
// Emits three flat classes mirroring the source JSON:
//   - FabledSwordDarkTokens (surface colors for dark mode)
//   - FabledSwordLightTokens (surface colors for light mode)
//   - FabledSwordFlatTokens (colors that don't change between modes,
//     plus radii + font families)
//
// Plus a back-compat FabledSwordTokens alias that re-exports the dark
// surface colors + flat — kept so any code that still reads
// FabledSwordTokens.obsidian (etc.) continues to work during the
// migration. Safe to delete once theme_extension.dart switches over.
import 'dart:convert';
import 'dart:io';

void main() {
  final jsonFile = File('shared/fabledsword.tokens.json');
  final tokens = jsonDecode(jsonFile.readAsStringSync()) as Map<String, dynamic>;

  final colorsRoot = (tokens['colors'] as Map).cast<String, dynamic>();
  final dark = (colorsRoot['dark'] as Map).cast<String, String>();
  final light = (colorsRoot['light'] as Map).cast<String, String>();
  final flat = (colorsRoot['flat'] as Map).cast<String, String>();
  final radii = (tokens['radii'] as Map).cast<String, String>();
  final fonts = (tokens['fonts'] as Map).cast<String, String>();

  final out = StringBuffer()
    ..writeln('// GENERATED — do not edit. Source: shared/fabledsword.tokens.json')
    ..writeln('// Run `dart run tool/gen_tokens.dart` to regenerate.')
    ..writeln("import 'package:flutter/material.dart';")
    ..writeln();

  void writeColorClass(String className, Map<String, String> colors) {
    out.writeln('class $className {');
    colors.forEach((name, hex) {
      final value = hex.replaceFirst('#', '0xFF');
      out.writeln('  static const Color ${_camel(name)} = Color($value);');
    });
    out.writeln('}');
    out.writeln();
  }

  writeColorClass('FabledSwordDarkTokens', dark);
  writeColorClass('FabledSwordLightTokens', light);

  out.writeln('class FabledSwordFlatTokens {');
  flat.forEach((name, hex) {
    final value = hex.replaceFirst('#', '0xFF');
    out.writeln('  static const Color ${_camel(name)} = Color($value);');
  });
  radii.forEach((name, px) {
    final v = px.replaceAll('px', '');
    out.writeln('  static const double radius${_pascal(name)} = $v;');
  });
  fonts.forEach((name, family) {
    out.writeln('  static const String font${_pascal(name)} = ${jsonEncode(family)};');
  });
  out.writeln('}');
  out.writeln();

  // Back-compat alias: dark surface colors + flat. Lets existing
  // call sites that read FabledSwordTokens.obsidian etc. keep working
  // until they're migrated to the explicit dark/light/flat classes.
  out.writeln('/// Back-compat alias — dark surface tokens + flat. Prefer the explicit');
  out.writeln('/// FabledSwordDarkTokens / FabledSwordLightTokens / FabledSwordFlatTokens.');
  out.writeln('class FabledSwordTokens {');
  dark.forEach((name, hex) {
    final value = hex.replaceFirst('#', '0xFF');
    out.writeln('  static const Color ${_camel(name)} = Color($value);');
  });
  flat.forEach((name, hex) {
    final value = hex.replaceFirst('#', '0xFF');
    out.writeln('  static const Color ${_camel(name)} = Color($value);');
  });
  radii.forEach((name, px) {
    final v = px.replaceAll('px', '');
    out.writeln('  static const double radius${_pascal(name)} = $v;');
  });
  fonts.forEach((name, family) {
    out.writeln('  static const String font${_pascal(name)} = ${jsonEncode(family)};');
  });
  out.writeln('}');

  File('lib/theme/tokens.dart').writeAsStringSync(out.toString());
  stdout.writeln('wrote lib/theme/tokens.dart');
}

// Hyphens become camelCase boundaries: on-action → onAction.
String _camel(String s) {
  final parts = s.split('-');
  return parts.first +
      parts.skip(1).map((p) => p[0].toUpperCase() + p.substring(1)).join();
}

String _pascal(String s) => s[0].toUpperCase() + s.substring(1);
