<?php
/**
 * BulkSMSDhaka SMS Service Class
 * 
 * Bulk SMS Dhaka API ব্যবহার করে এসএমএস পাঠানোর জন্য সেবা
 * API Documentation: https://bulksmsdhaka.net/bulk-sms-api-in-bangladesh
 */

class SMSService {
    
    private $apiKey;
    private $callerId;
    private $sendTextUrl = 'https://bulksmsdhaka.com/api/sendtext';
    private $sendOtpUrl = 'https://bulksmsdhaka.com/api/otpsend';
    private $getStatusUrl = 'https://bulksmsdhaka.com/api/getstatus';
    private $getBalanceUrl = 'https://bulksmsdhaka.com/api/getBalance';
    private $pdo;
    private $logPath;
    private $logToDatabase = true;
    
    /**
     * Constructor - SMS সেবা ইনিশিয়ালাইজ করুন
     * 
     * @param string $apiKey BulkSMSDhaka API Key
     * @param string $callerId Caller ID (ডিফল্ট: '1234')
     * @param PDO $pdo ডাটাবেস সংযোগ (ঐচ্ছিক)
     */
    public function __construct($apiKey, $callerId = '1234', PDO $pdo = null) {
        if (empty($apiKey)) {
            throw new Exception('API Key আবশ্যক');
        }
        
        $this->apiKey = $apiKey;
        $this->callerId = $callerId;
        $this->pdo = $pdo;
        
        // লগ ডিরেক্টরি সেট আপ করুন
        $this->logPath = dirname(__DIR__) . '/logs/sms/';
        if (!is_dir($this->logPath)) {
            @mkdir($this->logPath, 0755, true);
        }
    }
    
    /**
     * একটি বা একাধিক নম্বরে SMS পাঠান
     * 
     * @param mixed $numbers ফোন নম্বর (স্ট্রিং বা অ্যারে) - ফরম্যাট: 8801XXXXXXXXX বা 01XXXXXXXXX
     * @param string $message SMS বার্তা (UTF-8 এনকোডেড)
     * @param string $type 'text' বা 'otp' (ডিফল্ট: 'text')
     * @return array সাফল্য/ব্যর্থতা বিবরণ
     */
    public function send($numbers, $message, $type = 'text') {
        // ইনপুট ভ্যালিডেশন
        $numbers = $this->normalizeNumbers($numbers);
        
        if (empty($numbers)) {
            return $this->createResponse(false, 'কোনো বৈধ ফোন নম্বর নেই');
        }
        
        if (empty($message)) {
            return $this->createResponse(false, 'বার্তা খালি থাকতে পারে না');
        }
        
        $results = [];
        $urls = [];
        
        // URL তৈরি করুন
        foreach ($numbers as $number) {
            $url = $this->buildSmsUrl($number, $message, $type);
            $urls[$number] = $url;
        }
        
        // cURL সহ SMS পাঠান
        foreach ($urls as $number => $url) {
            $response = $this->makeApiCall($url);
            $results[$number] = $response;
            
            // ডাটাবেসে লগ সংরক্ষণ করুন
            if ($this->logToDatabase && $this->pdo) {
                $this->logSmsToDB($number, $message, $type, $response);
            }
            
            // ফাইলে লগ সংরক্ষণ করুন
            $this->logSmsToFile($number, $message, $type, $response);
        }
        
        return [
            'success' => count(array_filter($results)) > 0,
            'results' => $results,
            'timestamp' => date('Y-m-d H:i:s')
        ];
    }
    
    /**
     * স্টুডেন্টদের কাছে SMS পাঠান
     * 
     * @param array $studentIds স্টুডেন্ট IDs অ্যারে
     * @param string $message SMS বার্তা
     * @param bool $sendToGuardian গার্ডিয়ানকেও পাঠাবেন কিনা
     * @return array সাফল্য/ব্যর্থতা বিবরণ
     */
    public function sendToStudents($studentIds, $message, $sendToGuardian = true) {
        if (!$this->pdo) {
            return $this->createResponse(false, 'ডাটাবেস সংযোগ প্রয়োজন');
        }
        
        try {
            $placeholders = implode(',', array_fill(0, count($studentIds), '?'));
            
            if ($sendToGuardian) {
                // স্টুডেন্ট এবং গার্ডিয়ান উভয়ের ফোন নম্বর নিন
                $stmt = $this->pdo->prepare("
                    SELECT DISTINCT COALESCE(phone, guardian_phone) as phone, 
                           student_id, first_name
                    FROM students 
                    WHERE id IN ($placeholders)
                    AND (phone IS NOT NULL OR guardian_phone IS NOT NULL)
                ");
            } else {
                // শুধু স্টুডেন্টের ফোন নম্বর
                $stmt = $this->pdo->prepare("
                    SELECT DISTINCT phone, student_id, first_name
                    FROM students 
                    WHERE id IN ($placeholders)
                    AND phone IS NOT NULL
                ");
            }
            
            $stmt->execute($studentIds);
            $students = $stmt->fetchAll();
            
            if (empty($students)) {
                return $this->createResponse(false, 'কোনো স্টুডেন্ট খুঁজে পাওয়া যায়নি বা ফোন নম্বর নেই');
            }
            
            $numbers = array_column($students, 'phone');
            $result = $this->send($numbers, $message);
            
            // মেটাডেটা যোগ করুন
            $result['student_count'] = count($students);
            $result['students'] = $students;
            
            return $result;
            
        } catch (PDOException $e) {
            return $this->createResponse(false, 'ডাটাবেস ত্রুটি: ' . $e->getMessage());
        }
    }
    
    /**
     * নির্দিষ্ট ক্লাসের সকল স্টুডেন্টকে SMS পাঠান
     * 
     * @param int $classId ক্লাস ID
     * @param string $message SMS বার্তা
     * @param bool $sendToGuardian গার্ডিয়ানকেও পাঠাবেন কিনা
     * @return array সাফল্য/ব্যর্থতা বিবরণ
     */
    public function sendToClass($classId, $message, $sendToGuardian = true) {
        if (!$this->pdo) {
            return $this->createResponse(false, 'ডাটাবেস সংযোগ প্রয়োজন');
        }
        
        try {
            if ($sendToGuardian) {
                $stmt = $this->pdo->prepare("
                    SELECT DISTINCT COALESCE(phone, guardian_phone) as phone,
                           student_id, first_name
                    FROM students
                    WHERE class_id = ?
                    AND (phone IS NOT NULL OR guardian_phone IS NOT NULL)
                ");
            } else {
                $stmt = $this->pdo->prepare("
                    SELECT DISTINCT phone, student_id, first_name
                    FROM students
                    WHERE class_id = ?
                    AND phone IS NOT NULL
                ");
            }
            
            $stmt->execute([$classId]);
            $students = $stmt->fetchAll();
            
            if (empty($students)) {
                return $this->createResponse(false, 'এই ক্লাসে কোনো স্টুডেন্ট নেই বা ফোন নম্বর নেই');
            }
            
            $numbers = array_column($students, 'phone');
            $result = $this->send($numbers, $message);
            
            $result['class_id'] = $classId;
            $result['student_count'] = count($students);
            
            return $result;
            
        } catch (PDOException $e) {
            return $this->createResponse(false, 'ডাটাবেস ত্রুটি: ' . $e->getMessage());
        }
    }
    
    /**
     * API ভারসাম্য চেক করুন
     * 
     * @return array ব্যালেন্স তথ্য
     */
    public function getBalance() {
        $url = $this->getBalanceUrl . '?apikey=' . urlencode($this->apiKey);
        return $this->makeApiCall($url);
    }
    
    /**
     * SMS সরবরাহের স্থিতি চেক করুন
     * 
     * @param string $messageId API থেকে প্রাপ্ত Message ID
     * @return array স্থিতি তথ্য
     */
    public function getStatus($messageId) {
        $url = $this->getStatusUrl . '?apikey=' . urlencode($this->apiKey) . '&messageid=' . urlencode($messageId);
        return $this->makeApiCall($url);
    }
    
    /**
     * SMS URL তৈরি করুন
     * 
     * @param string $number ফোন নম্বর
     * @param string $message বার্তা
     * @param string $type SMS টাইপ
     * @return string সম্পূর্ণ URL
     */
    private function buildSmsUrl($number, $message, $type = 'text') {
        $url = ($type === 'otp') ? $this->sendOtpUrl : $this->sendTextUrl;
        
        // URL এনকোডিং সহ প্যারামিটার যোগ করুন
        $params = [
            'apikey' => $this->apiKey,
            'callerID' => $this->callerId,
            'number' => $number,
            'message' => $message
        ];
        
        $queryString = http_build_query($params);
        return $url . '?' . $queryString;
    }
    
    /**
     * cURL সহ API কলে ডেটা পাঠান
     * 
     * @param string $url পূর্ণ API URL
     * @return array API প্রতিক্রিয়া
     */
    private function makeApiCall($url) {
        try {
            $ch = curl_init();
            curl_setopt_array($ch, [
                CURLOPT_URL => $url,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_TIMEOUT => 30,
                CURLOPT_SSL_VERIFYPEER => true,
                CURLOPT_SSL_VERIFYHOST => 2,
                CURLOPT_FOLLOWLOCATION => true,
                CURLOPT_MAXREDIRS => 5
            ]);
            
            $response = curl_exec($ch);
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            $curlError = curl_error($ch);
            curl_close($ch);
            
            if ($curlError) {
                return [
                    'success' => false,
                    'error' => 'Network Error: ' . $curlError,
                    'http_code' => $httpCode
                ];
            }
            
            // JSON প্রতিক্রিয়া পার্স করুন
            $decoded = json_decode($response, true);
            
            if (json_last_error() !== JSON_ERROR_NONE) {
                // JSON ডিকোডিং ব্যর্থ হলে কাঁচা প্রতিক্রিয়া ফেরত দিন
                return [
                    'success' => ($httpCode === 200),
                    'response' => $response,
                    'http_code' => $httpCode
                ];
            }
            
            // স্ট্যাটাস কোড চেক করুন
            $statusCode = isset($decoded['Status']) ? $decoded['Status'] : null;
            $success = isset($decoded['Success']) ? $decoded['Success'] === 'true' : false;
            
            return [
                'success' => $success,
                'status_code' => $statusCode,
                'message' => $decoded['Message'] ?? $decoded['message'] ?? 'No message',
                'balance' => $decoded['Balance'] ?? null,
                'raw_response' => $decoded,
                'http_code' => $httpCode
            ];
            
        } catch (Exception $e) {
            return [
                'success' => false,
                'error' => 'Exception: ' . $e->getMessage()
            ];
        }
    }
    
    /**
     * ফোন নম্বর স্বাভাবিক করুন (বাংলাদেশী ফরম্যাট)
     * 
     * @param mixed $numbers ফোন নম্বর (স্ট্রিং বা অ্যারে)
     * @return array স্বাভাবিক ফোন নম্বর
     */
    private function normalizeNumbers($numbers) {
        $normalized = [];
        $numbers = is_array($numbers) ? $numbers : [$numbers];
        
        foreach ($numbers as $number) {
            $cleaned = preg_replace('/\D/', '', $number);
            
            // Bangladeshi format validation
            if (strlen($cleaned) === 11 && substr($cleaned, 0, 1) === '0') {
                // 01xxxxxxxxx to 8801xxxxxxxxx
                $cleaned = '88' . $cleaned;
            } elseif (strlen($cleaned) === 12 && substr($cleaned, 0, 2) === '88') {
                // Already in correct format
                $cleaned = $cleaned;
            } elseif (strlen($cleaned) === 10) {
                // 1xxxxxxxxx to 8801xxxxxxxxx
                $cleaned = '880' . $cleaned;
            } else {
                continue; // অবৈধ নম্বর
            }
            
            if (!in_array($cleaned, $normalized)) {
                $normalized[] = $cleaned;
            }
        }
        
        return $normalized;
    }
    
    /**
     * SMS লগ ডাটাবেসে সংরক্ষণ করুন
     * 
     * @param string $number ফোন নম্বর
     * @param string $message বার্তা
     * @param string $type SMS টাইপ
     * @param array $response API প্রতিক্রিয়া
     */
    private function logSmsToDB($number, $message, $type, $response) {
        try {
            $stmt = $this->pdo->prepare("
                INSERT INTO sms_logs (
                    phone_number, message, type, status, response,
                    api_status_code, created_at
                ) VALUES (?, ?, ?, ?, ?, ?, NOW())
            ");
            
            $stmt->execute([
                $number,
                $message,
                $type,
                $response['success'] ? 'sent' : 'failed',
                json_encode($response),
                $response['status_code'] ?? null
            ]);
        } catch (Exception $e) {
            // ডাটাবেস লগিং ব্যর্থ হলেও প্রক্রিয়া চলতে থাকে
            error_log('SMS DB Logging Error: ' . $e->getMessage());
        }
    }
    
    /**
     * SMS লগ ফাইলে সংরক্ষণ করুন
     * 
     * @param string $number ফোন নম্বর
     * @param string $message বার্তা
     * @param string $type SMS টাইপ
     * @param array $response API প্রতিক্রিয়া
     */
    private function logSmsToFile($number, $message, $type, $response) {
        try {
            $logFile = $this->logPath . date('Y-m-d') . '.log';
            
            $logEntry = [
                'timestamp' => date('Y-m-d H:i:s'),
                'phone_number' => $number,
                'message' => $message,
                'type' => $type,
                'success' => $response['success'],
                'status_code' => $response['status_code'] ?? null,
                'message' => $response['message'] ?? ''
            ];
            
            $logLine = json_encode($logEntry, JSON_UNESCAPED_UNICODE) . "\n";
            @file_put_contents($logFile, $logLine, FILE_APPEND | LOCK_EX);
        } catch (Exception $e) {
            // ফাইল লগিং ব্যর্থ হলেও প্রক্রিয়া চলতে থাকে
            error_log('SMS File Logging Error: ' . $e->getMessage());
        }
    }
    
    /**
     * রেসপন্স অ্যারে তৈরি করুন
     * 
     * @param bool $success সাফল্য স্থিতি
     * @param string $message বার্তা
     * @return array রেসপন্স
     */
    private function createResponse($success, $message) {
        return [
            'success' => $success,
            'message' => $message,
            'timestamp' => date('Y-m-d H:i:s')
        ];
    }
}
?>
