<?php
/**
 * Lightweight SMS helper for Bangladeshi gateways (or test logging).
 * Usage:
 *   $res = sms_send($pdo, ['017XXXXXXXX'], 'Hello');
 */

function sms_config(): array {
    // Base from file
    $cfgPath = __DIR__ . '/../config/sms.php';
    $base = ['enabled'=>false, 'test_mode'=>true, 'templates'=>[]];
    if (file_exists($cfgPath)) {
        $fileCfg = require $cfgPath;
        if (is_array($fileCfg)) $base = array_merge($base, $fileCfg);
    }

    // Merge DB settings if available
    $dbCfg = sms_load_settings_db();
    $merged = array_merge($base, $dbCfg['scalar']);
    // Merge templates
    $merged['templates'] = array_merge($base['templates'] ?? [], $dbCfg['templates']);
    return $merged;
}

function sms_load_settings_db(): array {
    $result = ['scalar'=>[], 'templates'=>[]];
    try {
        if (!isset($GLOBALS['pdo'])) return $result;
        $pdo = $GLOBALS['pdo'];
        // Ensure settings table exists (best effort)
        $pdo->exec("CREATE TABLE IF NOT EXISTS settings (
            id INT PRIMARY KEY AUTO_INCREMENT,
            setting_key VARCHAR(100) UNIQUE,
            setting_value TEXT,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
            updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
        )");
        $keys = [
            'sms_enabled','sms_test_mode','sms_api_url','sms_api_key','sms_username','sms_password','sms_sender_id','sms_send_to_guardian'
        ];
        $tplKeys = [
            'sms_tpl_admission_success','sms_tpl_result_pass','sms_tpl_result_fail','sms_tpl_fee_payment','sms_tpl_fee_due_reminder','sms_tpl_bill_submission'
        ];
        $in = str_repeat('?,', count($keys)+count($tplKeys));
        $in = rtrim($in, ',');
        $stmt = $pdo->prepare("SELECT setting_key, setting_value FROM settings WHERE setting_key IN ($in)");
        $stmt->execute(array_merge($keys, $tplKeys));
        foreach ($stmt->fetchAll() as $row) {
            $k = $row['setting_key'];
            $v = $row['setting_value'];
            if ($k === 'sms_enabled' || $k === 'sms_test_mode' || $k === 'sms_send_to_guardian') {
                $result['scalar'][str_replace('sms_','',$k)] = in_array(strtolower((string)$v), ['1','true','yes','on'], true);
            } elseif (strpos($k, 'sms_tpl_') === 0) {
                $tplKey = substr($k, strlen('sms_tpl_'));
                $result['templates'][$tplKey] = $v;
            } else {
                // map scalar string keys removing prefix
                $result['scalar'][str_replace('sms_','',$k)] = $v;
            }
        }
    } catch (Throwable $e) {
        // ignore
    }
    return $result;
}

function sms_interpolate(string $template, array $vars): string {
    return preg_replace_callback('/\{([a-zA-Z0-9_]+)\}/', function($m) use ($vars) {
        return isset($vars[$m[1]]) ? (string)$vars[$m[1]] : $m[0];
    }, $template);
}

function sms_log(string $line): void {
    $cfg = sms_config();
    $log = $cfg['log_file'] ?? (__DIR__ . '/../backups/sms.log');
    $dir = dirname($log);
    if (!is_dir($dir)) @mkdir($dir, 0777, true);
    @file_put_contents($log, '['.date('Y-m-d H:i:s')."] ".$line."\n", FILE_APPEND | LOCK_EX);
}

function sms_normalize_number(?string $raw): ?string {
    if (!$raw) return null;
    $n = preg_replace('/\D+/', '', $raw);
    // Basic BD normalization: allow 01XXXXXXXXX or +8801XXXXXXXXX
    if (strpos($n, '880') === 0) {
        $n = '+'.$n;
    } elseif (strpos($n, '0') === 0) {
        $n = '+88'.$n;
    } elseif (strpos($n, '1') === 0 && strlen($n) === 10) {
        $n = '+880'.$n;
    } elseif (strpos($raw, '+') === 0) {
        // keep as-is
        $n = $raw;
    }
    return $n;
}

function sms_send($pdo, array $numbers, string $message, array $meta = []): array {
    $cfg = sms_config();

    // Filter/normalize numbers
    $to = array_values(array_unique(array_filter(array_map('sms_normalize_number', $numbers))));
    if (empty($to)) return ['success'=>false, 'message'=>'No valid numbers'];

    // When disabled or test mode: just log
    if (!($cfg['enabled'] ?? false) || ($cfg['test_mode'] ?? true)) {
        sms_log('TEST SEND to='.json_encode($to, JSON_UNESCAPED_UNICODE).' msg='. $message);
        return ['success'=>true, 'test_mode'=>true, 'to'=>$to];
    }

    $payload = [
        // Adapt these fields to your aggregator format
        'sender_id' => $cfg['sender_id'] ?? 'SCHOOL',
        'message'   => $message,
        'to'        => implode(',', $to),
        'type'      => 'text',
        'unicode'   => 1,
    ];

    // Add credentials if needed
    if (!empty($cfg['api_key']))    $payload['api_key'] = $cfg['api_key'];
    if (!empty($cfg['username']))   $payload['username'] = $cfg['username'];
    if (!empty($cfg['password']))   $payload['password'] = $cfg['password'];

    $tries = max(1, intval($cfg['retry'] ?? 1));
    $lastErr = null;
    for ($i=0; $i<$tries; $i++) {
        $ch = curl_init($cfg['api_url']);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, intval($cfg['timeout'] ?? 10));
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($payload));
        $resp = curl_exec($ch);
        $err  = curl_error($ch);
        $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        sms_log('SEND try='.($i+1).' code='.$code.' to='.json_encode($to, JSON_UNESCAPED_UNICODE).' resp='.substr((string)$resp,0,300));

        if (!$err && $code>=200 && $code<300) {
            return ['success'=>true, 'to'=>$to, 'response'=>$resp, 'http_code'=>$code];
        }
        $lastErr = $err ?: ('HTTP '.$code);
    }
    return ['success'=>false, 'message'=>'Gateway error: '.$lastErr];
}

function sms_send_template($pdo, string $templateKey, array $vars, array $numbers): array {
    $cfg = sms_config();
    $tpl = $cfg['templates'][$templateKey] ?? '';
    if (!$tpl) return ['success'=>false, 'message'=>'Template not found: '.$templateKey];
    $msg = sms_interpolate($tpl, $vars);
    return sms_send($pdo, $numbers, $msg, ['template'=>$templateKey]);
}

function non_musking_config(): array {
    // Load settings from database
    $result = ['enabled'=>false, 'method'=>'sms', 'templates'=>[]];
    try {
        if (!isset($GLOBALS['pdo'])) return $result;
        $pdo = $GLOBALS['pdo'];
        
        $keys = [
            'non_musking_enabled','non_musking_method','non_musking_api_url','non_musking_api_key','non_musking_username','non_musking_password','non_musking_sender_id'
        ];
        $tplKeys = [
            'non_musking_tpl_general_message',
            'non_musking_tpl_admission_confirmation',
            'non_musking_tpl_fee_payment'
        ];
        $in = str_repeat('?,', count($keys)+count($tplKeys));
        $in = rtrim($in, ',');
        $stmt = $pdo->prepare("SELECT setting_key, setting_value FROM settings WHERE setting_key IN ($in)");
        $stmt->execute(array_merge($keys, $tplKeys));
        foreach ($stmt->fetchAll() as $row) {
            $k = $row['setting_key'];
            $v = $row['setting_value'];
            if ($k === 'non_musking_enabled') {
                $result[str_replace('non_musking_','',$k)] = in_array(strtolower((string)$v), ['1','true','yes','on'], true);
            } elseif (strpos($k, 'non_musking_tpl_') === 0) {
                $tplKey = substr($k, strlen('non_musking_tpl_'));
                $result['templates'][$tplKey] = $v;
            } else {
                // map scalar string keys removing prefix
                $result[str_replace('non_musking_','',$k)] = $v;
            }
        }
    } catch (Throwable $e) {
        // ignore
    }
    return $result;
}

function non_musking_send($pdo, array $numbers, string $message, array $meta = []): array {
    $cfg = non_musking_config();

    // Filter/normalize numbers
    $to = array_values(array_unique(array_filter(array_map('sms_normalize_number', $numbers))));
    if (empty($to)) return ['success'=>false, 'message'=>'No valid numbers'];

    // Check if non-musking is enabled
    if (!($cfg['enabled'] ?? false)) {
        return ['success'=>false, 'message'=>'Non-musking messaging is not enabled'];
    }

    // Log the message for test purposes
    sms_log('NON-MUSKING SEND to='.json_encode($to, JSON_UNESCAPED_UNICODE).' msg='. $message);
    
    // Initialize delivery tracking
    $sent_recipients = [];
    $failed_recipients = [];
    $delivery_status = 'pending';
    $lastErrorMessage = null;
    
    // Prepare payload for MRAM API call
    $contacts = implode(',', $to);
    
    // Build the API URL with parameters for MRAM API
    $api_key = $cfg['api_key'] ?? '';
    $sender_id = $cfg['sender_id'] ?? 'SCHOOL';
    $message_encoded = urlencode($message);
    
    $apiUrl = "https://sms.mram.com.bd/smsapi?api_key={$api_key}&type=text&contacts={$contacts}&senderid={$sender_id}&msg={$message_encoded}&label=transactional";

    // Make API call to MRAM service
    $ch = curl_init($apiUrl);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Adjust as needed for security
    
    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $curlError = curl_error($ch);
    curl_close($ch);

    if ($curlError) {
        // Log the error
        sms_log('NON-MUSKING API ERROR: '. $curlError);
        
        // Mark all as failed
        $failed_recipients = $to;
        $delivery_status = 'failed';
        
        // Return specific error message
        return [
            'success' => false,
            'message' => 'cURL Error: ' . $curlError,
            'raw_response' => false,
            'http_code' => $httpCode
        ];
    } elseif ($response === false) {
        // cURL exec failed without specific error
        $failed_recipients = $to;
        $delivery_status = 'failed';
        
        // Return specific error message
        return [
            'success' => false,
            'message' => 'Failed to connect to SMS API endpoint. Please check API URL configuration.',
            'raw_response' => false,
            'http_code' => $httpCode
        ];
    } else {
        // Process MRAM API response
        // MRAM returns plain text response codes like '1001', '1008', etc.
        $responseStr = trim($response);
        
        // Log the response for debugging
        sms_log('MRAM API RESPONSE: '. $responseStr);
        
        // MRAM API response handling
        // 1001 = Success
        // 1008 = Accepted (queued for delivery)
        // Responses may include transaction IDs like 'bw-rdC300279169771f000c732'
        // Or formatted responses like 'SMS SUBMITTED: ID - bw-rdC30027916977218d7c6ed'
        // Other responses may include error messages
        $apiSuccess = false;
        
        // Check if response is a known success code
        if ($responseStr === '1001' || $responseStr === '1008') {
            $apiSuccess = true;
        } elseif (preg_match('/^[a-zA-Z0-9-]+$/', $responseStr) && strlen($responseStr) >= 10) {
            // If response looks like a transaction ID (alphanumeric with hyphens, case insensitive), consider it success
            $apiSuccess = true;
        } elseif (preg_match('/^SMS\s+SUBMITTED:\s+ID\s+-\s+[a-zA-Z0-9-]+$/', $responseStr)) {
            // If response is in format "SMS SUBMITTED: ID - <transaction_id>", consider it success
            $apiSuccess = true;
        } elseif (is_numeric($responseStr) && strlen($responseStr) <= 4) {
            // If it's a numeric error code (likely 4 digits or less), treat as error
            // But log it for debugging
            sms_log('MRAM API numeric error code: ' . $responseStr);
        } else {
            // If it's a non-numeric response, it might be an error message
            sms_log('MRAM API non-numeric response: ' . $responseStr);
        }
        
        
        if ($apiSuccess) {
            $sent_recipients = $to;
            $delivery_status = 'sent';
        } else {
            // Failed to send, mark all as failed
            $failed_recipients = $to;
            $delivery_status = 'failed';
            
            // Check for specific error codes
            if ($responseStr === '1016') {
                // Error 1016 means IP address is not whitelisted
                $errorMessage = 'IP Address not whitelisted in MRAM account. Contact MRAM to whitelist your IP address.';
            } else {
                $errorMessage = 'MRAM API Error Code: ' . $responseStr;
            }
            sms_log($errorMessage);
            
            // Store error message to include in result
            $lastErrorMessage = $errorMessage;
        }
    }
    
    // Determine overall status
    if (count($failed_recipients) === 0) {
        $delivery_status = 'sent'; // or 'delivered' if we get confirmation
    } elseif (count($sent_recipients) === 0) {
        $delivery_status = 'failed';
    } else {
        $delivery_status = 'partial';
    }
    
    // Log the message to database
    try {
        $stmt = $pdo->prepare(
            "INSERT INTO messages_log 
            (message_type, message_content, recipient_count, recipients, sent_recipients, failed_recipients, sender_id, status, method) 
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"
        );
        $stmt->execute([
            $meta['message_type'] ?? 'general',
            $message,
            count($to),
            json_encode($to),
            json_encode($sent_recipients),
            json_encode($failed_recipients),
            $_SESSION['user_id'] ?? null,
            $delivery_status,
            'non_musking'
        ]);
    } catch (Exception $e) {
        // Log error but continue
        error_log('Message logging error: ' . $e->getMessage());
    }
    
    // Determine final success and prepare result
    $finalSuccess = count($sent_recipients) > 0;
    
    $result = [
        'success' => $finalSuccess,
        'to' => $sent_recipients,
        'failed' => $failed_recipients,
        'method' => $cfg['method'],
        'total_count' => count($to),
        'sent_count' => count($sent_recipients),
        'failed_count' => count($failed_recipients),
        'raw_response' => $response ?? null
    ];
    
    // Add error message if there was a failure but no specific message
    if (!$finalSuccess) {
        if (isset($lastErrorMessage)) {
            $result['message'] = $lastErrorMessage;
        } elseif (count($failed_recipients) > 0) {
            $result['message'] = 'Failed to send SMS to ' . count($failed_recipients) . ' out of ' . count($to) . ' numbers';
        } else {
            $result['message'] = 'SMS sending failed with unknown reason';
        }
    }
    
    return $result;
}

function non_musking_send_template($pdo, string $templateKey, array $vars, array $numbers): array {
    $cfg = non_musking_config();
    $tpl = $cfg['templates'][$templateKey] ?? '';
    if (!$tpl) return ['success'=>false, 'message'=>'Template not found: '.$templateKey];
    $msg = sms_interpolate($tpl, $vars);
    return non_musking_send($pdo, $numbers, $msg, ['template'=>$templateKey]);
}

function update_message_delivery_status($pdo, $message_log_id, $status, $delivery_report = null) {
    try {
        $stmt = $pdo->prepare(
            "UPDATE messages_log 
            SET status = ?, delivery_report = ?, delivered_at = CURRENT_TIMESTAMP, updated_at = CURRENT_TIMESTAMP 
            WHERE id = ?"
        );
        $result = $stmt->execute([$status, $delivery_report, $message_log_id]);
        return $result;
    } catch (Exception $e) {
        error_log('Update message status error: ' . $e->getMessage());
        return false;
    }
}

function get_message_delivery_status($pdo, $message_log_id) {
    try {
        $stmt = $pdo->prepare("SELECT * FROM messages_log WHERE id = ?");
        $stmt->execute([$message_log_id]);
        return $stmt->fetch();
    } catch (Exception $e) {
        error_log('Get message status error: ' . $e->getMessage());
        return null;
    }
}