<?php

// Database Configuration

define('DB_HOST', 'localhost');

define('DB_USER', 'root');

define('DB_PASS', '');

define('DB_NAME', 'rvfcyvys_xcpo');



// Site Configuration

define('SITE_NAME', 'EduTrack PRO');

define('BASE_URL', 'https://edutrack.oricnetwork.com');



// Timezone

date_default_timezone_set('Africa/Accra');



// Error reporting - Turn off in production

error_reporting(E_ALL);

ini_set('display_errors', 0);



// Global database connection variable

$global_conn = null;



// Global configuration array

$config = [

    'arkesel' => [

        'api_key' => 'a2JKV2libkhvUEV3d3B3dWxUQ1E',

        'sender_id' => 'Oric',

        'base_url' => 'https://sms.arkesel.com/api/v2/sms/send'

    ],

    'paystack' => [

        'secret_key' => 'sk_test_f5f8c4d36c349f992b300cb8fcbc143a6994799e',

        'public_key' => 'pk_test_6c64a12b054ad9cbf950fb9c4e1a719e85457416',

        'base_url' => 'https://api.paystack.co'

    ],

    'email' => [

        'smtp_host' => 'business89.web-hosting.com',

        'smtp_user' => 'info@oricnetwork.com',

        'smtp_pass' => '0551274917@series',

        'smtp_port' => 587,

        'from_email' => 'info@oricnetwork.com',

        'from_name' => 'Oric Network Limited',

        'tech_email' => 'tech@oric.network',

        'manager_email' => 'manager@oricnetwork.com',

        'ceo_email' => 'ceo@oricnetwork.com'

    ]

];



// Database Connection - IMPROVED VERSION

function getDBConnection() {

    global $global_conn;

    

    // Check if connection exists and is still alive

    if ($global_conn !== null) {

        try {

            // Try to ping the server to check if connection is alive

            if (@$global_conn->ping()) {

                return $global_conn;

            }

        } catch (Exception $e) {

            // Connection is dead, will create new one below

            error_log("Database connection ping failed: " . $e->getMessage());

        }

        

        // If we get here, connection is dead - close it properly

        try {

            @$global_conn->close();

        } catch (Exception $e) {

            // Ignore errors when closing dead connection

        }

        $global_conn = null;

    }

    

    // Create new connection

    $global_conn = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);

    

    if ($global_conn->connect_error) {

        error_log("Database connection failed: " . $global_conn->connect_error);

        return null;

    }

    

    $global_conn->set_charset("utf8mb4");

    return $global_conn;

}



// Helper function to safely close connection (call only at end of script)

function closeDBConnection() {

    global $global_conn;

    if ($global_conn !== null) {

        try {

            $global_conn->close();

        } catch (Exception $e) {

            // Ignore errors

        }

        $global_conn = null;

    }

}



// Helper function to sanitize input

function sanitize($input) {

    if ($input === null) {

        return '';

    }

    

    $input = trim($input);

    $input = stripslashes($input);

    

    // Get connection for escaping

    $conn = getDBConnection();

    if ($conn) {

        $input = $conn->real_escape_string($input);

    }

    

    return htmlspecialchars($input, ENT_QUOTES, 'UTF-8');

}



// Helper function to format currency - Ghana Cedi

function formatCurrency($amount) {

    if (!is_numeric($amount)) {

        $amount = 0;

    }

    return '₵' . number_format($amount, 2);

}



// Helper function to get current academic year

function getAcademicYear() {

    $year = date('Y');

    $month = date('m');

    if ($month > 6) {

        return $year . '-' . ($year + 1);

    } else {

        return ($year - 1) . '-' . $year;

    }

}



// ==================== ARKESEL SMS SERVICE ====================



/**

 * Send SMS using Arkesel API

 * 

 * @param string $phone Recipient phone number

 * @param string $message SMS message content

 * @return bool Success status

 */

function sendSMS($phone, $message) {

    global $config, $global_conn;

    

    $phone = formatPhoneNumber($phone);

    

    if (empty($config['arkesel']['api_key'])) {

        error_log("Arkesel API not configured");

        return false;

    }

    

    $data = [

        'sender' => $config['arkesel']['sender_id'],

        'message' => $message,

        'recipients' => [$phone]

    ];

    

    $headers = [

        'api-key: ' . $config['arkesel']['api_key'],

        'Content-Type: application/json'

    ];

    

    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $config['arkesel']['base_url']);

    curl_setopt($ch, CURLOPT_POST, true);

    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);

    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));

    

    $response = curl_exec($ch);

    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    curl_close($ch);

    

    // Log SMS

    logSMS($phone, $message, $httpCode == 200 ? 'Success' : 'Failed');

    

    return $httpCode == 200;

}



/**

 * Format phone number to international format

 * 

 * @param string $phone Phone number to format

 * @return string Formatted phone number

 */

function formatPhoneNumber($phone) {

    // Remove any non-numeric characters

    $phone = preg_replace('/[^0-9]/', '', $phone);

    

    // If number starts with 0, convert to 233

    if (substr($phone, 0, 1) == '0') {

        $phone = '233' . substr($phone, 1);

    }

    

    // If number doesn't start with 233, add it

    if (substr($phone, 0, 3) != '233') {

        $phone = '233' . $phone;

    }

    

    return $phone;

}



/**

 * Log SMS to database

 * 

 * @param string $phone Recipient phone number

 * @param string $message SMS content

 * @param string $status Delivery status

 */

function logSMS($phone, $message, $status) {

    $conn = getDBConnection();

    if (!$conn) return;

    

    try {

        $logQuery = "INSERT INTO sms_logs (phone, message, status, created_at) VALUES (?, ?, ?, NOW())";

        $stmt = $conn->prepare($logQuery);

        $stmt->bind_param("sss", $phone, $message, $status);

        $stmt->execute();

        // //$stmt->close();

    } catch (Exception $e) {

        error_log("Error logging SMS: " . $e->getMessage());

    }

    // DON'T close the connection here - let it persist

}



// ==================== EMAIL SERVICE ====================



/**

 * Send email using PHPMailer

 * 

 * @param string $to Recipient email

 * @param string $subject Email subject

 * @param string $body Email body (HTML)

 * @param array $cc CC recipients

 * @param array $attachments File attachments

 * @return bool Success status

 */

function sendEmail($to, $subject, $body, $cc = [], $attachments = []) {

    global $config;

    

    // Check if PHPMailer is available

    if (!class_exists('PHPMailer\PHPMailer\PHPMailer')) {

        error_log("PHPMailer not loaded. Please include PHPMailer library.");

        return false;

    }

    

    try {

        $mail = new PHPMailer\PHPMailer\PHPMailer(true);

        

        // Server settings

        $mail->isSMTP();

        $mail->Host = $config['email']['smtp_host'];

        $mail->SMTPAuth   = true;

        $mail->Username   = $config['email']['smtp_user'];

        $mail->Password   = $config['email']['smtp_pass'];

        $mail->SMTPSecure = PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_STARTTLS;

        $mail->Port = $config['email']['smtp_port'];

        $mail->Timeout = 30;

        $mail->CharSet = 'UTF-8';



        // Recipients

        $mail->setFrom($config['email']['from_email'], $config['email']['from_name']);

        $mail->addAddress($to);

        

        foreach ($cc as $email) {

            $mail->addCC($email);

        }

        

        // Attachments

        foreach ($attachments as $attachment) {

            if (file_exists($attachment['path'])) {

                $mail->addAttachment($attachment['path'], $attachment['name']);

            }

        }

        

        // Content

        $mail->isHTML(true);

        $mail->Subject = $subject;

        $mail->Body    = $body;

        $mail->AltBody = strip_tags($body);

        

        $mail->send();

        return true;

    } catch (Exception $e) {

        error_log("Email Error: " . $e->getMessage());

        return false;

    }

}



// ==================== PAYSTACK PAYMENT SERVICE ====================



/**

 * Initialize Paystack payment

 * 

 * @param array $data Payment data

 * @return array Response from Paystack

 */

function initializePaystackPayment($data) {

    global $config;

    

    $url = $config['paystack']['base_url'] . '/transaction/initialize';

    

    $headers = [

        'Authorization: Bearer ' . $config['paystack']['secret_key'],

        'Content-Type: application/json'

    ];

    

    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $url);

    curl_setopt($ch, CURLOPT_POST, true);

    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);

    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));

    

    $response = curl_exec($ch);

    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    curl_close($ch);

    

    return [

        'success' => $httpCode == 200,

        'data' => json_decode($response, true),

        'http_code' => $httpCode

    ];

}



/**

 * Verify Paystack payment

 * 

 * @param string $reference Transaction reference

 * @return array Response from Paystack

 */

function verifyPaystackPayment($reference) {

    global $config;

    

    $url = $config['paystack']['base_url'] . '/transaction/verify/' . $reference;

    

    $headers = [

        'Authorization: Bearer ' . $config['paystack']['secret_key'],

        'Content-Type: application/json'

    ];

    

    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $url);

    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);

    

    $response = curl_exec($ch);

    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    curl_close($ch);

    

    return [

        'success' => $httpCode == 200,

        'data' => json_decode($response, true),

        'http_code' => $httpCode

    ];

}



/**

 * Get setting value from database

 * 

 * @param string $key Setting key to retrieve

 * @param mixed $default Default value if setting not found

 * @return mixed Setting value or default

 */

function getSetting($key, $default = '') {

    $conn = getDBConnection();

    if (!$conn) return $default;

    

    // Use prepared statement for security

    $stmt = $conn->prepare("SELECT setting_value FROM settings WHERE setting_key = ?");

    if (!$stmt) return $default;

    

    $stmt->bind_param("s", $key);

    $stmt->execute();

    $result = $stmt->get_result();

    

    if ($row = $result->fetch_assoc()) {

        $value = $row['setting_value'];

        //$stmt->close();

        return $value;

    }

    

    //$stmt->close();

    return $default;

}



/**

 * Update setting value

 * 

 * @param string $key Setting key

 * @param mixed $value New value

 * @return bool Success status

 */

function updateSetting($key, $value) {

    $conn = getDBConnection();

    if (!$conn) return false;

    

    // Check if setting exists

    $check = $conn->query("SELECT id FROM settings WHERE setting_key = '$key'");

    

    if ($check && $check->num_rows > 0) {

        $stmt = $conn->prepare("UPDATE settings SET setting_value = ?, updated_at = NOW() WHERE setting_key = ?");

        $stmt->bind_param("ss", $value, $key);

    } else {

        $stmt = $conn->prepare("INSERT INTO settings (setting_key, setting_value, updated_at) VALUES (?, ?, NOW())");

        $stmt->bind_param("ss", $key, $value);

    }

    

    $result = $stmt->execute();

    //$stmt->close();

    return $result;

}



/**

 * Log user activity for audit trail

 * 

 * @param mysqli $conn Database connection

 * @param int $user_id User ID performing the action

 * @param string $action Action type (e.g., 'Login', 'Add Student', 'Delete Payment')

 * @param string $description Detailed description of the action

 * @return bool Success status

 */

function logActivity($conn, $user_id, $action, $description) {

    // Get IP address

    $ip_address = $_SERVER['REMOTE_ADDR'] ?? '';

    

    // Get user agent

    $user_agent = $_SERVER['HTTP_USER_AGENT'] ?? '';

    

    // Prepare and execute insert

    $stmt = $conn->prepare("INSERT INTO user_activities (user_id, action, description, ip_address, user_agent, created_at) VALUES (?, ?, ?, ?, ?, NOW())");

    $stmt->bind_param("issss", $user_id, $action, $description, $ip_address, $user_agent);

    

    $result = $stmt->execute();

    //$stmt->close();

    

    return $result;

}



/**

 * Get user activity log with optional filters

 * 

 * @param mysqli $conn Database connection

 * @param int $user_id Optional user ID filter

 * @param string $action Optional action filter

 * @param string $date_from Optional start date

 * @param string $date_to Optional end date

 * @param int $limit Number of records to return

 * @return array Array of activity records

 */

function getActivityLog($conn, $user_id = null, $action = null, $date_from = null, $date_to = null, $limit = 100) {

    $query = "SELECT ua.*, u.full_name, u.username, u.role 

              FROM user_activities ua 

              JOIN users u ON ua.user_id = u.id 

              WHERE 1=1";

    

    $params = [];

    $types = "";

    

    if ($user_id) {

        $query .= " AND ua.user_id = ?";

        $params[] = $user_id;

        $types .= "i";

    }

    

    if ($action) {

        $query .= " AND ua.action = ?";

        $params[] = $action;

        $types .= "s";

    }

    

    if ($date_from) {

        $query .= " AND DATE(ua.created_at) >= ?";

        $params[] = $date_from;

        $types .= "s";

    }

    

    if ($date_to) {

        $query .= " AND DATE(ua.created_at) <= ?";

        $params[] = $date_to;

        $types .= "s";

    }

    

    $query .= " ORDER BY ua.created_at DESC LIMIT ?";

    $params[] = $limit;

    $types .= "i";

    

    $stmt = $conn->prepare($query);

    

    if (!empty($params)) {

        $stmt->bind_param($types, ...$params);

    }

    

    $stmt->execute();

    $result = $stmt->get_result();

    

    $activities = [];

    while ($row = $result->fetch_assoc()) {

        $activities[] = $row;

    }

    

    //$stmt->close();

    return $activities;

}

// ── AI provider configuration ───────────────────────────────────────────────
// This file is a SEPARATE config world from the root edutrack/config.php (see
// getDBConnection() above — both files define it, so they must never both be
// required in one request). That meant CLAUDE_API_KEY/GROQ_API_KEY/etc and
// getSettingValue() were never defined for any code path that only loads this
// file (e.g. exams_generator/ajax/generate_exam.php's pipeline), so
// RBCAIEngine's cascade fataled on "Call to undefined function
// getSettingValue()" for every provider and silently fell back to the offline
// template generator. Added here, additive-only and guarded exactly like the
// root config does it, so it's safe even if both ever end up loaded together.
(static function (): void {
    $envFile = dirname(__DIR__) . '/.env';
    if (!is_file($envFile)) {
        return;
    }
    $vars = parse_ini_file($envFile, false, INI_SCANNER_RAW);
    if (!is_array($vars)) {
        return;
    }
    foreach ($vars as $key => $value) {
        $key = (string) $key;
        $value = (string) $value;
        if (!array_key_exists($key, $_ENV)) {
            $_ENV[$key] = $value;
            putenv("{$key}={$value}");
        }
    }
})();

if (!defined('CLAUDE_API_KEY')) {
    define('CLAUDE_API_KEY', $_ENV['CLAUDE_API_KEY'] ?? '');
}
if (!defined('CLAUDE_MODEL')) {
    define('CLAUDE_MODEL', 'claude-haiku-4-5');
}
if (!defined('GROQ_API_KEY')) {
    define('GROQ_API_KEY', $_ENV['GROQ_API_KEY'] ?? '');
}
if (!defined('GROQ_MODEL')) {
    define('GROQ_MODEL', 'llama-3.3-70b-versatile');
}
if (!defined('GEMINI_API_KEY')) {
    define('GEMINI_API_KEY', $_ENV['GEMINI_API_KEY'] ?? '');
}
if (!defined('GEMINI_MODEL')) {
    define('GEMINI_MODEL', 'gemini-2.0-flash');
}

if (!function_exists('getSettingValue')) {
    function getSettingValue($key) {
        $conn = getDBConnection();
        if (!$conn) {
            return null;
        }
        $stmt = $conn->prepare("SELECT setting_value FROM settings WHERE setting_key = ? LIMIT 1");
        if (!$stmt) {
            return null;
        }
        $stmt->bind_param('s', $key);
        $stmt->execute();
        $result = $stmt->get_result();
        $row = $result->fetch_assoc();
        return $row['setting_value'] ?? null;
    }
}



// Session start - moved from global scope

if (session_status() === PHP_SESSION_NONE) {

    session_start();

}



// Register shutdown function to close connection at end of script

register_shutdown_function('closeDBConnection');

?>