<?php

namespace App\Controllers;

use Core\Request;
use Core\Redirect;
use Core\DB;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;

include realpath(dirname(__DIR__) . '/include/function.php');
include_once realpath(dirname(__DIR__) . '/../config.php');

class Register
{

  function registerProcess()
  {

    if (!isset($_POST['register_isp_account'])) {
      Redirect::redirectError('register_isp_account', "Invalid request.");
      return;
    }

    // Get database connection
    $db = new DB();
    $conn = $db->getConnection();

    $isp_name = trim(Request::getPost('isp_name', 'string'));
    $email = trim(Request::getPost('email', 'string'));
    $phone = trim(Request::getPost('phone', 'string'));
    $subdomain = trim(Request::getPost('subdomain', 'string'));
    $duration = intval(Request::getPost('duration', 'int'));
    $username = trim(Request::getPost('username', 'string'));
    $password = trim(Request::getPost('password', 'string'));
    $confirm_password = trim(Request::getPost('confirm_password', 'string'));


    // Check if password and confirm password match
    if ($password !== $confirm_password) {
      send_telegram_notification("Password and confirm password do not match!", BOT_TOKEN, CHAT_ID);
      Redirect::redirectError('register_isp_account', "Password and confirm password do not match!");
    }

    //make subdomain to be lowercase
    $subdomain = strtolower($subdomain);
    //REMOVE WHITESPACE FROM SUBDOMAIN
    $subdomain = str_replace(' ', '', $subdomain);
    //MAKE USERR NAME LOWASER CASE
    $username = strtolower($username);
    //REMOVE WHITESPACE FROM USERNAME
    $username = str_replace(' ', '', $username);

    // Create Apache configuration file
    $main_domain = MAIN_DOMAIN; // Ensure this is defined in your config.php
    $server_ip = SERVER_IP; // Ensure this is defined in your config.php
    $cloudflare_token = CLOUDFLARE_TOKEN; // Ensure this is defined in your config.php
    $cloudflare_zone_id = CLOUDFLARE_ZONE_ID; // Ensure this is defined in your config.php
    $mysql_host = MYSQL_HOST; // Ensure this is defined in your config.php
    $mysql_user = MYSQL_USER; // Ensure this is defined in your config.php
    $mysql_password = MYSQL_PASSWORD; // Ensure this is defined in your config.php
  

    // Check if the subdomain is already taken
    $checkSubdomainCmd = $conn->prepare("SELECT COUNT(*) FROM users WHERE subdomain = ?");
    $checkSubdomainCmd->bind_param("s", $subdomain);
    $checkSubdomainCmd->execute();
    $count = 0; // Initialize the variable
    $checkSubdomainCmd->bind_result($count);
    $checkSubdomainCmd->fetch();
    $checkSubdomainCmd->close();
    if ($count > 0) {
      send_telegram_notification("Subdomain already exists!", BOT_TOKEN, CHAT_ID);
      Redirect::redirectError('register_isp_account', "Subdomain already exists!");
    }

    // Check if the username is already taken on users table 
    $checkUserCmd = $conn->prepare("SELECT COUNT(*) FROM users WHERE username = ?");
    $checkUserCmd->bind_param("s", $username);
    $checkUserCmd->execute();
    $checkUserCmd->bind_result($count);
    $checkUserCmd->fetch();
    $checkUserCmd->close();
    if ($count > 0) {
      send_telegram_notification("Username already exists!", BOT_TOKEN, CHAT_ID);
      Redirect::redirectError('register_isp_account', "Username already exists!");
    }

    // Check if the email is already taken on users table
    $checkEmailCmd = $conn->prepare("SELECT COUNT(*) FROM users WHERE email = ?");
    $checkEmailCmd->bind_param("s", $email);
    $checkEmailCmd->execute();
    $checkEmailCmd->bind_result($count);
    $checkEmailCmd->fetch();
    $checkEmailCmd->close();
    if ($count > 0) {
      send_telegram_notification("Email already exists!", BOT_TOKEN, CHAT_ID);
      Redirect::redirectError('register_isp_account', "Email already exists!");
    }



    $base_folder = "/var/www/html";
    $demo_folder = "${base_folder}/dev";
    $new_folder = "${base_folder}/${username}";
    $new_db = $username;
    $apache_conf_file = "/etc/apache2/sites-available/${username}.conf";
    $config_file = "${new_folder}/config.php";
    $system_zip_file = realpath(dirname(__DIR__) . '/../' . SYSTEM_ZIP_FILE_NAME);
    $database_file = realpath(dirname(__DIR__) . '/../' . DATABASE_FILE);

    //Check if system_zip_file exists
    if (!file_exists($system_zip_file)) {
      error_log("System zip file not found: $system_zip_file");
      send_telegram_notification("System zip file not found: $system_zip_file", BOT_TOKEN, CHAT_ID);
      //Redirect::redirectError('register_isp_account', "System zip file not found: $system_zip_file PATH: " . realpath(dirname(__DIR__) . '/../../'.SYSTEM_ZIP_FILE_NAME));
    }

    //Check if database_file exists
    if (!file_exists($database_file)) {
      error_log("Database file not found: $database_file");
      send_telegram_notification("Database file not found: $database_file", BOT_TOKEN, CHAT_ID);
      // Redirect::redirectError('register_isp_account', "Database file not found: $database_file");
    }

    $zip = new \ZipArchive;

    // Duplicate the folder contents
    if (!file_exists($new_folder)) {
      //create new folder
      if (!mkdir($new_folder, 0755, true)) {
        error_log("Failed to create directory: $new_folder");
        send_telegram_notification("Failed to create directory: $new_folder", BOT_TOKEN, CHAT_ID);
        Redirect::redirectError('register_isp_account', "Failed to create directory: $new_folder");
      }
      //unzip the system files  QNE MOVE TO NEW FOLDER
      if ($zip->open($system_zip_file) === TRUE) {
        $extractPath = pathinfo($system_zip_file, PATHINFO_FILENAME);
        $tempExtractPath = $new_folder . '_temp'; // Temporary folder for extraction

        //send_telegram_notification("Inside folder name $extractPath Temp Extract Path: $tempExtractPath", BOT_TOKEN, CHAT_ID);

        // Create temp extraction folder
        if (!is_dir($tempExtractPath)) {
          mkdir($tempExtractPath, 0777, true);
        }

        $zip->extractTo($tempExtractPath);   // Extract to temp folder
        $zip->close();

        // Find extracted folder (if it's inside a subdirectory)
        $subfolders = array_diff(scandir($tempExtractPath), ['.', '..']);
        if (count($subfolders) === 1 && is_dir($tempExtractPath . "/" . reset($subfolders))) {
          $extractPath = $tempExtractPath . "/" . reset($subfolders);
        } else {
          $extractPath = $tempExtractPath;
        }

        // Ensure the new folder exists
        if (!is_dir($new_folder)) {
          mkdir($new_folder, 0777, true);
        }

        // Move extracted files to the new folder
        $files = new \RecursiveIteratorIterator(
          new RecursiveDirectoryIterator($extractPath, RecursiveDirectoryIterator::SKIP_DOTS),
          RecursiveIteratorIterator::SELF_FIRST
        );

        foreach ($files as $file) {
          $destination = str_replace($extractPath, $new_folder, $file);

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

        // Remove temporary folder
        function delete_folder($folder)
        {
          $files = array_diff(scandir($folder), ['.', '..']);
          foreach ($files as $file) {
            $path = "$folder/$file";
            is_dir($path) ? delete_folder($path) : unlink($path);
          }
          rmdir($folder);
        }
        delete_folder($tempExtractPath);
      } else {
        error_log("Failed to extract zip file: SYSTEM_ZIP_FILE_NAME");
        send_telegram_notification("Failed to extract zip file: SYSTEM_ZIP_FILE_NAME", BOT_TOKEN, CHAT_ID);
        Redirect::redirectError('register_isp_account', "Failed to extract zip file: SYSTEM_ZIP_FILE_NAME");
      }
    }

    // Check if the database already exists
    $conn_connection = new $conn(MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD);
    if ($conn_connection->connect_error) {
      error_log("MySQL Connection Error: " . $conn_connection->connect_error);
      send_telegram_notification("Failed to connect to MySQL: " . $conn_connection->connect_error, BOT_TOKEN, CHAT_ID);
      Redirect::redirectError('register_isp_account', "Failed to connect to MySQL: " . $conn_connection->connect_error);
    }

    // Check if the database exists if not create it
    $dbExists = $conn_connection->query("SHOW DATABASES LIKE '$new_db'");
    if ($dbExists->num_rows === 0) {
      if (!$conn_connection->query("CREATE DATABASE $new_db")) {
        error_log("Failed to create database: " . $conn_connection->error);
        send_telegram_notification("Failed to create database: " . $conn_connection->error, BOT_TOKEN, CHAT_ID);
        Redirect::redirectError('register_isp_account', "Failed to create database: " . $conn_connection->error);
      }
    }



    // Check if database already contains data
    $checkDataCmd = $conn_connection->query("SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '$new_db'");
    if ($checkDataCmd->num_rows > 0) {
      $checkDataCmd->data_seek(0);
      $row = $checkDataCmd->fetch_row();
      if ($row[0] > 0) {
        // Database already contains data
      } else {
        // IMPORT DATABASE database_file TO THE NEW DATABASE
        $importCmd = "mysql -u" . MYSQL_USER . " -p" . MYSQL_PASSWORD . " $new_db < " . $database_file . " 2>&1";
        $importOutput = shell_exec($importCmd);
      }
    }


    $updateCompanyNameCmd = $conn_connection->prepare("UPDATE `$new_db`.tbl_appconfig SET value = ? WHERE setting = 'CompanyName'");
    if ($updateCompanyNameCmd) {
      $updateCompanyNameCmd->bind_param("s", $isp_name);
      if (!$updateCompanyNameCmd->execute()) {
        error_log("Failed to update CompanyName: " . $updateCompanyNameCmd->error);
        send_telegram_notification("Failed to update CompanyName: " . $updateCompanyNameCmd->error, BOT_TOKEN, CHAT_ID);
        Redirect::redirectError('register_isp_account', "Failed to update CompanyName: " . $updateCompanyNameCmd->error);
      }
      $updateCompanyNameCmd->close();
    } else {
      error_log("Prepare failed for CompanyName: " . $conn_connection->error);
      send_telegram_notification("Prepare failed for CompanyName: " . $conn_connection->error, BOT_TOKEN, CHAT_ID);
      Redirect::redirectError('register_isp_account', "Prepare failed for CompanyName: " . $conn_connection->error);
    }

    // UPDATE PHONE ON tbl_appconfig
    $updatePhoneCmd = $conn_connection->prepare("UPDATE `$new_db`.tbl_appconfig SET value = ? WHERE setting	 = 'phone'");
    if ($updatePhoneCmd) {
      $updatePhoneCmd->bind_param("s", $phone);
      if (!$updatePhoneCmd->execute()) {
        error_log("Failed to update phone: " . $updatePhoneCmd->error);
        send_telegram_notification("Failed to update phone: " . $updatePhoneCmd->error, BOT_TOKEN, CHAT_ID);
        Redirect::redirectError('register_isp_account', "Failed to update phone: " . $updatePhoneCmd->error);
      }
      $updatePhoneCmd->close();
    } else {
      error_log("Prepare failed for phone: " . $conn_connection->error);
      send_telegram_notification("Prepare failed for phone: " . $conn_connection->error, BOT_TOKEN, CHAT_ID);
      Redirect::redirectError('register_isp_account', "Prepare failed for phone: " . $conn_connection->error);
    }

    // Close the$conn connection
    $conn_connection->close();





    if (!file_exists($apache_conf_file)) { // Check if the file already exists
      $apache_conf = <<<EOL
      <VirtualHost *:80>
          ServerName ${subdomain}.$main_domain
          ServerAlias www.${subdomain}.$main_domain
          ServerAdmin webmaster@localhost
          DocumentRoot $new_folder
          ErrorLog \${APACHE_LOG_DIR}/error.log
          CustomLog \${APACHE_LOG_DIR}/access.log combined
      </VirtualHost>
      EOL;
      $apache_conf = str_replace("\n", PHP_EOL, $apache_conf);

      // Attempt to write the configuration file
      if (file_put_contents($apache_conf_file, $apache_conf) === false) {
        send_telegram_notification("Failed to create Apache configuration file: $apache_conf_file", BOT_TOKEN, CHAT_ID);
        error_log("Failed to create Apache configuration file: $apache_conf_file");
        Redirect::redirectError('register_isp_account', "Failed to create Apache configuration file: $apache_conf_file");
      }
    }




    // Enable the new site and reload Apache
    exec("sudo a2ensite ${username}.conf && sudo systemctl reload apache2", $output, $return_var);

    if ($return_var !== 0) {
      $error_message = "Failed to enable the new site or reload Apache: " . implode("\n", (array) $output);
      // Log error
      error_log($error_message);
      // Send Telegram notification (ensure BOT_TOKEN and CHAT_ID are defined)

      send_telegram_notification($error_message, BOT_TOKEN, CHAT_ID);

      // Redirect with error message
      Redirect::redirectError('register_isp_account', $error_message);
    }

    // Escape the username to prevent shell injection
    $escaped_username = escapeshellarg($username);




    // Configure Cloudflare DNS
    $cloudflare_url = "https://api.cloudflare.com/client/v4/zones/$cloudflare_zone_id/dns_records";
    $cloudflare_data = json_encode([
      'type'    => 'A',
      'name'    => "$subdomain.$main_domain",
      'content' => $server_ip, // Ensure this is set
      'ttl'     => 3600,
      'proxied' => true
    ]);
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $cloudflare_url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $cloudflare_data);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
      "Content-Type: application/json",
      "Authorization: Bearer $cloudflare_token"
    ]);
    //

    $response = curl_exec($ch);
    $data = json_decode($response, true);
    curl_close($ch);
    if (isset($data['success']) && $data['success']) {
      // send_telegram_notification("Cloudflare configured successfully! DNS record created for $username.$main_domain", BOT_TOKEN, CHAT_ID);
    } else {
      $error_message = "Failed to configure  Cloudflare: " . $response;

      // Log error
      error_log($error_message);

      // Redirect with error message
      Redirect::redirectError('register_isp_account', $error_message);
    }





    // Update config.php file
    $config_content = <<<EOL
            <?php

            define('APP_URL', 'https://${subdomain}.$main_domain');
            \$_app_stage = 'Live';

            // Database Nena Config
            \$db_host = '$mysql_host';
            \$db_user = '$mysql_user';
            \$db_password = '$mysql_password';
            \$db_name = '$new_db';

            if (\$_app_stage != 'Live') {
                error_reporting(E_ERROR);
                ini_set('display_errors', 1);
                ini_set('display_startup_errors', 1);
            } else {
                error_reporting(E_ERROR);
                ini_set('display_errors', 0);
                ini_set('display_startup_errors', 0);
            }
            EOL;

    if (file_put_contents($config_file, $config_content) === false) {
      error_log("Failed to create config file: $config_file");
      send_telegram_notification("Failed to create config file: $config_file", BOT_TOKEN, CHAT_ID);
      Redirect::redirectError('register_isp_account', "Failed to create config file: $config_file");
    }



    // Create user and license
    createUserAndLicense($isp_name, $email, $username, $subdomain, $duration, $phone, $main_domain, MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE);

    // Notify admin about the new client registration
    notify_new_client($conn, $isp_name, $email, $password, $phone, $subdomain, BOT_TOKEN, CHAT_ID, $main_domain);


    Redirect::redirectSuccess('register_isp_account', "ISP account created successfully! Please check your email for login details.");
  }
}
