import path from 'path';
import fsExtra from 'fs-extra';
import { execa } from 'execa';
import { input } from '@inquirer/prompts';
import { isCronJobPresent } from '../../../utils/is-cron-job-present.util';
import { isBinaryInstalled } from '../../../utils/is-binary-installed.util';
import { installBinary } from '../../../utils/install-binary.util';
import { isDependencyCustom } from '../../../types';
import { SetupAlertArgs } from './setup-alert.type';

const { writeFileSync, mkdirSync, existsSync, readFileSync } = fsExtra;

export async function setupAlert({
  alertName,
  dependencies,
  templates,
  cronScriptPath,
  healthdPath,
  healthScriptsPath,
  checkFiles,
}: SetupAlertArgs) {
  try {
    if (!healthdPath || !healthScriptsPath) {
      throw new Error(
        'healthdPath and healthScriptsPath must be set in config before calling setupAlert.',
      );
    }

    const isAlertSetup = async (): Promise<boolean> =>
      checkFiles.every((file) => existsSync(file)) &&
      isCronJobPresent(cronScriptPath);

    for (const dep of dependencies) {
      if (isDependencyCustom(dep)) {
        await dep.install();
      } else if (!(await isBinaryInstalled(dep.binary))) {
        await installBinary(dep.binary, dep.packageName);
      }
    }

    if (await isAlertSetup()) {
      const shouldResetupInput = await input({
        message: `⚠️  ${alertName} alert is already set up. Do you want to re-setup it? (y/N): `,
      });
      const shouldResetup = /^y(es)?$/i.test(shouldResetupInput.trim());

      if (!shouldResetup) {
        console.log('❌ Setup cancelled by user.');
        process.exit(0);
      }
    }

    // Ensure directories exist
    templates.forEach(({ destinationPath }) => {
      mkdirSync(path.dirname(destinationPath), { recursive: true });
    });
    mkdirSync(healthdPath, { recursive: true });

    // Write all templates
    for (const {
      templatePath,
      destinationPath,
      replacements,
      mode,
    } of templates) {
      let content = readFileSync(templatePath, 'utf-8');
      for (const [key, value] of Object.entries(replacements)) {
        content = content.replace(new RegExp(key, 'g'), value);
      }
      writeFileSync(destinationPath, content, mode ? { mode } : undefined);
    }

    console.log(`✅ ${alertName} alert setup completed.`);

    if (!(await isCronJobPresent(cronScriptPath))) {
      const cronJob = `* * * * * ${cronScriptPath}`; // every minute
      await execa(`(crontab -l 2>/dev/null; echo "${cronJob}") | crontab -`, {
        shell: true,
        stdio: 'inherit',
      });
      console.log(`✅ Cron job for ${alertName} setup successfully.`);
    } else {
      console.log(`ℹ️  Cron job for ${alertName} already exists.`);
    }
  } catch (err) {
    console.error(`❌ Failed to set up ${alertName} alert:`, err);
    process.exit(1);
  }
}
