<?php
/*
 * ============================================================
 *  ROOT.CLASS.PHP  —  BUG-FIXED SECTIONS
 *  Apply these replacements to the original root.class.php
 * ============================================================
 *
 *  CHANGES:
 *   1. db_safeguard  – added escape() helper (used by save.php)
 *   2. ajax::insert() – guard $email->send() inside isset check
 *   3. ajax::update() – guard $email->send() + fix isset on user_password
 *   4. ajax::select() – fix $to_date_key → isset($to_Date)
 *   5. file_upload handler – use $_FILES["file"] not $_FILES["fileToUpload"]
 * ============================================================
 */


/* ─────────────────────────────────────────────────────────────
   1.  db_safeguard  –  add escape() method
   Place this method anywhere inside the db_safeguard class body.
───────────────────────────────────────────────────────────── */

// INSIDE class db_safeguard  {  ...

    /**
     * Safely escape a string for use in a raw SQL query.
     */
    public function escape(string $value): string
    {
        return mysqli_real_escape_string($this->connection, $value);
    }

// }  end db_safeguard


/* ─────────────────────────────────────────────────────────────
   2.  ajax::insert()  –  guard $email->send()
   Replace the existing insert() method with this version.
───────────────────────────────────────────────────────────── */

// INSIDE class ajax  {  ...

    function insert()
    {
        $table_name           = $_POST['table_name'];
        $edit_file_name       = $_POST['edit_file_name'];
        $returned_cols        = explode(",", $_POST['return_columns']);
        $add_column_and_value = explode(",", $_POST['add_column_and_value']);

        if (count($add_column_and_value) > 0) {
            foreach ($add_column_and_value as $pair) {
                $pair = explode("=", $pair);
                if (count($pair) === 2) {
                    $_POST[$pair[0]] = $pair[1];
                }
            }
        }

        $excloudedcolumns = explode(',', $_POST['excloded_colum_names']);
        foreach ($excloudedcolumns as $col) {
            unset($_POST[$col]);
        }

        unset(
            $_POST['excloded_colum_names'],
            $_POST['add_column_and_value'],
            $_POST['return_columns'],
            $_POST['edit_file_name'],
            $_POST['ajax_type'],
            $_POST['table_name'],
            $_POST['where_clause'],
            $_POST['submit'],
            $_POST['']
        );

        // BUG 3 FIX: only instantiate $email when the fields are present,
        //            and only call send() inside the same block.
        $emailInstance = null;
        if (isset($_POST['email_address_array'])) {
            $emailInstance = new email();
            $addresses     = explode(',', $_POST['email_address_array']);
            foreach ($addresses as $addr) {
                if (strlen($addr) > 0) {
                    $emailInstance->add_address($addr, $addr);
                }
            }
            $emailInstance->subject($_POST['subject'] ?? '');
            $emailInstance->body($_POST['body']    ?? '');
        }
        unset($_POST['email_address_array'], $_POST['subject'], $_POST['body']);

        if (isset($_POST['password'])) {
            $auth            = new authentication();
            $_POST['password'] = $auth->encrypt_password($_POST['password']);
        }
        if (isset($_POST['user_password'])) {
            $_POST['user_password'] = hash('SHA256', $_POST['user_password']);
        }

        $columns        = array_keys($_POST);
        $values         = array_values($_POST);
        $columns_string = "`" . implode("` , `", $columns) . "`";
        $values_string  = "'" . implode("','", $values) . "'";

        $sql = "INSERT INTO $table_name ($columns_string) VALUES ($values_string)";
        $db  = new db_safeguard();
        $res = $db->query($table_name, $sql);

        if ($res > 0) {
            // Only send e-mail if one was configured
            if ($emailInstance !== null) {
                $emailInstance->send();
            }
            return 1;
        }

        return $res;
    }


/* ─────────────────────────────────────────────────────────────
   3.  ajax::update()  –  guard $email->send() + fix isset
   Replace the existing update() method with this version.
───────────────────────────────────────────────────────────── */

    function update()
    {
        $table_name           = $_POST['table_name'];
        $edit_file_name       = $_POST['edit_file_name'];
        $returned_cols        = explode(",", $_POST['return_columns']);
        $add_column_and_value = explode(",", $_POST['add_column_and_value']);

        if (count($add_column_and_value) > 0) {
            foreach ($add_column_and_value as $pair) {
                $pair = explode("=", $pair);
                if (count($pair) === 2) {
                    $_POST[$pair[0]] = $pair[1];
                }
            }
        }

        $excloudedcolumns = explode(',', $_POST['excloded_colum_names']);
        foreach ($excloudedcolumns as $col) {
            unset($_POST[$col]);
        }

        unset(
            $_POST['excloded_colum_names'],
            $_POST['add_column_and_value'],
            $_POST['return_columns'],
            $_POST['edit_file_name'],
            $_POST['ajax_type'],
            $_POST['table_name'],
            $_POST['where_clause'],
            $_POST['submit']
        );

        $record_id = $_POST['record_id'];
        unset($_POST['record_id']);

        if (isset($_POST['password'])) {
            $auth              = new authentication();
            $_POST['password'] = $auth->encrypt_password($_POST['password']);
        }

        // BUG 5 FIX: check isset before calling strlen to avoid PHP 8 error
        if (!isset($_POST['user_password']) || strlen($_POST['user_password']) < 1) {
            unset($_POST['user_password']);
        } else {
            $_POST['user_password'] = hash('SHA256', $_POST['user_password']);
        }

        // BUG 4 FIX: same email guard as insert()
        $emailInstance = null;
        if (isset($_POST['email_address_array'])) {
            $emailInstance = new email();
            $addresses     = explode(',', $_POST['email_address_array']);
            foreach ($addresses as $addr) {
                if (strlen($addr) > 0) {
                    $emailInstance->add_address($addr, $addr);
                }
            }
            $emailInstance->subject($_POST['subject'] ?? '');
            $emailInstance->body($_POST['body']    ?? '');
        }
        unset($_POST['email_address_array'], $_POST['subject'], $_POST['body']);

        $columns       = array_keys($_POST);
        $values        = array_values($_POST);
        $update_string = "";
        foreach ($columns as $key => $column) {
            if (strlen($column) > 1) {
                $update_string .= "`$column` = '$values[$key]', ";
            }
        }
        $update_string = rtrim($update_string, ', ');

        $sql    = "UPDATE $table_name SET $update_string WHERE `record_id` = $record_id";
        $db     = new db_safeguard();
        $result = $db->query($table_name, $sql);

        if ($result) {
            if ($emailInstance !== null) {
                $emailInstance->send();
            }
            return 1;
        }

        return $result;
    }


/* ─────────────────────────────────────────────────────────────
   4.  ajax::select()  –  fix undefined $to_date_key
   Replace only the inner foreach date-range block.
───────────────────────────────────────────────────────────── */

// ORIGINAL (broken):
//
//   } elseif (strpos($columns[$key], 'from_date') !== false) {
//       foreach ($columns[$key] as $key2 => $value2) {          // ← iterates a string!
//           if (strpos($columns[$key2], 'to_date') !== false) {
//               $to_Date = $columns[$key2];
//           }
//       }
//       if ($to_date_key !== false) {                            // ← $to_date_key never set
//           $conditions[] = ...
//       }
//   }

// FIXED version of that elseif block:
//
//   } elseif (strpos($columns[$key], 'from_date') !== false) {
//       $to_Date = null;
//       foreach ($columns as $key2 => $col2) {           // iterate the columns array, not a string
//           if (strpos($col2, 'to_date') !== false && isset($values[$key2])) {
//               $to_Date = $values[$key2];
//               break;
//           }
//       }
//       // BUG 6 FIX: check $to_Date (the value), not the undefined $to_date_key
//       if (isset($to_Date)) {
//           $conditions[] = "`$columns[$key]` BETWEEN '$values[$key]' AND '$to_Date'";
//       }
//   }

// Apply the same fix to the identical block inside ajax::project_reports().


/* ─────────────────────────────────────────────────────────────
   5.  file_upload  –  use correct $_FILES key
   Find this block near the bottom of root.class.php:

       if (isset($_POST['ajax_type']) && $_POST['ajax_type'] == "file_upload") {
           $file_save_path = $_POST['file_save_path'];
           $target_dir     = $file_save_path;
           $target_file    = $target_dir . basename($_FILES["fileToUpload"]["name"]);  ← BUG
           ...
           if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) { ← BUG

   Replace with the version below.
───────────────────────────────────────────────────────────── */

if (isset($_POST['ajax_type']) && $_POST['ajax_type'] == "file_upload") {

    // BUG 7 FIX: JS sends the file as 'file', not 'fileToUpload'
    if (!isset($_FILES['file']) || $_FILES['file']['error'] !== UPLOAD_ERR_OK) {
        echo "No file uploaded or upload error. Code: "
            . ($_FILES['file']['error'] ?? 'no file');
        exit;
    }

    $file_save_path = rtrim($_POST['file_save_path'], '/') . '/';

    if (!is_dir($file_save_path)) {
        mkdir($file_save_path, 0755, true);
    }

    $target_file = $file_save_path . basename($_FILES['file']['name']);

    if (move_uploaded_file($_FILES['file']['tmp_name'], $target_file)) {
        echo "OK";
    } else {
        echo "Failed to move uploaded file to: $target_file";
    }
    exit;
}