<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);

set_time_limit(0);
ini_set('memory_limit', '-1');
date_default_timezone_set('Asia/Karachi');

$logFile = "/home/trustscoringco/logs/composeportalsinglAsc.log";

function logMsg($msg){
    global $logFile;
    $time = date("Y-m-d H:i:s");
    file_put_contents($logFile, "[$time] $msg\n", FILE_APPEND);
}

logMsg("========== SCRIPT STARTED ==========");

try {

    logMsg("Including config.php");
    include("config.php");

    if(!isset($connect)){
        logMsg("ERROR: MySQL connection variable \$connect not found.");
        exit;
    }

    if(mysqli_connect_errno()){
        logMsg("ERROR: MySQL connection failed: " . mysqli_connect_error());
        exit;
    }

    logMsg("MySQL connected successfully.");

    logMsg("Including functions.php");
    include("functions.php");

    logMsg("Loading cron settings.");

    // --- Cron time check ---
    $q1 = mysqli_query($connect,"SELECT value FROM settings_portal_dsc WHERE name='Cron_start'");
    if(!$q1){
        logMsg("ERROR fetching Cron_start: " . mysqli_error($connect));
        exit;
    }

    $cronStart = mysqli_fetch_array($q1)['value'];

    $q2 = mysqli_query($connect,"SELECT value FROM settings_portal_dsc WHERE name='Cron_stop'");
    if(!$q2){
        logMsg("ERROR fetching Cron_stop: " . mysqli_error($connect));
        exit;
    }

    $cronStop = mysqli_fetch_array($q2)['value'];

    $currentTime = date("H:i");

    logMsg("Current Time: $currentTime | Allowed: $cronStart - $cronStop");

    if($currentTime < date("H:i", strtotime($cronStart)) || $currentTime > date("H:i", strtotime($cronStop))){
        logMsg("Cron outside allowed hours. Exiting.");
        exit;
    }

    // --- Check API_CRON lock ---
    logMsg("Checking API_CRON lock.");

    $q3 = mysqli_query($connect,"SELECT value FROM settings_portal_dsc WHERE id=6");

    if(!$q3){
        logMsg("ERROR fetching API_CRON: " . mysqli_error($connect));
        exit;
    }

    $apiCron = mysqli_fetch_array($q3)['value'];

    logMsg("API_CRON status: $apiCron");

    if($apiCron !== "Unlocked"){
        logMsg("API_CRON locked. Exiting.");
        exit;
    }

    // Lock cron
    logMsg("Locking cron.");

    $lockQuery = mysqli_query($connect,"UPDATE settings_portal_dsc SET value='Locked', locked_at=NOW() WHERE id=6");

    if(!$lockQuery){
        logMsg("ERROR locking cron: " . mysqli_error($connect));
        exit;
    }

    logMsg("Cron locked successfully.");

    // --- Load SMS settings ---
    logMsg("Loading SMS settings.");

    $sms_per_sec = (int) mysqli_fetch_array(mysqli_query($connect,"SELECT value FROM settings_portal_dsc WHERE name='SMS_PER_SECOND'"))['value'];

    $sms_wait_sec = (int) mysqli_fetch_array(mysqli_query($connect,"SELECT value FROM settings_portal_dsc WHERE name='SMS_WAIT_TIME'"))['value'];

    $sms_force_off = (int) mysqli_fetch_array(mysqli_query($connect,"SELECT value FROM settings_portal_dsc WHERE name='SMS_FORCE_OFF'"))['value'];

    logMsg("SMS_PER_SECOND: $sms_per_sec");
    logMsg("SMS_WAIT_TIME: $sms_wait_sec");
    logMsg("SMS_FORCE_OFF: $sms_force_off");

    if($sms_force_off === 1){
        logMsg("SMS_FORCE_OFF enabled. Exiting.");
        exit;
    }

    // --- Main loop ---
    logMsg("Entering main processing loop.");

    while(true){

        logMsg("Fetching pending SMS batch.");

        $query = "SELECT * FROM compose_portal_single WHERE sms_status='Pending' ORDER BY id ASC LIMIT $sms_per_sec";

        $res = mysqli_query($connect,$query);

        if(!$res){
            logMsg("ERROR fetching pending SMS: " . mysqli_error($connect));
            break;
        }

        $numRows = mysqli_num_rows($res);

        logMsg("Pending SMS fetched: $numRows");

        if($numRows == 0){
            logMsg("No pending SMS found. Exiting loop.");
            break;
        }

        $smsBatch = [];

        while($row = mysqli_fetch_assoc($res)){
            $smsBatch[$row['id']] = $row;
        }

        logMsg("Batch prepared. Total: " . count($smsBatch));

        // --- Prepare multi-curl ---
        $mh = curl_multi_init();
        $handles = [];

        foreach($smsBatch as $id => $sms){

            logMsg("Preparing SMS ID: $id | Network: ".$sms['networkname']);

            $ch = curl_init();

            if(strtolower($sms['networkname']) === 'smpp' && !empty($sms['smpp_url'])){

                $url = $sms['smpp_url'] .
                    "?username={$sms['api_username']}" .
                    "&password={$sms['api_password']}" .
                    "&from={$sms['mask_name']}" .
                    "&to={$sms['mobile_number']}" .
                    "&text=" . urlencode($sms['message']);

                logMsg("SMS ID $id SMPP URL: $url");

                curl_setopt($ch, CURLOPT_URL, $url);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                curl_setopt($ch, CURLOPT_TIMEOUT, 30);
                curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);

            } else {

                logMsg("SMS ID $id marked for local function processing.");

                $smsBatch[$id]['call_func'] = true;
                continue;
            }

            curl_multi_add_handle($mh, $ch);
            $handles[$id] = $ch;
        }

        // --- Execute curl ---
        if(!empty($handles)){

            logMsg("Executing curl multi batch. Handles: ".count($handles));

            do {

                $status = curl_multi_exec($mh, $active);

                if($status > 0){
                    logMsg("curl_multi_exec error: " . curl_multi_strerror($status));
                }

                curl_multi_select($mh);

            } while ($active && $status == CURLM_OK);

            logMsg("curl multi execution completed.");

            foreach($handles as $id => $ch){

                $response = curl_multi_getcontent($ch);

                $curlError = curl_error($ch);

                $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

                logMsg("SMS ID $id HTTP Code: $httpCode");

                if($curlError){
                    logMsg("SMS ID $id CURL ERROR: $curlError");
                }

                curl_multi_remove_handle($mh, $ch);

                $update = mysqli_query(
                    $connect,
                    "UPDATE compose_portal_single 
                     SET telecom_response='".mysqli_real_escape_string($connect,$response)."',
                         sms_status='Sent'
                     WHERE id=$id"
                );

                if(!$update){
                    logMsg("ERROR updating SMS ID $id: " . mysqli_error($connect));
                } else {
                    logMsg("SMS ID $id updated successfully.");
                }

                logMsg("SMS ID $id SMPP Response: $response");
            }

            curl_multi_close($mh);

            logMsg("curl multi handles closed.");
        }

        // --- Process local functions ---
        foreach($smsBatch as $id => $sms){

            if(empty($sms['call_func'])){
                continue;
            }

            $network = strtolower($sms['networkname']);

            logMsg("Processing SMS ID $id using local function: $network");

            $response = '';

            try {

                switch($network){

                    case 'mobilinkbiz':

                        logMsg("Calling Mobilinkbiz function for SMS ID $id");

                        if($sms['message_actuall_response'] === 'yes'){
                            $response = Mobilinkbizme(
                                "compose_portal_single",
                                "telecom_response",
                                $sms['api_username'],
                                $sms['api_password'],
                                $sms['api_unicode'],
                                $sms['mask_name'],
                                $sms['mobile_number'],
                                $sms['message'],
                                $id
                            );
                        } else {
                            $response = Mobilinkbiz(
                                "compose_portal_single",
                                "telecom_response",
                                $sms['api_username'],
                                $sms['api_password'],
                                $sms['api_unicode'],
                                $sms['mask_name'],
                                $sms['mobile_number'],
                                $sms['message'],
                                $id
                            );
                        }

                    break;

                    case 'mobilink':

                        logMsg("Calling Mobilink function for SMS ID $id");

                        if($sms['message_actuall_response'] === 'yes'){
                            $response = Mobilinkme(
                                "compose_portal_single",
                                "telecom_response",
                                $sms['api_username'],
                                $sms['api_password'],
                                $sms['api_unicode'],
                                $sms['mask_name'],
                                $sms['mobile_number'],
                                $sms['message'],
                                $id
                            );
                        } else {
                            $response = Mobilink(
                                "compose_portal_single",
                                "telecom_response",
                                $sms['api_username'],
                                $sms['api_password'],
                                $sms['api_unicode'],
                                $sms['mask_name'],
                                $sms['mobile_number'],
                                $sms['message'],
                                $id
                            );
                        }

                    break;

                    case 'ufone':

                        logMsg("Calling Ufone function for SMS ID $id");

                        $response = Ufone(
                            "compose_portal_single",
                            "telecom_response",
                            $sms['api_username'],
                            $sms['api_password'],
                            $sms['api_unicode'],
                            $sms['mask_name'],
                            $sms['mobile_number'],
                            $sms['message'],
                            $id
                        );

                    break;

                    case 'telenor':

                        logMsg("Calling Telenor function for SMS ID $id");

                        $response = Telenor(
                            "compose_portal_single",
                            "telecom_response",
                            $sms['api_username'],
                            $sms['api_password'],
                            $sms['api_unicode'],
                            $sms['mask_name'],
                            $sms['mobile_number'],
                            $sms['message'],
                            $id
                        );

                    break;

                    case 'zong':

                        logMsg("Calling Zong function for SMS ID $id");

                        $response = Zong(
                            "compose_portal_single",
                            "telecom_response",
                            $sms['api_username'],
                            $sms['api_password'],
                            $sms['api_unicode'],
                            $sms['mask_name'],
                            $sms['mobile_number'],
                            $sms['message'],
                            $id
                        );

                    break;

                    default:

                        logMsg("Unknown network for SMS ID $id");

                        $response = 'Unknown network';
                }

                $update = mysqli_query(
                    $connect,
                    "UPDATE compose_portal_single
                     SET telecom_response='".mysqli_real_escape_string($connect,$response)."',
                         sms_status='Sent'
                     WHERE id=$id"
                );

                if(!$update){
                    logMsg("ERROR updating SMS ID $id after local function: " . mysqli_error($connect));
                }

                logMsg("SMS ID $id processed successfully. Response: $response");

            } catch(Exception $e){

                logMsg("EXCEPTION for SMS ID $id : ".$e->getMessage());

            } catch(Error $e){

                logMsg("FATAL ERROR for SMS ID $id : ".$e->getMessage());

            }
        }

        logMsg("Sleeping for $sms_wait_sec microseconds.");

        usleep($sms_wait_sec);
    }

} catch(Exception $e){

    logMsg("GLOBAL EXCEPTION: ".$e->getMessage());

} catch(Error $e){

    logMsg("GLOBAL FATAL ERROR: ".$e->getMessage());

}

// --- Unlock cron ---
logMsg("Unlocking cron.");

mysqli_query($connect,"UPDATE settings_portal_dsc SET value='Unlocked', locked_at=NOW() WHERE id=6");

logMsg("Cron unlocked.");

logMsg("========== SCRIPT ENDED ==========");

exit;
