#!/usr/bin/env node
/* eslint-disable no-console */
const fs = require('fs');
const path = require('path');
const vm = require('vm');
require('dotenv').config();

const { closeDatabase, openDatabase } = require('../lib/sqlite');
const { ensurePlantSchema, rebuildPlantsCatalog } = require('../lib/plants');

let ts;
try {
  ts = require('typescript');
} catch (error) {
  console.error('The rebuild script needs the "typescript" package in node_modules.');
  console.error('Install dependencies in the repository root before running this script.');
  process.exit(1);
}

const ROOT_DIR = path.resolve(__dirname, '..', '..');
const BATCH_1_PATH = path.join(ROOT_DIR, 'constants', 'lexiconBatch1.ts');
const BATCH_2_PATH = path.join(ROOT_DIR, 'constants', 'lexiconBatch2.ts');

const resolveTsFilePath = (fromFile, specifier) => {
  if (!specifier.startsWith('.')) return null;
  const fromDirectory = path.dirname(fromFile);
  const absoluteBase = path.resolve(fromDirectory, specifier);
  const candidates = [
    absoluteBase,
    `${absoluteBase}.ts`,
    `${absoluteBase}.tsx`,
    path.join(absoluteBase, 'index.ts'),
  ];
  for (const candidate of candidates) {
    if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) {
      return candidate;
    }
  }
  return null;
};

const loadTsModule = (absolutePath, cache = new Map()) => {
  if (cache.has(absolutePath)) return cache.get(absolutePath);

  const source = fs.readFileSync(absolutePath, 'utf8');
  const transpiled = ts.transpileModule(source, {
    compilerOptions: {
      module: ts.ModuleKind.CommonJS,
      target: ts.ScriptTarget.ES2020,
      esModuleInterop: true,
      jsx: ts.JsxEmit.ReactJSX,
    },
    fileName: absolutePath,
    reportDiagnostics: false,
  }).outputText;

  const module = { exports: {} };
  cache.set(absolutePath, module.exports);

  const localRequire = (specifier) => {
    const resolvedTsPath = resolveTsFilePath(absolutePath, specifier);
    if (resolvedTsPath) {
      return loadTsModule(resolvedTsPath, cache);
    }
    return require(specifier);
  };

  const sandbox = {
    module,
    exports: module.exports,
    require: localRequire,
    __dirname: path.dirname(absolutePath),
    __filename: absolutePath,
    console,
    process,
    Buffer,
    setTimeout,
    clearTimeout,
  };

  vm.runInNewContext(transpiled, sandbox, { filename: absolutePath });
  cache.set(absolutePath, module.exports);
  return module.exports;
};

const loadBatchEntries = () => {
  const batch1Module = loadTsModule(BATCH_1_PATH);
  const batch2Module = loadTsModule(BATCH_2_PATH);

  const batch1Entries = batch1Module.LEXICON_BATCH_1_ENTRIES;
  const batch2Entries = batch2Module.LEXICON_BATCH_2_ENTRIES;

  if (!Array.isArray(batch1Entries) || !Array.isArray(batch2Entries)) {
    throw new Error('Could not load lexicon batch entries from TypeScript constants.');
  }

  return [...batch1Entries, ...batch2Entries];
};

const main = async () => {
  const entries = loadBatchEntries();
  const db = await openDatabase();

  try {
    await ensurePlantSchema(db);
    const summary = await rebuildPlantsCatalog(db, entries, {
      source: 'local_batch_script',
      preserveExistingIds: true,
      enforceUniqueImages: true,
    });

    console.log('Rebuild finished successfully.');
    console.log(JSON.stringify(summary, null, 2));
  } finally {
    await closeDatabase(db);
  }
};

main().catch((error) => {
  console.error('Failed to rebuild plants from local batches.');
  console.error(error instanceof Error ? error.stack || error.message : String(error));
  process.exit(1);
});
