<?php

namespace App\Controllers;

use Core\Request;
use Core\Redirect;
use Core\DB;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use Exception;
use ZipArchive;
use mysqli;

include realpath(dirname(__DIR__) . '/include/function.php');
include_once realpath(dirname(__DIR__) . '/../config.php');
/**
 * Class Account
 * Handles account creation and management processes.
 */
class Account
{
  private $rollbackActions = [];
  private $createdResources = [
    'database' => false,
    'folder' => false,
    'apache_config' => false,
    'cloudflare_record' => false,
    'cron_jobs' => false,
    'isp_account' => false
  ];
  private $accountData = [];
  private $conn;

  public function __construct()
  {
    $db = new DB();
    $this->conn = $db->getConnection();
  }

  public function createAccountProcess()
  {
    try {
      // Validate and prepare data
      $this->validateRequest();
      $this->accountData = $this->sanitizeInputs();
      $this->validateAccountUniqueness();

      // Process subscription
      $subscriptionData = $this->getSubscriptionData();
      $this->accountData = array_merge($this->accountData, $subscriptionData);

      // Create account and environment
      $this->createIspAccount();
      $this->setupApplicationEnvironment();
      $this->configureServer();

      // Finalize setup
      $this->createUserAndLicense();
      $this->notifyAdmin();
      $this->cleanup();

      Redirect::redirectSuccess('accounts', "ISP account created successfully!");
    } catch (Exception $e) {
      $this->rollback();
      error_log("Account creation failed: " . $e->getMessage());
      send_telegram_notification("Account creation failed: " . $e->getMessage(), BOT_TOKEN, CHAT_ID);
      Redirect::redirectError('create_account', $e->getMessage());
    }
  }

  private function validateRequest()
  {
    if (!isset($_POST['create_account'])) {
      throw new Exception("Invalid request.");
    }
  }

  private function sanitizeInputs()
  {
    return [
      'isp_name' => trim(Request::getPost('isp_name', 'string')),
      'email' => trim(Request::getPost('email', 'string')),
      'phone' => trim(Request::getPost('phone', 'string')),
      'subdomain' => str_replace(' ', '', strtolower(trim(Request::getPost('subdomain', 'string')))),
      'username' => str_replace(' ', '', strtolower(trim(Request::getPost('username', 'string')))),
      'subscription_plan_id' => intval(Request::getPost('subscription_plan_id', 'int')),
      'password' => str_pad(mt_rand(0, 9999), 4, '0', STR_PAD_LEFT),
      'main_domain' => defined('MAIN_DOMAIN') ? MAIN_DOMAIN : '',
      'server_ip' => defined('SERVER_IP') ? SERVER_IP : '',
      'cloudflare_token' => defined('CLOUDFLARE_TOKEN') ? CLOUDFLARE_TOKEN : '',
      'cloudflare_zone_id' => defined('CLOUDFLARE_ZONE_ID') ? CLOUDFLARE_ZONE_ID : '',
      'mysql_host' => defined('MYSQL_HOST') ? MYSQL_HOST : '',
      'mysql_user' => defined('MYSQL_USER') ? MYSQL_USER : '',
      'mysql_password' => defined('MYSQL_PASSWORD') ? MYSQL_PASSWORD : '',
      'mysql_database' => defined('MYSQL_DATABASE') ? MYSQL_DATABASE : ''
    ];
  }

  private function validateAccountUniqueness()
  {
    $this->checkFieldUniqueness('subdomain', $this->accountData['subdomain'], 'Subdomain already exists!');
    $this->checkFieldUniqueness('username', $this->accountData['username'], 'Username already exists!');
    $this->checkFieldUniqueness('email', $this->accountData['email'], 'Email already exists!');
  }
  private function checkFieldUniqueness($field, $value, $errorMessage)
  {
    $stmt = $this->conn->prepare("SELECT COUNT(*) FROM isp_accounts WHERE $field = ?");
    $stmt->bind_param("s", $value);
    $stmt->execute();
    $count = 0;
    $stmt->bind_result($count);
    $stmt->fetch();
    $stmt->close();

    if ($count > 0) {
      throw new Exception($errorMessage);
    }
  }

  private function getSubscriptionData()
  {
    $data = [
      'subscription_start' => date('Y-m-d'),
      'subscription_end' => date('Y-m-d', strtotime('+30 days')),
      'duration' => 30
    ];

    if ($this->accountData['subscription_plan_id'] > 0) {
      $stmt = $this->conn->prepare("SELECT duration_days FROM subscription_plans WHERE id = ?");
      $stmt->bind_param("i", $this->accountData['subscription_plan_id']);
      $stmt->execute();
      $result = $stmt->get_result();

      if ($result->num_rows > 0) {
        $plan = $result->fetch_assoc();
        $data['duration'] = $plan['duration_days'];
        $data['subscription_end'] = date('Y-m-d', strtotime("+{$plan['duration_days']} days"));
      }
      $stmt->close();
    }

    return $data;
  }

  private function createIspAccount()
  {
    $hashedPassword = password_hash($this->accountData['password'], PASSWORD_DEFAULT);
    $stmt =  $this->conn->prepare("
            INSERT INTO isp_accounts 
            (username, email, company_name, subdomain, phone, subscription_plan_id, 
             subscription_start, subscription_end, status, created_at) 
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'active', NOW())
        ");

    $stmt->bind_param(
      "ssssssis",
      $this->accountData['username'],
      $this->accountData['email'],
      $this->accountData['isp_name'],
      $this->accountData['subdomain'],
      $this->accountData['phone'],
      $this->accountData['subscription_plan_id'],
      $this->accountData['subscription_start'],
      $this->accountData['subscription_end']
    );

    if (!$stmt->execute()) {
      throw new Exception("Failed to create ISP account: " . $stmt->error);
    }

    $this->accountData['isp_account_id'] =  $this->conn->insert_id;
    $this->createdResources['isp_account'] = true;
    $stmt->close();

    $this->rollbackActions[] = function () {
      $stmt =  $this->conn->prepare("DELETE FROM isp_accounts WHERE id = ?");
      $stmt->bind_param("i", $this->accountData['isp_account_id']);
      $stmt->execute();
      $stmt->close();
    };
  }

  private function setupApplicationEnvironment()
  {
    $this->verifyRequiredFiles();
    $this->createApplicationFolder();
    $this->createDatabase();
    $this->updateDatabaseConfig();
    $this->createConfigFile();
  }

  private function verifyRequiredFiles()
  {
    $system_zip_file = realpath(dirname(__DIR__) . '/../' . SYSTEM_ZIP_FILE_NAME);
    $database_file = realpath(dirname(__DIR__) . '/../' . DATABASE_FILE);

    if (!file_exists($system_zip_file)) {
      throw new Exception("System zip file not found: $system_zip_file");
    }

    if (!file_exists($database_file)) {
      throw new Exception("Database file not found: $database_file");
    }

    if (!class_exists('ZipArchive')) {
      throw new Exception("ZipArchive class not found. Please install the PHP Zip extension.");
    }
  }

  private function createApplicationFolder()
  {
    $new_folder = "/var/www/html/{$this->accountData['username']}";

    if (!file_exists($new_folder)) {
      if (!mkdir($new_folder, 0755, true)) {
        throw new Exception("Failed to create directory: $new_folder");
      }
      $this->createdResources['folder'] = true;

      $this->extractSystemFiles($new_folder);
    }
  }

  private function extractSystemFiles($new_folder)
  {
    $system_zip_file = realpath(dirname(__DIR__) . '/../' . SYSTEM_ZIP_FILE_NAME);
    $zip = new ZipArchive();

    if ($zip->open($system_zip_file) !== TRUE) {
      throw new Exception("Failed to open zip file: $system_zip_file");
    }

    $tempExtractPath = $new_folder . '_temp';
    if (!is_dir($tempExtractPath)) {
      mkdir($tempExtractPath, 0777, true);
    }

    if (!$zip->extractTo($tempExtractPath)) {
      $zip->close();
      throw new Exception("Failed to extract zip file to: $tempExtractPath");
    }
    $zip->close();

    $subfolders = array_diff(scandir($tempExtractPath), ['.', '..']);
    $extractPath = count($subfolders) === 1 && is_dir("$tempExtractPath/" . reset($subfolders))
      ? "$tempExtractPath/" . reset($subfolders)
      : $tempExtractPath;

    $this->moveFiles($extractPath, $new_folder);
    $this->removeDirectory($tempExtractPath);
  }

  private function moveFiles($source, $destination)
  {
    $files = new RecursiveIteratorIterator(
      new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS),
      RecursiveIteratorIterator::SELF_FIRST
    );

    foreach ($files as $file) {
      $target = str_replace($source, $destination, $file);

      if ($file->isDir()) {
        if (!is_dir($target)) {
          mkdir($target, 0777, true);
        }
      } else {
        rename($file, $target);
      }
    }
  }

  private function removeDirectory($dir)
  {
    $files = array_diff(scandir($dir), ['.', '..']);
    foreach ($files as $file) {
      $path = "$dir/$file";
      is_dir($path) ? $this->removeDirectory($path) : unlink($path);
    }
    rmdir($dir);
  }

  private function createDatabase()
  {
    $conn = new mysqli(
      $this->accountData['mysql_host'],
      $this->accountData['mysql_user'],
      $this->accountData['mysql_password']
    );

    if ($conn->connect_error) {
      throw new Exception("Failed to connect to MySQL: " . $conn->connect_error);
    }

    if (!$conn->query("CREATE DATABASE IF NOT EXISTS `{$this->accountData['username']}`")) {
      $conn->close();
      throw new Exception("Failed to create database: " . $conn->error);
    }
    $this->createdResources['database'] = true;

    $result = $conn->query("SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '{$this->accountData['username']}'");
    $row = $result->fetch_row();
    if ($row[0] == 0) {
      $database_file = realpath(dirname(__DIR__) . '/../' . DATABASE_FILE);
      $importCmd = "mysql -u{$this->accountData['mysql_user']} -p{$this->accountData['mysql_password']} {$this->accountData['username']} < $database_file 2>&1";
      $importOutput = shell_exec($importCmd);

      if (strpos($importOutput, 'ERROR') !== false) {
        $conn->close();
        throw new Exception("Failed to import database: $importOutput");
      }
    }

    $conn->close();
  }

  private function updateDatabaseConfig()
  {
    $conn = new mysqli(
      $this->accountData['mysql_host'],
      $this->accountData['mysql_user'],
      $this->accountData['mysql_password'],
      $this->accountData['username']
    );

    if ($conn->connect_error) {
      throw new Exception("Failed to connect to database: " . $conn->connect_error);
    }

    $this->updateConfigValue($conn, 'CompanyName', $this->accountData['isp_name']);
    $this->updateConfigValue($conn, 'phone', $this->accountData['phone']);

    $conn->close();
  }

  private function updateConfigValue($conn, $setting, $value)
  {
    $stmt = $conn->prepare("UPDATE tbl_appconfig SET value = ? WHERE setting = ?");
    if (!$stmt) {
      throw new Exception("Prepare failed for $setting: " . $conn->error);
    }

    $stmt->bind_param("ss", $value, $setting);
    if (!$stmt->execute()) {
      $stmt->close();
      throw new Exception("Failed to update $setting: " . $stmt->error);
    }
    $stmt->close();
  }

  private function createConfigFile()
  {
    $config_file = "/var/www/html/{$this->accountData['username']}/config.php";
    $config_content = <<<EOL
<?php
// Auto-detect protocol for Cloudflare
\$protocol = (!empty(\$_SERVER['HTTPS']) && \$_SERVER['HTTPS'] !== 'off' || 
             (isset(\$_SERVER['SERVER_PORT']) && \$_SERVER['SERVER_PORT'] == 443) ||
             (isset(\$_SERVER['HTTP_X_FORWARDED_PROTO']) && \$_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https')) ? "https://" : "http://";

\$host = isset(\$_SERVER['HTTP_HOST']) ? \$_SERVER['HTTP_HOST'] : '{$this->accountData['subdomain']}.{$this->accountData['main_domain']}';
\$baseDir = rtrim(dirname(\$_SERVER['SCRIPT_NAME']), '/\\\\');
define('APP_URL', \$protocol . \$host . \$baseDir);

\$_app_stage = 'Live';

// Database settings
\$db_host = '{$this->accountData['mysql_host']}';
\$db_user = '{$this->accountData['mysql_user']}';
\$db_pass = '{$this->accountData['mysql_password']}';
\$db_name = '{$this->accountData['username']}';

// Hide errors in production
if(\$_app_stage != 'Live'){
    error_reporting(E_ALL);
    ini_set('display_errors', 1);
} else {
    error_reporting(0);
    ini_set('display_errors', 0);
}
?>
EOL;

    if (file_put_contents($config_file, $config_content) === false) {
      throw new Exception("Failed to create config file: $config_file");
    }
  }

  private function configureServer()
  {
    $this->configureApache();
    $this->configureCloudflare();
    //$this->giveSubdomainSSLPermission();
    $this->configureCronJobs();
  }

  private function configureApache()
  {
    $server_software = strtolower($_SERVER['SERVER_SOFTWARE'] ?? php_uname());
    if (strpos($server_software, 'apache') !== false) {
      $apache_conf_file = "/etc/apache2/sites-available/{$this->accountData['username']}.conf";
      $new_folder = "/var/www/html/{$this->accountData['username']}";

      if (!file_exists($apache_conf_file)) {
        $apache_conf = <<<EOL
<VirtualHost *:80 *:443>
    ServerName {$this->accountData['subdomain']}.{$this->accountData['main_domain']}
    DocumentRoot $new_folder
    
    # Trust Cloudflare
    SetEnvIf X-Forwarded-Proto "https" HTTPS=on
    
    <Directory $new_folder>
        AllowOverride All
        Require all granted
    </Directory>
    
    # Protect system folder
    <Directory $new_folder/system>
        Require all denied
    </Directory>
    
    <Directory $new_folder/system/uploads>
        Require all granted
        <FilesMatch "\.php$">
            Require all denied
        </FilesMatch>
    </Directory>
    
    ErrorLog \${APACHE_LOG_DIR}/{$this->accountData['subdomain']}_error.log
    CustomLog \${APACHE_LOG_DIR}/{$this->accountData['subdomain']}_access.log combined
</VirtualHost>
EOL;

        if (file_put_contents($apache_conf_file, $apache_conf) === false) {
          throw new Exception("Failed to create Apache configuration file: $apache_conf_file");
        }
        $this->createdResources['apache_config'] = true;
      }

      exec("sudo a2ensite {$this->accountData['username']}.conf && sudo systemctl reload apache2", $output, $return_var);
      if ($return_var !== 0) {
        throw new Exception("Failed to enable the new site or reload Apache: " . implode("\n", $output));
      }
    }
  }

  private function giveSubdomainSSLPermission()
  {
    $domain = "{$this->accountData['subdomain']}.{$this->accountData['main_domain']}";
    exec("sudo certbot --apache -d $domain", $output, $return_var);
    if ($return_var !== 0) {
      throw new Exception("Failed to obtain SSL certificate for $domain: " . implode("\n", $output));
    }
  }

  private function configureCloudflare()
  {
    $url = "https://api.cloudflare.com/client/v4/zones/{$this->accountData['cloudflare_zone_id']}/dns_records";
    $payload = json_encode([
      'type' => 'A',
      'name' => "{$this->accountData['subdomain']}.{$this->accountData['main_domain']}",
      'content' => $this->accountData['server_ip'],
      'ttl' => 3600,
      'proxied' => true
    ]);

    $ch = curl_init();
    curl_setopt_array($ch, [
      CURLOPT_URL => $url,
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_POST => true,
      CURLOPT_POSTFIELDS => $payload,
      CURLOPT_HTTPHEADER => [
        "Content-Type: application/json",
        "Authorization: Bearer {$this->accountData['cloudflare_token']}"
      ]
    ]);

    $response = curl_exec($ch);
    if (curl_errno($ch)) {
      curl_close($ch);
      throw new Exception('Cloudflare API error: ' . curl_error($ch));
    }

    $responseData = json_decode($response, true);
    curl_close($ch);

    if (!$responseData['success']) {
      throw new Exception("Failed to create Cloudflare DNS record: " .
        ($responseData['errors'][0]['message'] ?? 'Unknown error'));
    }

    $this->createdResources['cloudflare_record'] = true;
  }

  private function configureCronJobs()
  {
    $newCrons = [
      "*/1 * * * * cd /var/www/html/{$this->accountData['username']}/system/ && /usr/bin/php cron.php",
      "0 * * * * cd /var/www/html/{$this->accountData['username']}/system/ && /usr/bin/php cron.php",
      "0 7 * * * cd /var/www/html/{$this->accountData['username']}/system/ && /usr/bin/php cron_reminder.php"
    ];

    exec('crontab -l', $currentCrons);
    $updatedCrons = array_unique(array_merge($currentCrons, $newCrons));

    if (count($updatedCrons) > count($currentCrons)) {
      file_put_contents('/tmp/crontab.txt', implode("\n", $updatedCrons) . "\n");
      exec('crontab /tmp/crontab.txt', $output, $return_var);

      if ($return_var !== 0) {
        throw new Exception("Failed to update crontab: " . implode("\n", $output));
      }

      $this->createdResources['cron_jobs'] = true;
    }
  }


  private function generateLicenseKey($length = 8)
  {
    $characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    $licenseKey = 'ISP-';
    for ($i = 0; $i < $length; $i++) {
      $licenseKey .= $characters[rand(0, strlen($characters) - 1)];
    }
    return $licenseKey;
  }

  private function createUserAndLicense()
  {
    // Connect to the main database
    $main_db = $this->accountData['mysql_database'];
    $conn = new mysqli(
      $this->accountData['mysql_host'],
      $this->accountData['mysql_user'],
      $this->accountData['mysql_password'],
      $main_db
    );

    if ($conn->connect_error) {
      throw new Exception("Failed to connect to main database: " . $conn->connect_error);
    }

    // Prepare user data
    $username = $this->accountData['username'];
    $licenseKey = $this->generateLicenseKey();
    $subdomain = $this->accountData['subdomain'];
    $main_domain = $this->accountData['main_domain'];
    $email = $this->accountData['email'];
    $phone = $this->accountData['phone'];
    $basePath = "/var/www/html/";
    $userPath = $basePath . $username;
    $domain = "https://" . trim($subdomain, ".") . "." . ltrim($main_domain, ".");
    $expiryDate = $this->accountData['subscription_end']; // Use the subscription end date from account data

    // Insert user
    $stmt = $conn->prepare("INSERT INTO users (username, email, folder_path, subdomain, domain, phone) VALUES (?, ?, ?, ?, ?, ?)");
    if (!$stmt) {
      throw new Exception("Prepare failed for user insertion: " . $conn->error);
    }

    $stmt->bind_param("ssssss", $username, $email, $userPath, $subdomain, $domain, $phone);
    if (!$stmt->execute()) {
      $stmt->close();
      throw new Exception("Failed to insert user into database: " . $conn->error);
    }

    $userId = $conn->insert_id; // Get the auto-incremented user ID
    $stmt->close();

    // Insert license
    $stmt = $conn->prepare("INSERT INTO licenses (user_id, license_key, expiry_date, status) VALUES (?, ?, ?, 'active')");
    if (!$stmt) {
      throw new Exception("Prepare failed for license insertion: " . $conn->error);
    }

    $stmt->bind_param("iss", $userId, $licenseKey, $expiryDate);
    if (!$stmt->execute()) {
      $stmt->close();
      throw new Exception("Failed to insert license into database: " . $conn->error);
    }
    $stmt->close();

    // Store license in a file inside the user's folder
    $licenseFilePath = $userPath . "/license.txt";
    $licenseContent = "License Key: $licenseKey\nExpiry Date: $expiryDate";

    if (file_put_contents($licenseFilePath, $licenseContent) === false) {
      throw new Exception("Failed to store license in file: $licenseFilePath");
    }

    $conn->close();
  }

  private function notifyAdmin()
  {
    $siteUrl = "https://{$this->accountData['subdomain']}.{$this->accountData['main_domain']}";
    
    $message = "New ISP Account Created:\n\n";
    $message .= "Company: {$this->accountData['isp_name']}\n";
    $message .= "Site URL: {$siteUrl}\n";
    $message .= "Admin Email: {$this->accountData['email']}\n";
    $message .= "Admin Username: admin\n";
    $message .= "Temporary Password: admin\n";
    $message .= "Subscription Plan: {$this->accountData['subscription_plan_id']}\n";
    $message .= "Expiry Date: {$this->accountData['subscription_end']}";

    // Send Telegram notification
    send_telegram_notification($message, BOT_TOKEN, CHAT_ID);
    
    // Send SMS notification (same data)
    //send_sms_notification($this->accountData['phone'], $message);
  }

  private function cleanup()
  {
    if (file_exists('/tmp/crontab.txt')) {
      unlink('/tmp/crontab.txt');
    }
  }

  private function rollback()
  {
    // Execute rollback actions in reverse order
    while (!empty($this->rollbackActions)) {
      $action = array_pop($this->rollbackActions);
      try {
        $action();
      } catch (Exception $e) {
        error_log("Rollback failed: " . $e->getMessage());
      }
    }

    // Clean up created resources
    if ($this->createdResources['folder']) {
      $this->removeDirectory("/var/www/html/{$this->accountData['username']}");
    }

    if ($this->createdResources['database']) {
      $conn = new mysqli(
        $this->accountData['mysql_host'],
        $this->accountData['mysql_user'],
        $this->accountData['mysql_password']
      );
      $conn->query("DROP DATABASE IF EXISTS `{$this->accountData['username']}`");
      $conn->close();
    }

    if ($this->createdResources['apache_config']) {
      @unlink("/etc/apache2/sites-available/{$this->accountData['username']}.conf");
      exec("sudo a2dissite {$this->accountData['username']}.conf 2>/dev/null");
      exec("sudo systemctl reload apache2 2>/dev/null");
    }

    if ($this->createdResources['cloudflare_record']) {
      try {
        // First we need to get the DNS record ID
        $url = "https://api.cloudflare.com/client/v4/zones/{$this->accountData['cloudflare_zone_id']}/dns_records?" .
          "type=A&name={$this->accountData['subdomain']}.{$this->accountData['main_domain']}";

        $ch = curl_init();
        curl_setopt_array($ch, [
          CURLOPT_URL => $url,
          CURLOPT_RETURNTRANSFER => true,
          CURLOPT_HTTPHEADER => [
            "Content-Type: application/json",
            "Authorization: Bearer {$this->accountData['cloudflare_token']}"
          ]
        ]);

        $response = curl_exec($ch);
        if (curl_errno($ch)) {
          throw new Exception('Cloudflare API error: ' . curl_error($ch));
        }

        $responseData = json_decode($response, true);
        curl_close($ch);

        if ($responseData['success'] && count($responseData['result']) > 0) {
          $recordId = $responseData['result'][0]['id'];

          // Now delete the record
          $deleteUrl = "https://api.cloudflare.com/client/v4/zones/{$this->accountData['cloudflare_zone_id']}/dns_records/$recordId";
          $ch = curl_init();
          curl_setopt_array($ch, [
            CURLOPT_URL => $deleteUrl,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_CUSTOMREQUEST => 'DELETE',
            CURLOPT_HTTPHEADER => [
              "Content-Type: application/json",
              "Authorization: Bearer {$this->accountData['cloudflare_token']}"
            ]
          ]);

          $response = curl_exec($ch);
          if (curl_errno($ch)) {
            throw new Exception('Cloudflare API error: ' . curl_error($ch));
          }

          $deleteResponse = json_decode($response, true);
          curl_close($ch);

          if (!$deleteResponse['success']) {
            throw new Exception("Failed to delete Cloudflare DNS record: " .
              ($deleteResponse['errors'][0]['message'] ?? 'Unknown error'));
          }
        }
      } catch (Exception $e) {
        error_log("Failed to delete Cloudflare DNS record during rollback: " . $e->getMessage());
      }
    }

    if ($this->createdResources['cron_jobs']) {
      try {
        // Get current crontab
        exec('crontab -l', $currentCrons);

        // Remove all cron jobs for this user
        $filteredCrons = array_filter($currentCrons, function ($line) {
          return strpos($line, "/var/www/html/{$this->accountData['username']}/") === false;
        });

        // Only update crontab if changes were made
        if (count($filteredCrons) < count($currentCrons)) {
          file_put_contents('/tmp/crontab.txt', implode("\n", $filteredCrons) . "\n");
          exec('crontab /tmp/crontab.txt', $output, $return_var);

          if ($return_var !== 0) {
            throw new Exception("Failed to update crontab during rollback: " . implode("\n", $output));
          }
        }
      } catch (Exception $e) {
        error_log("Failed to remove cron jobs during rollback: " . $e->getMessage());
      }
    }
  }
}
