#!/usr/bin/env node
/**
 * Merges lib/l10n/app_{en,te}.arb with app_{en,te}_more.arb (in-memory) and
 * writes lib/l10n/app_localizations.dart, app_localizations_en.dart, app_localizations_te.dart.
 *
 * Run from package root: node tool/sync_l10n.mjs
 */
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const root = path.join(__dirname, "..");
const l10nDir = path.join(root, "lib", "l10n");

function loadArb(name) {
  const p = path.join(l10nDir, name);
  return JSON.parse(fs.readFileSync(p, "utf8"));
}

function merge(base, extra) {
  return { ...base, ...extra };
}

function messageKeys(arb) {
  return Object.keys(arb).filter((k) => !k.startsWith("@") && k !== "@@locale");
}

function placeholdersFor(arb, key) {
  const meta = arb[`@${key}`];
  if (!meta || !meta.placeholders) return null;
  return Object.keys(meta.placeholders);
}

function dartEscapeSingle(s) {
  return s
    .replace(/\\/g, "\\\\")
    .replace(/\r\n/g, "\n")
    .replace(/\n/g, "\\n")
    .replace(/'/g, "\\'");
}

/** Build Dart string literal expr from ICU-ish template (e.g. "Hi, {name}!"). */
function dartReturnExpr(template, params) {
  let d = template;
  for (const p of params) {
    d = d.split(`{${p}}`).join(`$${p}`);
  }
  return `'${dartEscapeSingle(d)}'`;
}

function writeLocalizations(en, te) {
  const keys = [...new Set([...messageKeys(en), ...messageKeys(te)])].sort();

  const abstractDecls = [];
  const enImpl = [];
  const teImpl = [];

  for (const key of keys) {
    const ph = placeholdersFor(en, key) ?? placeholdersFor(te, key);
    if (ph && ph.length) {
      const args = ph.map((p) => `String ${p}`).join(", ");
      abstractDecls.push(`  String ${key}(${args});`);
      const tplEn = en[key];
      const tplTe = te[key] ?? tplEn;
      enImpl.push(`  @override\n  String ${key}(${args}) {\n    return ${dartReturnExpr(tplEn, ph)};\n  }`);
      teImpl.push(`  @override\n  String ${key}(${args}) {\n    return ${dartReturnExpr(tplTe, ph)};\n  }`);
    } else {
      abstractDecls.push(`  String get ${key};`);
      const vEn = en[key] ?? "";
      const vTe = te[key] ?? vEn;
      enImpl.push(`  @override\n  String get ${key} => '${dartEscapeSingle(vEn)}';`);
      teImpl.push(`  @override\n  String get ${key} => '${dartEscapeSingle(vTe)}';`);
    }
  }

  const header = `// GENERATED FILE — do not edit by hand.
// Source: lib/l10n/app_en.arb + app_en_more.arb (merged). Regenerate: node tool/sync_l10n.mjs

`;

  const main = `${header}import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'app_localizations_en.dart';
import 'app_localizations_te.dart';

abstract class AppLocalizations {
  AppLocalizations(String locale) : localeName = locale;

  final String localeName;

  static AppLocalizations? of(BuildContext context) {
    return Localizations.of<AppLocalizations>(context, AppLocalizations);
  }

  static const LocalizationsDelegate<AppLocalizations> delegate = _AppLocalizationsDelegate();

  static const List<LocalizationsDelegate<dynamic>> localizationsDelegates =
      <LocalizationsDelegate<dynamic>>[
    delegate,
    GlobalMaterialLocalizations.delegate,
    GlobalCupertinoLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
  ];

  static const List<Locale> supportedLocales = <Locale>[
    Locale('en'),
    Locale('te'),
  ];

${abstractDecls.join("\n\n")}
}

class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
  const _AppLocalizationsDelegate();

  @override
  Future<AppLocalizations> load(Locale locale) {
    return SynchronousFuture<AppLocalizations>(lookupAppLocalizations(locale));
  }

  @override
  bool isSupported(Locale locale) =>
      <String>['en', 'te'].contains(locale.languageCode);

  @override
  bool shouldReload(_AppLocalizationsDelegate old) => false;
}

AppLocalizations lookupAppLocalizations(Locale locale) {
  switch (locale.languageCode) {
    case 'en':
      return AppLocalizationsEn();
    case 'te':
      return AppLocalizationsTe();
  }
  throw FlutterError(
    'AppLocalizations.delegate failed to load unsupported locale "\$locale".',
  );
}
`;

  const enFile = `${header}import 'app_localizations.dart';

class AppLocalizationsEn extends AppLocalizations {
  AppLocalizationsEn([String locale = 'en']) : super(locale);

${enImpl.join("\n\n")}
}
`;

  const teFile = `${header}import 'app_localizations.dart';

class AppLocalizationsTe extends AppLocalizations {
  AppLocalizationsTe([String locale = 'te']) : super(locale);

${teImpl.join("\n\n")}
}
`;

  fs.writeFileSync(path.join(l10nDir, "app_localizations.dart"), main);
  fs.writeFileSync(path.join(l10nDir, "app_localizations_en.dart"), enFile);
  fs.writeFileSync(path.join(l10nDir, "app_localizations_te.dart"), teFile);
}

const baseEn = loadArb("app_en.arb");
const baseTe = loadArb("app_te.arb");
const moreEn = loadArb("app_en_more.arb");
const moreTe = loadArb("app_te_more.arb");

const en = merge(baseEn, moreEn);
const te = merge(baseTe, moreTe);

writeLocalizations(en, te);
console.log("Wrote app_localizations*.dart from merged ARBs.");
