const fs = require('fs');
const path = require('path');

const localesDir = path.join(__dirname, '..', 'extension', 'locales');
const enPath = path.join(localesDir, 'en.json');

if (!fs.existsSync(enPath)) {
  console.error('CRITICAL: en.json is missing!');
  process.exit(1);
}

let hasError = false;

// Verify SUPPORTED_LANGUAGES in extension/i18n.js matches JSON files
const i18nPath = path.join(__dirname, '..', 'extension', 'i18n.js');
try {
  if (fs.existsSync(i18nPath)) {
    const i18nContent = fs.readFileSync(i18nPath, 'utf8');
    const langMatch = i18nContent.match(/export const SUPPORTED_LANGUAGES = \[(.*?)\];/);
    if (!langMatch) {
      hasError = true;
      console.error('❌ Could not parse SUPPORTED_LANGUAGES from extension/i18n.js');
    } else {
      const supportedLangs = langMatch[1].split(',').map(s => s.trim().replace(/['"]/g, ''));
      const fileLangs = fs.readdirSync(localesDir)
        .filter(file => file.endsWith('.json'))
        .map(file => file.replace('.json', ''));

      for (const lang of fileLangs) {
        if (!supportedLangs.includes(lang)) {
          hasError = true;
          console.error(`❌ ${lang}.json exists in extension/locales but is missing from SUPPORTED_LANGUAGES in extension/i18n.js`);
        }
      }
      for (const lang of supportedLangs) {
        if (!fileLangs.includes(lang)) {
          hasError = true;
          console.error(`❌ ${lang} is in SUPPORTED_LANGUAGES in extension/i18n.js but ${lang}.json is missing from extension/locales`);
        }
      }
    }
  }
} catch (err) {
  hasError = true;
  console.error('❌ Failed to verify SUPPORTED_LANGUAGES synchronization:', err.message);
}

const enDict = JSON.parse(fs.readFileSync(enPath, 'utf8'));
const enKeys = Object.keys(enDict);

const localeFiles = fs.readdirSync(localesDir).filter(file => file.endsWith('.json'));

console.log(`Auditing i18n locales using ${enKeys.length} baseline keys from en.json...\n`);

for (const file of localeFiles) {
  const filePath = path.join(localesDir, file);
  try {
    const raw = fs.readFileSync(filePath, 'utf8');

    // Check for duplicate keys in raw JSON before parsing
    const keyRe = /"(\w+)"\s*:/g;
    const seenKeys = {};
    let dupes = [];
    let m;
    while ((m = keyRe.exec(raw)) !== null) {
      if (seenKeys[m[1]]) {
        dupes.push(m[1]);
      }
      seenKeys[m[1]] = true;
    }
    if (dupes.length > 0) {
      hasError = true;
      console.error(`❌ ${file} has duplicate keys: ${[...new Set(dupes)].join(', ')}`);
      continue;
    }

    const dict = JSON.parse(raw);
    const keys = Object.keys(dict);

    const missingKeys = enKeys.filter(k => !keys.includes(k));
    const extraKeys = keys.filter(k => !enKeys.includes(k));
    const emptyKeys = keys.filter(k => typeof dict[k] === 'string' && dict[k].trim() === '');
    const placeholderKeys = keys.filter(k => {
      if (typeof dict[k] !== 'string') return false;
      const val = dict[k];
      const lower = val.toLowerCase();
      return (
        lower.includes('placeholder') ||
        lower.includes('todo:') ||
        lower.includes('tbd:') ||
        /\bTODO\b/.test(val) ||
        /\bTBD\b/.test(val)
      );
    });

    if (missingKeys.length > 0 || extraKeys.length > 0 || emptyKeys.length > 0 || placeholderKeys.length > 0) {
      hasError = true;
      console.error(`❌ ${file} has inconsistencies:`);
      if (missingKeys.length > 0) {
        console.error(`  Missing keys (${missingKeys.length}):`, missingKeys);
      }
      if (extraKeys.length > 0) {
        console.error(`  Extra keys (${extraKeys.length}):`, extraKeys);
      }
      if (emptyKeys.length > 0) {
        console.error(`  Empty translation values (${emptyKeys.length}):`, emptyKeys);
      }
      if (placeholderKeys.length > 0) {
        console.error(`  Placeholder/TODO values (${placeholderKeys.length}):`, placeholderKeys);
      }
    } else {
      console.log(`✓ ${file} is fully consistent (matches all keys).`);
    }
  } catch (err) {
    hasError = true;
    console.error(`❌ Failed to parse ${file}:`, err.message);
  }
}

// ──────────────────────────────────────
// Verify Chrome _locales/*/messages.json
// ──────────────────────────────────────
console.log('\nVerifying Chrome _locales/messages.json structure...\n');

const chromeLocalesDir = path.join(__dirname, '..', 'extension', '_locales');

// Map custom locale codes to Chrome's underscore format
const chromeLocaleMap = {
  'en': 'en', 'de': 'de', 'fr': 'fr', 'es': 'es', 'it': 'it',
  'ja': 'ja', 'ko': 'ko', 'nl': 'nl', 'pl': 'pl',
  'pt-BR': 'pt_BR', 'pt': 'pt_PT', 'ru': 'ru', 'tr': 'tr',
  'zh': 'zh_CN', 'uk': 'uk'
};

// Read SUPPORTED_LANGUAGES from i18n.js
const i18nContent = fs.readFileSync(i18nPath, 'utf8');
const langMatch = i18nContent.match(/export const SUPPORTED_LANGUAGES = \[(.*?)\];/);
const supportedLangs = langMatch
  ? langMatch[1].split(',').map(s => s.trim().replace(/['"]/g, ''))
  : [];

// Verify default_locale in manifest.base.json
const manifestPath = path.join(__dirname, '..', 'extension', 'manifest.base.json');
try {
  const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
  if (!manifest.default_locale) {
    hasError = true;
    console.error('❌ manifest.base.json is missing "default_locale"');
  } else if (manifest.default_locale !== 'en') {
    hasError = true;
    console.error(`❌ manifest.base.json default_locale is "${manifest.default_locale}", expected "en"`);
  } else {
    console.log('✓ manifest.base.json has default_locale: "en"');
  }
} catch (err) {
  hasError = true;
  console.error('❌ Failed to read manifest.base.json:', err.message);
}

// Verify _locales structure for each supported language
const expectedKeys = ['appName', 'appDesc'];
for (const lang of supportedLangs) {
  const chromeLocale = chromeLocaleMap[lang];
  if (!chromeLocale) {
    hasError = true;
    console.error(`❌ No Chrome locale mapping for "${lang}" in chromeLocaleMap`);
    continue;
  }

  const msgPath = path.join(chromeLocalesDir, chromeLocale, 'messages.json');

  if (!fs.existsSync(msgPath)) {
    hasError = true;
    console.error(`❌ Missing _locales/${chromeLocale}/messages.json for language "${lang}"`);
    continue;
  }

  try {
    const raw = fs.readFileSync(msgPath, 'utf8');
    const messages = JSON.parse(raw);
    const keys = Object.keys(messages);

    // Detect duplicate top-level keys via regex (JSON.parse silently keeps last value)
    const topKeyRe = /^\s{2}"(\w+)"\s*:/gm;
    const topSeen = {};
    let topDupes = [];
    let tm;
    while ((tm = topKeyRe.exec(raw)) !== null) {
      if (topSeen[tm[1]]) topDupes.push(tm[1]);
      topSeen[tm[1]] = true;
    }
    if (topDupes.length > 0) {
      hasError = true;
      console.error(`❌ _locales/${chromeLocale}/messages.json has duplicate keys: ${[...new Set(topDupes)].join(', ')}`);
      continue;
    }

    // Validate each entry has a "message" field
    for (const key of keys) {
      if (!messages[key].message || typeof messages[key].message !== 'string') {
        hasError = true;
        console.error(`❌ _locales/${chromeLocale}/messages.json: "${key}" is missing a valid "message" field`);
      }
    }

    // Check for missing or extra keys vs expected baseline
    const missing = expectedKeys.filter(k => !keys.includes(k));
    const extra = keys.filter(k => !expectedKeys.includes(k));
    if (missing.length > 0) {
      hasError = true;
      console.error(`❌ _locales/${chromeLocale}/messages.json missing keys: ${missing.join(', ')}`);
    }
    if (extra.length > 0) {
      console.log(`ℹ️  _locales/${chromeLocale}/messages.json has extra keys (ok): ${extra.join(', ')}`);
    }
    if (missing.length === 0) {
      console.log(`✓ _locales/${chromeLocale}/messages.json is valid and complete`);
    }
  } catch (err) {
    hasError = true;
    console.error(`❌ Failed to parse _locales/${chromeLocale}/messages.json:`, err.message);
  }
}

// Detect orphan _locales directories (no matching supported language)
if (fs.existsSync(chromeLocalesDir)) {
  const chromeCodes = supportedLangs.map(l => chromeLocaleMap[l]).filter(Boolean);
  const dirs = fs.readdirSync(chromeLocalesDir);
  for (const dir of dirs) {
    const dirPath = path.join(chromeLocalesDir, dir);
    if (fs.statSync(dirPath).isDirectory() && dir !== '.git' && !chromeCodes.includes(dir)) {
      hasError = true;
      console.error(`❌ Orphan _locales/${dir}/ directory exists but no matching language in SUPPORTED_LANGUAGES`);
    }
  }
}

console.log('');
if (hasError) {
  console.error('❌ Locale consistency check failed! Please fix the errors listed above.');
  process.exit(1);
} else {
  console.log('🎉 All locale files (locales/ and _locales/) are valid and consistent!');
  process.exit(0);
}
