const path = require('node:path');
const fs = require('fs-extra');
const kleur = require('kleur');
const ui = require('../utils/ui');
const { printCompactHeader } = require('../utils/brand');
const { createTranslator, detectDefaultLanguage } = require('../utils/i18n');
const { slangGenerate } = require('../scaffold/shared/post-build');

const SUPPORTED_LANGS = ['pt', 'en', 'es'];

/**
 * @param {string} projectDir
 * @param {string} lang
 */
async function readNotificationTexts(projectDir, lang) {
  const filePath = path.join(projectDir, 'lib', 'i18n', `${lang}.i18n.json`);
  const data = await fs.readJson(filePath);
  return {
    demoTitle: data.home?.features_page?.notification_demo_title ?? '',
    demoBody: data.home?.features_page?.notification_demo_body ?? '',
    reminderTitle: data.dailyReminder?.title ?? '',
    reminderBody: data.dailyReminder?.body ?? '',
  };
}

/**
 * @param {string} projectDir
 * @param {string[]} langs
 * @param {{ demoTitle: string, demoBody: string, reminderTitle: string, reminderBody: string }} texts
 */
async function writeNotificationTexts(projectDir, langs, texts) {
  for (const lang of langs) {
    const filePath = path.join(projectDir, 'lib', 'i18n', `${lang}.i18n.json`);
    const data = await fs.readJson(filePath);
    if (!data.home) {
      data.home = {};
    }
    if (!data.home.features_page) {
      data.home.features_page = {};
    }
    data.home.features_page.notification_demo_title = texts.demoTitle;
    data.home.features_page.notification_demo_body = texts.demoBody;
    data.dailyReminder = {
      ...(data.dailyReminder || {}),
      title: texts.reminderTitle,
      body: texts.reminderBody,
    };
    await fs.writeJson(filePath, data, { spaces: 4 });
    await fs.appendFile(filePath, '\n');
  }
}

/**
 * @param {string} langOption
 */
function resolveTargetLangs(langOption) {
  const normalized = String(langOption || 'all').trim().toLowerCase();
  if (normalized === 'all') {
    return [...SUPPORTED_LANGS];
  }
  if (!SUPPORTED_LANGS.includes(normalized)) {
    throw new Error(`Invalid --lang "${langOption}". Use: pt, en, es, or all.`);
  }
  return [normalized];
}

async function assertKasyProject(projectDir, t) {
  const kitSetupPath = path.join(projectDir, 'kit_setup.json');
  if (!(await fs.pathExists(kitSetupPath))) {
    throw new Error(t('notifications.error.notKasyProject'));
  }
  const i18nPath = path.join(projectDir, 'lib', 'i18n', 'pt.i18n.json');
  if (!(await fs.pathExists(i18nPath))) {
    throw new Error(t('notifications.error.noI18n'));
  }
}

async function assertLocalNotificationsEnabled(projectDir, t) {
  const featuresPath = path.join(projectDir, 'lib', 'core', 'config', 'features.dart');
  if (!(await fs.pathExists(featuresPath))) {
    throw new Error(t('notifications.error.noFeatures'));
  }
  const content = await fs.readFile(featuresPath, 'utf8');
  if (!/const bool withLocalNotifications\s*=\s*true/.test(content)) {
    throw new Error(t('notifications.error.notEnabled'));
  }
}

/**
 * @param {string} projectDir
 * @param {import('../utils/i18n').Translator} t
 * @param {{ demoTitle?: string, demoBody?: string, reminderTitle?: string, reminderBody?: string }} flags
 */
async function promptForTexts(projectDir, t, flags) {
  const current = await readNotificationTexts(projectDir, 'pt');
  const hasAllFlags =
    flags.demoTitle &&
    flags.demoBody &&
    flags.reminderTitle &&
    flags.reminderBody;

  if (hasAllFlags) {
    return {
      demoTitle: flags.demoTitle.trim(),
      demoBody: flags.demoBody.trim(),
      reminderTitle: flags.reminderTitle.trim(),
      reminderBody: flags.reminderBody.trim(),
    };
  }

  const cancel = () => { ui.cancel(t('notifications.error.cancelled')); process.exit(0); };

  ui.log.step(kleur.bold(t('notifications.prompt.intro')));
  ui.log.message(kleur.dim(t('notifications.prompt.hint')));

  const required = (v) => (String(v || '').trim().length > 0 ? undefined : t('notifications.prompt.required'));

  const demoTitle = await ui.text({
    message: t('notifications.prompt.demoTitle'),
    initialValue: flags.demoTitle || current.demoTitle,
    validate: required,
    onCancel: cancel,
  });
  const demoBody = await ui.text({
    message: t('notifications.prompt.demoBody'),
    initialValue: flags.demoBody || current.demoBody,
    validate: required,
    onCancel: cancel,
  });
  const reminderTitle = await ui.text({
    message: t('notifications.prompt.reminderTitle'),
    initialValue: flags.reminderTitle || current.reminderTitle,
    validate: required,
    onCancel: cancel,
  });
  const reminderBody = await ui.text({
    message: t('notifications.prompt.reminderBody'),
    initialValue: flags.reminderBody || current.reminderBody,
    validate: required,
    onCancel: cancel,
  });

  return {
    demoTitle: String(demoTitle).trim(),
    demoBody: String(demoBody).trim(),
    reminderTitle: String(reminderTitle).trim(),
    reminderBody: String(reminderBody).trim(),
  };
}

/**
 * Configure local notification copy (Home demo + scheduled reminders).
 *
 * @param {string} [directory]
 * @param {{ language?: string, directory?: string, lang?: string, demoTitle?: string, demoBody?: string, reminderTitle?: string, reminderBody?: string }} [options]
 */
async function runNotificationsText(directory, options = {}) {
  const t = createTranslator(options.language || detectDefaultLanguage());
  const projectDir = path.resolve(options.directory || directory || '.');

  await assertKasyProject(projectDir, t);
  await assertLocalNotificationsEnabled(projectDir, t);

  printCompactHeader(t);
  ui.intro(t('notifications.prompt.intro'));

  const targetLangs = resolveTargetLangs(options.lang);
  const texts = await promptForTexts(
    projectDir,
    t,
    {
      demoTitle: options.demoTitle,
      demoBody: options.demoBody,
      reminderTitle: options.reminderTitle,
      reminderBody: options.reminderBody,
    },
  );

  const writeSpinner = ui.spinner();
  writeSpinner.start(t('notifications.writing'));
  await writeNotificationTexts(projectDir, targetLangs, texts);
  writeSpinner.stop(t('notifications.written', { langs: targetLangs.join(', ') }));

  const slangSpinner = ui.spinner();
  slangSpinner.start(t('notifications.slang'));
  const slangResult = await slangGenerate(projectDir);
  if (slangResult.ok) {
    slangSpinner.stop(t('notifications.slangDone'));
  } else {
    slangSpinner.stop(`⚠ ${t('notifications.slangFailed')}`);
    ui.log.message(kleur.dim('dart run slang'));
  }

  const summary = [
    `${t('notifications.summary.demo')}`,
    `  ${kleur.white(texts.demoTitle)}`,
    `  ${kleur.white(texts.demoBody)}`,
    `${t('notifications.summary.reminder')}`,
    `  ${kleur.white(texts.reminderTitle)}`,
    `  ${kleur.white(texts.reminderBody)}`,
  ].join('\n');
  ui.note(summary);

  ui.outro(t('notifications.done'));
}

module.exports = { runNotificationsText, readNotificationTexts, writeNotificationTexts };
