<?php

namespace App\Controllers;

use App\Core\Request;
use App\Core\Response;
use App\Models\WhatsAppSession;

/**
 * Handles WhatsApp Session Management and communicates with Baileys Node.js Gateway
 */
class WhatsAppController extends BaseController
{
    /**
     * Get the current WhatsApp connection status for the company
     */
    public function status(Request $request, Response $response)
    {
        $companyId = $request->company_id; // Added by AuthMiddleware
        $sessionId = $request->get('session_id') ?? null;
        
        if ($sessionId) {
            $session = WhatsAppSession::findSecure((int)$sessionId);
            if (!$session || (int)$session['company_id'] !== (int)$companyId) {
                $response->status(404)->json(['status' => 'error', 'message' => 'Session not found']);
                return;
            }
        } else {
            $session = WhatsAppSession::findOrCreate($companyId);
        }
        
        // Auto-heal logic: Check if the session is active in the Node.js gateway
        if ($session['status'] === 'connected' && !empty($session['session_key'])) {
            $gatewayUrl = rtrim(getenv('WHATSAPP_GATEWAY_URL') ?: 'http://localhost:3722', '/');
            if (substr($gatewayUrl, -4) === '/api') {
                $activeUrl = substr($gatewayUrl, 0, -4) . '/api/sessions/active';
            } else {
                $activeUrl = $gatewayUrl . '/api/sessions/active';
            }
            
            $ch = curl_init($activeUrl);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_TIMEOUT, 3);
            $res = curl_exec($ch);
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            curl_close($ch);
            
            $isActive = false;
            if ($httpCode === 200 && !empty($res)) {
                $resData = json_decode($res, true);
                if (isset($resData['active_sessions']) && is_array($resData['active_sessions'])) {
                    if (in_array($session['session_key'], $resData['active_sessions'])) {
                        $isActive = true;
                    }
                }
            }
            
            // If the DB says connected but the Gateway does not have it in memory, trigger auto-reconnect
            if (!$isActive) {
                error_log("[WhatsApp Auto-Heal] Session " . $session['session_key'] . " is not active in Gateway memory. Reconnecting...");
                
                $appUrl = rtrim(getenv('APP_URL') ?: 'https://nabeh.intaleqapp.com', '/');
                if (substr($gatewayUrl, -4) === '/api') {
                    $startUrl = substr($gatewayUrl, 0, -4) . '/api/sessions/start';
                } else {
                    $startUrl = $gatewayUrl . '/api/sessions/start';
                }
                
                $payload = json_encode([
                    'session_key' => $session['session_key'],
                    'webhook_url' => $appUrl . '/api/whatsapp/webhook'
                ]);
                
                $ch = curl_init($startUrl);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                curl_setopt($ch, CURLOPT_POST, true);
                curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
                curl_setopt($ch, CURLOPT_HTTPHEADER, [
                    'Content-Type: application/json',
                    'X-Webhook-Secret: ' . getenv('WEBHOOK_SECRET')
                ]);
                curl_setopt($ch, CURLOPT_TIMEOUT, 5);
                curl_exec($ch);
                curl_close($ch);
            }
        }
        
        // Strip sensitive/internal data before sending to frontend
        unset($session['phone_hash']);
        
        $response->json([
            'status' => 'success',
            'data' => $session
        ]);
    }

    /**
     * Get all WhatsApp sessions for the company
     */
    public function listSessions(Request $request, Response $response)
    {
        $companyId = $request->company_id;
        $sessions = WhatsAppSession::findAllByCompany($companyId);
        
        $activeSub = \App\Models\CompanySubscription::findActiveByCompany($companyId);
        $maxSessions = 1;
        if (isset($request->is_super_admin) && $request->is_super_admin) {
            $maxSessions = 999;
        } elseif ($activeSub) {
            $maxSessions = (int)$activeSub['max_sessions'];
        }
        
        $response->json([
            'status' => 'success',
            'data' => $sessions,
            'max_sessions' => $maxSessions
        ]);
    }

    /**
     * Create a new WhatsApp session
     */
    public function createSession(Request $request, Response $response)
    {
        $companyId = $request->company_id;
        $body = $request->getBody();
        $name = !empty($body['name']) ? trim($body['name']) : 'WhatsApp Team';

        // Fetch subscription limits
        $activeSub = \App\Models\CompanySubscription::findActiveByCompany($companyId);
        $maxSessions = 1;
        if (isset($request->is_super_admin) && $request->is_super_admin) {
            $maxSessions = 999; // Unlimited for Super Admin
        } elseif ($activeSub) {
            $maxSessions = (int)$activeSub['max_sessions'];
        }

        $sessions = WhatsAppSession::findAllByCompany($companyId);
        if (count($sessions) >= $maxSessions) {
            $response->status(400)->json([
                'status' => 'error',
                'message' => "You have reached the maximum number of WhatsApp sessions allowed by your plan ({$maxSessions})."
            ]);
            return;
        }

        $sessionKey = 'cmp_' . $companyId . '_' . bin2hex(random_bytes(4));
        $id = WhatsAppSession::create([
            'company_id' => $companyId,
            'name' => $name,
            'session_key' => $sessionKey,
            'status' => 'disconnected'
        ]);

        $newSession = WhatsAppSession::findSecure((int)$id);

        $response->json([
            'status' => 'success',
            'data' => $newSession
        ]);
    }

    /**
     * Delete an existing WhatsApp session
     */
    public function deleteSession(Request $request, Response $response)
    {
        $companyId = $request->company_id;
        $body = $request->getBody();
        $sessionId = $body['session_id'] ?? null;

        if (!$sessionId) {
            $response->status(400)->json(['status' => 'error', 'message' => 'Missing session_id']);
            return;
        }

        $session = WhatsAppSession::findSecure((int)$sessionId);
        if (!$session || (int)$session['company_id'] !== (int)$companyId) {
            $response->status(404)->json(['status' => 'error', 'message' => 'Session not found']);
            return;
        }

        // Call Baileys Node.js Service to delete session from memory
        $nodeUrl = 'http://127.0.0.1:3722/api/sessions/delete';
        $payload = json_encode(['session_key' => $session['session_key']]);
        
        $ch = curl_init($nodeUrl);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
            'X-Webhook-Secret: ' . getenv('WEBHOOK_SECRET')
        ]);
        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
        curl_exec($ch);
        curl_close($ch);

        WhatsAppSession::delete((int)$sessionId);

        $response->json(['status' => 'success', 'message' => 'Session deleted successfully']);
    }

    /**
     * Request a new connection/QR code from the Baileys service for a specific session
     */
    public function requestQr(Request $request, Response $response)
    {
        $companyId = $request->company_id;
        $body = $request->getBody();
        $sessionId = $body['session_id'] ?? null;

        if ($sessionId) {
            $session = WhatsAppSession::findSecure((int)$sessionId);
            if (!$session || (int)$session['company_id'] !== (int)$companyId) {
                $response->status(404)->json(['status' => 'error', 'message' => 'Session not found']);
                return;
            }
        } else {
            $session = WhatsAppSession::findOrCreate($companyId);
        }
        
        // Temporarily set to connecting
        WhatsAppSession::updateState($session['id'], ['status' => 'connecting']);
        
        // Call Baileys Node.js Service on port 3722
        $appUrl = rtrim(getenv('APP_URL') ?: 'https://nabeh.intaleqapp.com', '/');
        $nodeUrl = 'http://127.0.0.1:3722/api/sessions/start';
        $payload = json_encode([
            'session_key' => $session['session_key'],
            'webhook_url' => $appUrl . '/api/whatsapp/webhook'
        ]);
        
        $ch = curl_init($nodeUrl);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
            'X-Webhook-Secret: ' . getenv('WEBHOOK_SECRET')
        ]);
        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
        $result = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        
        // Note: Even if it fails immediately, the webhook will try to correct the state
        if ($httpCode >= 200 && $httpCode < 300) {
            $response->json([
                'status' => 'success',
                'message' => 'Connection requested. Please poll status to get QR code.'
            ]);
        } else {
            // Revert state on failure
            WhatsAppSession::updateState($session['id'], ['status' => 'disconnected']);
            $response->status(500)->json([
                'status' => 'error',
                'message' => 'Failed to reach WhatsApp Gateway.'
            ]);
        }
    }

    /**
     * Disconnect the WhatsApp session
     */
    public function disconnect(Request $request, Response $response)
    {
        $companyId = $request->company_id;
        $body = $request->getBody();
        $sessionId = $body['session_id'] ?? null;

        if ($sessionId) {
            $session = WhatsAppSession::findSecure((int)$sessionId);
            if (!$session || (int)$session['company_id'] !== (int)$companyId) {
                $response->status(404)->json(['status' => 'error', 'message' => 'Session not found']);
                return;
            }
        } else {
            $session = WhatsAppSession::findByCompany($companyId);
        }
        
        if ($session && $session['status'] !== 'disconnected') {
            // Call Baileys Node.js Service to disconnect
            $nodeUrl = 'http://127.0.0.1:3722/api/sessions/disconnect';
            $payload = json_encode(['session_key' => $session['session_key']]);
            
            $ch = curl_init($nodeUrl);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
            curl_setopt($ch, CURLOPT_HTTPHEADER, [
                'Content-Type: application/json',
                'X-Webhook-Secret: ' . getenv('WEBHOOK_SECRET')
            ]);
            curl_setopt($ch, CURLOPT_TIMEOUT, 5);
            curl_exec($ch);
            curl_close($ch);
            
            WhatsAppSession::updateState($session['id'], [
                'status' => 'disconnected',
                'qr_code' => null,
                'phone' => null,
                'phone_hash' => null
            ]);
        }
        
        $response->json(['status' => 'success', 'message' => 'Session disconnected']);
    }

    /**
     * Webhook called by Baileys Node.js server to sync state
     */
    public function webhook(Request $request, Response $response)
    {
        // Internal Security Check
        $secret = $request->getHeader('X-Webhook-Secret');
        if ($secret !== getenv('WEBHOOK_SECRET')) {
            $response->status(403)->json(['error' => 'Unauthorized webhook access']);
            return;
        }

        $body = $request->getBody();
        if (empty($body['session_key']) || empty($body['state'])) {
            $response->status(400)->json(['error' => 'Missing session_key or state']);
            return;
        }

        $session = WhatsAppSession::findBySessionKey($body['session_key']);
        
        if (!$session) {
            $response->status(404)->json(['error' => 'Session not found']);
            return;
        }

        // Handle message received events
        if ($body['state'] === 'message_received') {
            if (empty($body['message'])) {
                $response->status(400)->json(['error' => 'Missing message payload']);
                return;
            }
            
            $msgData = $body['message'];
            
            // 0. Check if this message has already been processed (deduplication)
            if (!empty($msgData['id'])) {
                $alreadyLogged = \App\Core\Database::selectOne(
                    "SELECT id FROM messages_log WHERE whatsapp_message_id = ? LIMIT 1",
                    [$msgData['id']]
                );
                if ($alreadyLogged) {
                    // Message already processed, return 200 immediately to prevent duplicate replies & DB errors
                    $response->status(200)->json([
                        'status' => 'success',
                        'message' => 'Message already processed (duplicate detected)'
                    ]);
                    return;
                }
            }
            
            // 1. Find or create the contact in the CRM
            $contact = \App\Models\Contact::findByPhone($session['company_id'], $msgData['phone']);
            if (!$contact) {
                // Determine a fallback name
                $contactName = !empty($msgData['name']) ? $msgData['name'] : 'WA-' . substr($msgData['phone'], -4);
                try {
                    \App\Models\Contact::createSecure([
                        'company_id' => $session['company_id'],
                        'name' => $contactName,
                        'phone' => $msgData['phone'],
                        'notes' => 'Auto-created via incoming WhatsApp message'
                    ]);
                } catch (\PDOException $e) {
                    // Ignore duplicate contact error if another thread created it concurrently
                    if ($e->getCode() !== '23000' && strpos($e->getMessage(), '1062') === false) {
                        throw $e;
                    }
                }
            }
            
            // 2. Log the incoming message in history log
            $isAudioMsg = !empty($msgData['audio']) && !empty($msgData['mimeType']);
            $isImageMsg = !empty($msgData['image']) && !empty($msgData['imageMimeType']);
            
            $msgType = 'text';
            if ($isAudioMsg) {
                $msgType = 'audio';
            } elseif ($isImageMsg) {
                $msgType = 'image';
            }
            
            $msgBody = $msgData['body'];
            if ($isAudioMsg) {
                $msgBody = $msgData['body'] ?: '[Voice Note]';
            } elseif ($isImageMsg) {
                $msgBody = $msgData['body'] ?: '[Image]';
            }

            \App\Models\MessageLog::logMessage([
                'company_id' => $session['company_id'],
                'session_id' => $session['id'],
                'contact_phone' => $msgData['phone'],
                'direction' => 'inbound',
                'message_type' => $msgType,
                'message_body' => $msgBody,
                'whatsapp_message_id' => $msgData['id'],
                'status' => 'read'
            ]);
            
            // 3. Placeholder for Phase 5 Gemini AI auto-reply
            if (function_exists('fastcgi_finish_request')) {
                $response->status(200);
                $response->setHeader('Content-Type', 'application/json; charset=utf-8');
                $allowedOrigin = getenv('ALLOWED_ORIGIN') ?: '*';
                $response->setHeader('Access-Control-Allow-Origin', $allowedOrigin);
                $response->setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
                $response->setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With');
                $response->sendHeaders();
                http_response_code(200);
                echo json_encode([
                    'status' => 'success',
                    'message' => 'Incoming message logged and auto-reply queued'
                ], JSON_UNESCAPED_UNICODE);
                fastcgi_finish_request();
                
                $this->triggerAutoReply($session, $msgData);
                exit;
            } else {
                // Fallback for environment without PHP-FPM
                $this->triggerAutoReply($session, $msgData);
                $response->json(['status' => 'success', 'message' => 'Incoming message logged']);
                return;
            }
        }

        // Handle connection state sync
        $updateData = [
            'status' => $body['state'] // 'waiting_qr', 'connected', 'disconnected'
        ];

        if ($body['state'] === 'waiting_qr' && !empty($body['qr_code'])) {
            $updateData['qr_code'] = $body['qr_code'];
        } elseif ($body['state'] === 'connected') {
            $updateData['qr_code'] = null; // Clear QR when connected
            if (!empty($body['phone'])) {
                // Anti-Abuse: Prevent Duplicate Phone Numbers Across Companies
                $existingPhoneSession = \App\Models\WhatsAppSession::findByPhone($body['phone']);
                if ($existingPhoneSession && (int)$existingPhoneSession['company_id'] !== (int)$session['company_id']) {
                    // This phone is already linked to another company! We must disconnect this malicious session.
                    $nodeUrl = 'http://127.0.0.1:3722/api/sessions/delete';
                    $payload = json_encode(['session_key' => $session['session_key']]);
                    $ch = curl_init($nodeUrl);
                    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                    curl_setopt($ch, CURLOPT_POST, true);
                    curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
                    curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
                    curl_exec($ch);
                    curl_close($ch);
                    
                    error_log("Anti-Abuse Block: Company ID {$session['company_id']} tried to link phone {$body['phone']} which is already linked to Company ID {$existingPhoneSession['company_id']}. Session disconnected.");
                    
                    $updateData['status'] = 'disconnected';
                    $updateData['qr_code'] = null;
                } else {
                    $updateData['phone'] = $body['phone'];
                }
            }
        } elseif ($body['state'] === 'disconnected') {
            $updateData['qr_code'] = null;
        }

        WhatsAppSession::updateState($session['id'], $updateData);

        $response->json(['status' => 'success']);
    }

    /**
     * Trigger Gemini AI Auto-Replies or Keyword rules (Phase 5)
     */
    private function triggerAutoReply(array $session, array $msgData)
    {
        try {
            // Hook the Conversation Flow Engine to intercept messages for active or new flows
            if (\App\Core\Flows\ConversationFlowEngine::processMessage($session, $msgData)) {
                return;
            }

            $rule = \App\Models\ChatbotRule::findActiveForRule($session['company_id'], $session['id']);
            if (!$rule || !$rule['is_active']) {
                return;
            }

            $incomingText = isset($msgData['body']) ? trim($msgData['body']) : '';
            $hasAudio = !empty($msgData['audio']) && !empty($msgData['mimeType']);
            $hasImage = !empty($msgData['image']) && !empty($msgData['imageMimeType']);

            if (empty($incomingText) && !$hasAudio && !$hasImage) {
                return;
            }

            $replyText = null;
            $replyAudio = null;
            $replyAudioMimeType = null;
            $usedElevenLabs = false;

            $companyId = $session['company_id'];
            $useElevenLabs = true;
            
            // Limit enforcement for non-admin companies (company 1 is admin/demo)
            if ($companyId !== 1) {
                $activeSub = \App\Models\CompanySubscription::findActiveByCompany($companyId);
                if (!$activeSub) {
                    error_log("[Chatbot Warning] Company {$companyId} has no active subscription.");
                    return;
                }
                
                // Check general request limit
                if (!\App\Models\CompanySubscriptionUsage::hasRemainingLimit($companyId, 'request')) {
                    error_log("[Chatbot Warning] Company {$companyId} has exceeded its general request limit.");
                    return;
                }
                
                // Check voice limit if input is audio to determine if we can use premium ElevenLabs
                if ($hasAudio && !\App\Models\CompanySubscriptionUsage::hasRemainingLimit($companyId, 'voice')) {
                    $useElevenLabs = false;
                }

                // Check if voice feature is enabled in subscription
                $features = json_decode($activeSub['features'] ?: '{}', true);
                if (isset($features['voice']) && !$features['voice']) {
                    $useElevenLabs = false;
                }
                
                // Check OCR limit if input is image
                if ($hasImage && !\App\Models\CompanySubscriptionUsage::hasRemainingLimit($companyId, 'ocr')) {
                    error_log("[Chatbot Warning] Company {$companyId} has exceeded its OCR/image request limit.");
                    $replyText = "⚠️ عذراً، لقد استهلك هذا المتجر الحد المسموح له من تحليل الصور والوصولات لهذا الشهر. يرجى إرسال استفسارك نصياً.";
                }
            }

            if ($replyText === null) {
                if ($rule['trigger_type'] === 'keyword') {
                    if (empty($incomingText)) {
                        return;
                    }
                    $keywords = array_filter(array_map('trim', explode(',', $rule['keyword'])));
                    $matched = false;
                    foreach ($keywords as $kw) {
                        if (mb_stripos($incomingText, $kw) !== false) {
                            $matched = true;
                            break;
                        }
                    }
                    if ($matched) {
                        $replyText = $rule['ai_prompt']; // Under keyword rules, ai_prompt stores the predefined static reply
                    }
                } elseif ($rule['trigger_type'] === 'gemini_ai') {
                    $configuredGeminiKey = ($rule && !empty($rule['gemini_api_key'])) ? $rule['gemini_api_key'] : null;
                    $apiKey = \App\Services\GeminiService::getGeminiApiKey($configuredGeminiKey);
                    
                    if (empty($apiKey)) {
                        error_log("[Chatbot Warning] Gemini API Key is not set globally or for company " . $session['company_id']);
                        return;
                    }

                    // Dynamically fetch customer/driver info from configured endpoints if set
                    $infoContext = "";
                    $infoEndpoint = \App\Models\CompanyEndpoint::findByAction($session['company_id'], 'fetch_user_info');
                    if ($infoEndpoint && !empty($msgData['phone'])) {
                        $infoContext = $this->fetchUserInfoFromEndpoint($infoEndpoint, $msgData['phone']);
                    }

                    // Dynamically fetch Salla order context if connected
                    $sallaContext = "";
                    if (!empty($msgData['phone'])) {
                        $sallaContext = $this->fetchSallaOrderContext($session['company_id'], $msgData['phone'], $incomingText);
                    }

                    // Dynamically fetch WooCommerce order context if connected
                    $wooContext = "";
                    if (!empty($msgData['phone'])) {
                        $wooContext = $this->fetchWooCommerceOrderContext($session['company_id'], $msgData['phone'], $incomingText);
                    }

                    $systemPrompt = $rule['ai_prompt'] ?: 'You are a helpful customer support assistant.';
                    
                    // Append real-time info context to Gemini system prompt
                    if (!empty($infoContext)) {
                        $systemPrompt .= "\n\n" . $infoContext;
                    }
                    if (!empty($sallaContext)) {
                        $systemPrompt .= "\n\n" . $sallaContext;
                    }
                    if (!empty($wooContext)) {
                        $systemPrompt .= "\n\n" . $wooContext;
                    }
                    
                    // Enforce language matching rule dynamically
                    $systemPrompt .= "\n\nIMPORTANT LANGUAGE RULE: Detect the language of the incoming message. If the incoming message is in English, you MUST reply in English. If the incoming message is in Arabic, you MUST reply in Arabic. Override any default language instruction to match the user's language.";
                    
                    if ($hasAudio) {
                        $duration = isset($msgData['duration']) ? intval($msgData['duration']) : null;
                        if ($duration !== null && $duration > 90) {
                            $replyText = "⚠️ عذراً، التسجيل الصوتي طويل جداً. يرجى إرسال تسجيل صوتي موجز (لا يتجاوز دقيقة واحدة) لتلخيص المشكلة لكي نتمكن من مساعدتك بشكل أفضل.";
                        } else {
                            $mimeType = $msgData['mimeType'];
                            if (strpos($mimeType, ';') !== false) {
                                $mimeType = trim(explode(';', $mimeType)[0]);
                            }
                            $configuredElKey = !empty($rule['elevenlabs_api_key']) ? $rule['elevenlabs_api_key'] : null;
                            $elApiKey = $useElevenLabs ? \App\Services\GeminiService::getElevenLabsApiKey($configuredElKey) : null;
                            
                            $configuredVoiceId = !empty($rule['elevenlabs_voice_id']) ? $rule['elevenlabs_voice_id'] : null;
                            $elVoiceId = $useElevenLabs ? \App\Services\GeminiService::getElevenLabsVoiceId($configuredVoiceId) : null;

                            // Try generating native audio response first
                            $audioResponse = \App\Services\GeminiService::generateAudioResponseFromAudio(
                                $apiKey,
                                $systemPrompt,
                                $msgData['audio'],
                                $mimeType,
                                'Puck',
                                $elApiKey,
                                $elVoiceId
                            );
                            if ($audioResponse && !empty($audioResponse['audio'])) {
                                $replyAudio = $audioResponse['audio'];
                                $replyAudioMimeType = $audioResponse['mimeType'] ?? 'audio/mp4';
                                $replyText = '[صوت من الذكاء الاصطناعي]';
                                if (!empty($elApiKey) && $replyAudioMimeType !== 'audio/mp3') {
                                    $usedElevenLabs = true;
                                }
                            } else {
                                // Fallback to text output from audio
                                $replyText = \App\Services\GeminiService::generateResponseFromAudio($apiKey, $systemPrompt, $msgData['audio'], $mimeType);
                            }
                        }
                    } elseif ($hasImage) {
                        $mimeType = $msgData['imageMimeType'];
                        if (strpos($mimeType, ';') !== false) {
                            $mimeType = trim(explode(';', $mimeType)[0]);
                        }
                        
                        // Prevent blind image processing outside of interactive flows to save OCR/Vision costs.
                        $replyText = "عذراً كابتن، يرجى إرسال الصور والمستندات فقط عندما يطلب منك النظام ذلك (مثلاً أثناء التسجيل عن طريق طباعة 'تسجيل' أو فحص الإيصالات بطباعة 'دفع').";
                    } else {
                        $replyText = \App\Services\GeminiService::generateResponse($apiKey, $systemPrompt, $incomingText);
                    }
                }
            }

            if (!empty($replyText) || !empty($replyAudio)) {
                // Check if the reply contains [PAYMENT_RECEIPT: { ... }] tag from Gemini
                if (!empty($replyText) && preg_match('/\[PAYMENT_RECEIPT:\s*(\{.*?\})\]/s', $replyText, $matches)) {
                    $jsonStr = $matches[1];
                    // Strip the tag from the final reply sent to user
                    $replyText = trim(str_replace($matches[0], '', $replyText));
                    
                    // Call the payment verification API (passing company_id)
                    $verificationResult = self::verifyPaymentSlipStatic($session['company_id'], $msgData['phone'], $jsonStr);
                    if ($verificationResult) {
                        $replyText .= "\n\n" . $verificationResult;
                    }
                }

                // Send reply back to the contact via Node.js Gateway
                $gatewayUrl = rtrim(getenv('WHATSAPP_GATEWAY_URL') ?: 'http://localhost:3722', '/');
                if (substr($gatewayUrl, -4) === '/api') {
                    $sendUrl = $gatewayUrl . '/messages/send';
                } else {
                    $sendUrl = $gatewayUrl . '/api/messages/send';
                }

                $payloadData = [
                    'session_key' => $session['session_key'],
                    'phone' => $msgData['phone']
                ];
                if (!empty($replyAudio)) {
                    $payloadData['audio'] = $replyAudio;
                    if (!empty($replyAudioMimeType)) {
                        $payloadData['mimetype'] = $replyAudioMimeType;
                    }
                } else {
                    $payloadData['message'] = $replyText;
                }
                $payload = json_encode($payloadData);

                $ch = curl_init($sendUrl);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                curl_setopt($ch, CURLOPT_POST, true);
                curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
                curl_setopt($ch, CURLOPT_HTTPHEADER, [
                    'Content-Type: application/json',
                    'X-Webhook-Secret: ' . getenv('WEBHOOK_SECRET')
                ]);
                curl_setopt($ch, CURLOPT_TIMEOUT, 10);
                
                $response = curl_exec($ch);
                $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                curl_close($ch);

                $status = 'failed';
                $errorMsg = null;
                $waMsgId = null;

                if ($httpCode === 200) {
                    $status = 'sent';
                    $resData = json_decode($response, true);
                    $waMsgId = $resData['data']['key']['id'] ?? null;
                } else {
                    $resData = json_decode($response, true);
                    $errorMsg = $resData['error'] ?? 'HTTP Code ' . $httpCode;
                    error_log("[Chatbot Gateway Error] failed to send auto-reply: " . $errorMsg);
                }

                // Increment SaaS usage stats if successfully sent
                if ($status === 'sent' && $companyId !== 1) {
                    \App\Models\CompanySubscriptionUsage::incrementUsage($companyId, 'request');
                    if ($usedElevenLabs) {
                        \App\Models\CompanySubscriptionUsage::incrementUsage($companyId, 'voice');
                    }
                    if ($hasImage) {
                        \App\Models\CompanySubscriptionUsage::incrementUsage($companyId, 'ocr');
                    }
                }

                // Log the outbound auto-reply message
                \App\Models\MessageLog::logMessage([
                    'company_id' => $session['company_id'],
                    'session_id' => $session['id'],
                    'contact_phone' => $msgData['phone'],
                    'direction' => 'outbound',
                    'message_type' => !empty($replyAudio) ? 'audio' : 'text',
                    'message_body' => $replyText,
                    'whatsapp_message_id' => $waMsgId,
                    'status' => $status,
                    'error_message' => $errorMsg
                ]);
            }
        } catch (\Exception $e) {
            error_log("[Chatbot Exception] Error: " . $e->getMessage() . " in " . $e->getFile() . ":" . $e->getLine());
        }
    }

    /**
     * Verify payment — sends data to payment server for AI verification or status query.
     *
     * Two modes:
     *   1. AI Verification (receiptImage given): sends phone + invoice_number + receipt_image
     *      to payment server, which runs GeminiAi::verifyPayment().
     *   2. Status Query (only jsonStr): parses {transaction_id, amount, method} from Gemini
     *      chatbot auto-detection, sends as status query to payment server.
     */
    public static function verifyPaymentSlipStatic(
        int $companyId,
        string $phone,
        string $jsonStr,
        string $userType = 'driver',
        string $paymentMethod = '',
        string $invoiceNumber = '',
        string $receiptImage = '',
        string $imageMimeType = 'image/jpeg'
    ): ?string
    {
        try {
            $apiUrl = getenv('PAYMENT_API_URL') ?: getenv('ENTALEQ_PAYMENT_API_URL');
            if (empty($apiUrl)) {
                $appUrl = rtrim(getenv('APP_URL') ?: 'https://nabeh.intaleqapp.com', '/');
                $apiUrl = $appUrl . '/api/external/verify-payment';
            }

            if (strpos($apiUrl, '/ride/nabeh/verify_payment.php') === false
                && strpos($apiUrl, '/api/external/verify-payment') === false) {
                $apiUrl = rtrim($apiUrl, '/') . '/ride/nabeh/verify_payment.php';
            }

            $apiKey = getenv('NABEH_API_KEY') ?: '';
            $headers = [
                'Content-Type: application/json',
                'X-API-Key: ' . $apiKey,
            ];

            // ── Mode 1: AI Verification (receipt image → auto-find invoice by phone) ──
            if (!empty($receiptImage)) {
                $payload = json_encode([
                    'phone' => $phone,
                    'payment_method' => $paymentMethod,
                    'receipt_image' => $receiptImage,
                    'image_mime_type' => $imageMimeType,
                ]);
            } else {
                // ── Mode 2: Status query from chatbot auto-detection ──────────────
                $data = json_decode($jsonStr, true);
                if (!$data) {
                    return null;
                }

                $transactionId = $data['transaction_id'] ?? '';
                $amount = $data['amount'] ?? '';
                $method = $data['method'] ?? $paymentMethod;

                if (empty($transactionId) && empty($amount) && empty($invoiceNumber)) {
                    return null;
                }

                $payload = json_encode([
                    'phone' => $phone,
                    'payment_method' => $method,
                    'transaction_id' => $transactionId,
                    'amount' => is_numeric($amount) ? (float) $amount : 0,
                    'invoice_number' => $invoiceNumber,
                ]);
            }

            $ch = curl_init($apiUrl);
            curl_setopt_array($ch, [
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_POST => true,
                CURLOPT_POSTFIELDS => $payload,
                CURLOPT_HTTPHEADER => $headers,
                CURLOPT_TIMEOUT => 30,
            ]);
            $response = curl_exec($ch);
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            curl_close($ch);

            if ($httpCode !== 200) {
                error_log("[PaymentVerify] HTTP $httpCode from $apiUrl: $response");
                return "⏳ تم استلام معلومات الدفع ويجري التحقق منها يدوياً. سنقوم بالرد فور الانتهاء.";
            }

            $resData = json_decode($response, true);
            if (!$resData) {
                return "⏳ تم استلام معلومات الدفع. يجري التحقق منها يدوياً.";
            }

            if (($resData['status'] ?? '') === 'success') {
                $verified = $resData['verified'] ?? false;
                if ($verified) {
                    return "✅ تم التحقق من عملية الدفع تلقائياً بنجاح!\n"
                        . "• تم تحديث رصيد حسابك.";
                }

                $reason = $resData['message']
                    ?? $resData['ai_reason']
                    ?? 'لم يتم التأكيد بعد';
                return "⚠️ " . $reason . "\n\nسيتم مراجعة العملية من قبل الإدارة والرد عليك قريباً.";
            }

            return "⏳ تم استلام معلومات الدفع. يجري التحقق منها يدوياً.";
        } catch (\Exception $e) {
            error_log("[PaymentVerify Exception] " . $e->getMessage());
            return "⏳ تم استلام معلومات الدفع. يجري التحقق منها يدوياً.";
        }
    }

    /**
     * Fetch user/driver info from external API endpoint configured by the company
     */
    private function fetchUserInfoFromEndpoint(array $endpoint, string $phone): string
    {
        try {
            $apiUrl = $endpoint['endpoint_url'];
            $payload = json_encode([
                'phone' => $phone
            ]);

            $headers = ['Content-Type: application/json'];
            if (!empty($endpoint['api_key'])) {
                $headers[] = 'X-API-Key: ' . $endpoint['api_key'];
                $headers[] = 'Authorization: Bearer ' . $endpoint['api_key'];
            }
            if (!empty($endpoint['headers'])) {
                $customHeaders = json_decode($endpoint['headers'], true);
                if (is_array($customHeaders)) {
                    foreach ($customHeaders as $key => $value) {
                        $headers[] = "$key: $value";
                    }
                }
            }

            $ch = curl_init($apiUrl);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
            curl_setopt($ch, CURLOPT_TIMEOUT, 5); // Short timeout to avoid blocking chatbot flow

            $response = curl_exec($ch);
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            curl_close($ch);

            if ($httpCode === 200 && !empty($response)) {
                return "\n\n[معلومات العميل المسترجعة من النظام الخارجي للمؤسسة:\n" . $response . "\nاستخدم هذه المعلومات للإجابة بدقة على أسئلة العميل المتعلقة بحسابه ورصيده وحالته]";
            }
        } catch (\Exception $e) {
            error_log("[Fetch User Info Exception] " . $e->getMessage());
        }
        return "";
    }

    /**
     * Fetch order info context from Salla e-commerce platform for the company
     */
    private function fetchSallaOrderContext(int $companyId, string $phone, string $incomingText): string
    {
        try {
            $accessToken = \App\Models\SallaMerchant::getOrRefreshAccessToken($companyId);
            if (!$accessToken) {
                return ""; // Salla is not integrated
            }

            // Standardize customer phone to compare last 9 digits
            $cleanPhone = preg_replace('/\D/', '', $phone);
            if (empty($cleanPhone)) {
                return "";
            }

            // 1. Check if user is asking about a specific order ID (e.g. sequence of 5-12 digits)
            if (preg_match('/\b(\d{5,12})\b/', $incomingText, $matches)) {
                $orderId = $matches[1];

                $ch = curl_init("https://api.salla.dev/admin/v2/orders/{$orderId}");
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                curl_setopt($ch, CURLOPT_HTTPHEADER, [
                    'Authorization: Bearer ' . $accessToken
                ]);
                curl_setopt($ch, CURLOPT_TIMEOUT, 8);
                $response = curl_exec($ch);
                $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                curl_close($ch);

                if ($httpCode === 200) {
                    $orderRes = json_decode($response, true);
                    $order = $orderRes['data'] ?? null;
                    if ($order) {
                        $orderCustPhone = preg_replace('/\D/', '', $order['customer']['mobile'] ?? $order['customer']['phone'] ?? '');
                        // Security check: match last 9 digits of WhatsApp phone to order customer phone
                        if (substr($orderCustPhone, -9) === substr($cleanPhone, -9)) {
                            $status = $order['status']['name'] ?? 'غير معروف';
                            $total = $order['amounts']['total']['amount'] ?? $order['total'] ?? '';
                            $currency = $order['amounts']['total']['currency'] ?? 'SAR';
                            $courier = $order['shipment']['courier_name'] ?? '';
                            $tracking = $order['shipment']['tracking_link'] ?? '';
                            $itemsCount = count($order['items'] ?? []);

                            $context = "\n\n[تفاصيل طلب سلة المستعلم عنه للعميل:\n";
                            $context .= "- رقم الطلب: {$orderId}\n";
                            $context .= "- حالة الطلب الحالية: {$status}\n";
                            $context .= "- إجمالي الطلب: {$total} {$currency}\n";
                            $context .= "- عدد المنتجات: {$itemsCount}\n";
                            if (!empty($courier)) {
                                $context .= "- شركة الشحن: {$courier}\n";
                            }
                            if (!empty($tracking)) {
                                $context .= "- رابط تتبع الشحنة: {$tracking}\n";
                            }
                            $context .= "الرجاء صياغة رد ودود ومختصر باللغة العربية لإخبار العميل بحالة هذا الطلب بالتحديد]";
                            return $context;
                        } else {
                            // Order ID exists but phone mismatch
                            return "\n\n[تنبيه أمني للذكاء الاصطناعي: العميل سأل عن الطلب رقم {$orderId} ولكن هذا الطلب مسجل برقم هاتف مختلف في سلة. لحماية الخصوصية والأمان، يمنع منعاً باتاً عرض تفاصيل هذا الطلب له. أخبر العميل بلطف أن رقم الهاتف الحالي لا يتطابق مع رقم الهاتف المسجل في تفاصيل هذا الطلب ولا يمكنك كشف تفاصيله]";
                        }
                    }
                }
            }

            // 2. Fetch list of recent orders for the merchant and search by customer phone number
            $ch = curl_init("https://api.salla.dev/admin/v2/orders?page=1");
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_HTTPHEADER, [
                'Authorization: Bearer ' . $accessToken
            ]);
            curl_setopt($ch, CURLOPT_TIMEOUT, 8);
            $response = curl_exec($ch);
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            curl_close($ch);

            if ($httpCode === 200) {
                $ordersRes = json_decode($response, true);
                $orders = $ordersRes['data'] ?? [];
                if (is_array($orders)) {
                    foreach ($orders as $order) {
                        $orderCustPhone = preg_replace('/\D/', '', $order['customer']['mobile'] ?? $order['customer']['phone'] ?? '');
                        if (substr($orderCustPhone, -9) === substr($cleanPhone, -9)) {
                            // Found the most recent order for this customer
                            $orderId = $order['id'] ?? $order['reference_id'] ?? '';
                            $status = $order['status']['name'] ?? 'غير معروف';
                            $total = $order['amounts']['total']['amount'] ?? $order['total'] ?? '';
                            $currency = $order['amounts']['total']['currency'] ?? 'SAR';
                            $courier = $order['shipment']['courier_name'] ?? '';
                            $tracking = $order['shipment']['tracking_link'] ?? '';
                            $itemsCount = count($order['items'] ?? []);

                            $context = "\n\n[آخر طلب للعميل في متجر سلة:\n";
                            $context .= "- رقم الطلب: {$orderId}\n";
                            $context .= "- حالة الطلب الحالية: {$status}\n";
                            $context .= "- إجمالي الطلب: {$total} {$currency}\n";
                            $context .= "- عدد المنتجات: {$itemsCount}\n";
                            if (!empty($courier)) {
                                $context .= "- شركة الشحن: {$courier}\n";
                            }
                            if (!empty($tracking)) {
                                $context .= "- رابط تتبع الشحنة: {$tracking}\n";
                            }
                            $context .= "الرجاء استخدام هذه التفاصيل للإجابة على استفساره حول حالة طلبه الأخير بدقة وود باللغة العربية]";
                            return $context;
                        }
                    }
                }
            }

            return "\n\n[سياق المتجر: العميل متصل بمتجر سلة ولكن لم يتم العثور على أي طلبات سابقة له برقم الهاتف هذا. أخبره بلطف أنه لا توجد طلبات سابقة مسجلة برقم هاتفه الحالي في المتجر، واطلب منه تزويدك برقم الطلب أو البريد الإلكتروني للبحث]";

        } catch (\Exception $e) {
            error_log("[Fetch Salla Order Exception] " . $e->getMessage());
        }
        return "";
    }

    /**
     * Fetch order info context from WooCommerce store for the company
     */
    private function fetchWooCommerceOrderContext(int $companyId, string $phone, string $incomingText): string
    {
        try {
            $store = \App\Models\WooCommerceStore::findByCompany($companyId);
            if (!$store) {
                return ""; // WooCommerce is not integrated
            }

            // Standardize customer phone to compare trailing digits
            $cleanPhone = preg_replace('/\D/', '', $phone);
            if (empty($cleanPhone)) {
                return "";
            }

            // 1. Check if user is asking about a specific order ID (e.g. sequence of 3-12 digits)
            if (preg_match('/\b(\d{3,12})\b/', $incomingText, $matches)) {
                $orderId = (int)$matches[1];

                $order = \App\Services\WooCommerceService::fetchOrder($store, $orderId, $phone);
                if ($order) {
                    if (isset($order['unauthorized']) && $order['unauthorized'] === true) {
                        return "\n\n[تنبيه أمني للذكاء الاصطناعي: العميل سأل عن الطلب رقم {$orderId} ولكن هذا الطلب مسجل برقم هاتف مختلف في WooCommerce. لحماية الخصوصية والأمان، يمنع منعاً باتاً عرض تفاصيل هذا الطلب له. أخبر العميل بلطف أن رقم الهاتف الحالي لا يتطابق مع رقم الهاتف المسجل في تفاصيل هذا الطلب ولا يمكنك كشف تفاصيله]";
                    }

                    $status = $order['status'] ?? 'غير معروف';
                    $translatedStatus = $this->translateStatus($status);
                    $total = $order['total'] ?? '';
                    $currency = $order['currency'] ?? 'SAR';
                    $itemsCount = count($order['line_items'] ?? []);

                    $context = "\n\n[تفاصيل طلب WooCommerce المستعلم عنه للعميل:\n";
                    $context .= "- رقم الطلب: {$orderId}\n";
                    $context .= "- حالة الطلب الحالية: {$translatedStatus}\n";
                    $context .= "- إجمالي الطلب: {$total} {$currency}\n";
                    $context .= "- عدد المنتجات: {$itemsCount}\n";
                    $context .= "الرجاء صياغة رد ودود ومختصر باللغة العربية لإخبار العميل بحالة هذا الطلب بالتحديد]";
                    return $context;
                }
            }

            // 2. Fetch list of recent orders for the merchant and search by customer phone number
            $orders = \App\Services\WooCommerceService::fetchRecentOrders($store, 30);
            if (is_array($orders)) {
                foreach ($orders as $order) {
                    $orderPhone = $order['billing']['phone'] ?? $order['shipping']['phone'] ?? '';
                    if (\App\Services\WooCommerceService::comparePhones($phone, $orderPhone)) {
                        // Found the most recent order for this customer
                        $orderId = $order['id'] ?? '';
                        $status = $order['status'] ?? 'غير معروف';
                        $translatedStatus = $this->translateStatus($status);
                        $total = $order['total'] ?? '';
                        $currency = $order['currency'] ?? 'SAR';
                        $itemsCount = count($order['line_items'] ?? []);

                        $context = "\n\n[آخر طلب للعميل في متجر WooCommerce:\n";
                        $context .= "- رقم الطلب: {$orderId}\n";
                        $context .= "- حالة الطلب الحالية: {$translatedStatus}\n";
                        $context .= "- إجمالي الطلب: {$total} {$currency}\n";
                        $context .= "- عدد المنتجات: {$itemsCount}\n";
                        $context .= "الرجاء استخدام هذه التفاصيل للإجابة على استفساره حول حالة طلبه الأخير بدقة وود باللغة العربية]";
                        return $context;
                    }
                }
            }

            return "\n\n[سياق المتجر: العميل متصل بمتجر WooCommerce ولكن لم يتم العثور على أي طلبات سابقة له برقم الهاتف هذا. أخبره بلطف أنه لا توجد طلبات سابقة مسجلة برقم هاتفه الحالي في المتجر، واطلب منه تزويدك برقم الطلب للبحث]";

        } catch (\Exception $e) {
            error_log("[Fetch WooCommerce Order Exception] " . $e->getMessage());
        }
        return "";
    }

    /**
     * Translate WooCommerce order status to Arabic
     */
    private function translateStatus(string $status): string
    {
        $translations = [
            'pending' => 'بانتظار الدفع',
            'processing' => 'قيد التجهيز',
            'on-hold' => 'قيد الانتظار',
            'completed' => 'مكتمل',
            'cancelled' => 'ملغي',
            'refunded' => 'مسترجع',
            'failed' => 'فشل الدفع',
            'checkout-draft' => 'مسودة السلة'
        ];

        return $translations[$status] ?? $status;
    }
}

