<?php
/**
 * ============================================================================
 * AIAssistant.php - Enhanced AI Assistant with Session Management
 * ============================================================================
 * Handles conversations with context, session tracking, and smart fallback
 */

namespace App;

class AIAssistant {
    private $db;
    private $openaiApiKey;
    private $model;
    private $maxTokens = 800; // Increased for better responses
    private $temperature = 0.7;
    private $timeout = 30;
    
    private static $knowledgeBase = null;
    
    public function __construct() {
        $this->db = Database::getInstance();
        $this->openaiApiKey = $_ENV['OPENAI_API_KEY'] ?? '';
        $this->model = $_ENV['OPENAI_MODEL'] ?? 'gpt-3.5-turbo';
    }
    
    /**
     * Main method to get AI response with session context
     */
    public function getResponse($message, $userId, $context = [], $sessionId = null) {
        try {
            // Validate input
            if (empty($message)) {
                throw new \Exception('Message cannot be empty');
            }
            
            if (strlen($message) > 2000) {
                throw new \Exception('Message too long. Maximum 2000 characters.');
            }
            
            // Generate or use existing session ID
            if (empty($sessionId)) {
                $sessionId = $this->generateSessionId($userId);
            }
            
            // Detect language
            $language = $this->detectLanguage($message);
            
            // Get conversation history for context
            $conversationHistory = $this->getSessionHistory($sessionId, 5); // Last 5 messages
            
            // Try OpenAI first if configured
            if ($this->isOpenAIConfigured()) {
                try {
                    error_log("Attempting OpenAI request for user: $userId");
                    
                    $response = $this->getOpenAIResponse(
                        $message, 
                        $language, 
                        $context, 
                        $conversationHistory
                    );
                    
                    error_log("OpenAI response received successfully");
                    
                    // Save conversation
                    $this->saveConversation(
                        $userId, 
                        $sessionId, 
                        $message, 
                        $response, 
                        $language, 
                        'openai'
                    );
                    
                    return [
                        'success' => true,
                        'response' => $response,
                        'language' => $language,
                        'source' => 'openai',
                        'session_id' => $sessionId,
                        'timestamp' => date('Y-m-d H:i:s')
                    ];
                    
                } catch (\Exception $e) {
                    error_log('OpenAI Error: ' . $e->getMessage());
                    error_log('OpenAI Error Details: ' . print_r($e, true));
                    // Fall through to rule-based
                }
            } else {
                error_log('OpenAI not configured - API key missing or invalid');
            }
            
            // Fallback to rule-based system
            $response = $this->getRuleBasedResponse($message, $language, $context);
            
            // Save conversation
            $this->saveConversation(
                $userId, 
                $sessionId, 
                $message, 
                $response, 
                $language, 
                'rule_based'
            );
            
            return [
                'success' => true,
                'response' => $response,
                'language' => $language,
                'source' => 'rule_based',
                'session_id' => $sessionId,
                'timestamp' => date('Y-m-d H:i:s')
            ];
            
        } catch (\Exception $e) {
            error_log('AI Assistant Error: ' . $e->getMessage());
            
            return [
                'success' => false,
                'message' => $e->getMessage(),
                'response' => $this->getErrorResponse($language ?? 'en'),
                'language' => $language ?? 'en',
                'source' => 'error',
                'session_id' => $sessionId ?? null,
                'timestamp' => date('Y-m-d H:i:s')
            ];
        }
    }
    
    /**
     * Generate a new session ID
     */
    private function generateSessionId($userId) {
        return 'session_' . $userId . '_' . time() . '_' . bin2hex(random_bytes(8));
    }
    
    /**
     * Get conversation history for a session
     */
    private function getSessionHistory($sessionId, $limit = 5) {
        try {
            $sql = "SELECT message, response, language 
                    FROM ai_conversations 
                    WHERE session_id = ? 
                    ORDER BY created_at DESC 
                    LIMIT ?";
            
            $history = $this->db->fetchAll($sql, [$sessionId, $limit]);
            return array_reverse($history); // Chronological order
            
        } catch (\Exception $e) {
            error_log('Error fetching session history: ' . $e->getMessage());
            return [];
        }
    }
    
    /**
     * Get all sessions for a user (for history sidebar)
     */
    public function getUserSessions($userId, $limit = 20) {
        try {
            $sql = "SELECT 
                        session_id,
                        MIN(created_at) as started_at,
                        MAX(created_at) as last_message_at,
                        COUNT(*) as message_count,
                        (SELECT message FROM ai_conversations ac2 
                         WHERE ac2.session_id = ac.session_id 
                         ORDER BY created_at ASC LIMIT 1) as first_message
                    FROM ai_conversations ac
                    WHERE user_id = ?
                    GROUP BY session_id
                    ORDER BY last_message_at DESC
                    LIMIT ?";
            
            return $this->db->fetchAll($sql, [$userId, $limit]);
            
        } catch (\Exception $e) {
            error_log('Error fetching user sessions: ' . $e->getMessage());
            return [];
        }
    }
    
    /**
     * Get all messages in a session
     */
    public function getSessionMessages($sessionId) {
        try {
            $sql = "SELECT * FROM ai_conversations 
                    WHERE session_id = ? 
                    ORDER BY created_at ASC";
            
            return $this->db->fetchAll($sql, [$sessionId]);
            
        } catch (\Exception $e) {
            error_log('Error fetching session messages: ' . $e->getMessage());
            return [];
        }
    }
    
    /**
     * Check if OpenAI is properly configured
     */
    private function isOpenAIConfigured() {
        $isConfigured = !empty($this->openaiApiKey) && 
                       $this->openaiApiKey !== 'your_openai_api_key' &&
                       strpos($this->openaiApiKey, 'sk-') === 0;
        
        error_log("OpenAI configured check: " . ($isConfigured ? 'YES' : 'NO'));
        error_log("API key starts with: " . substr($this->openaiApiKey, 0, 10) . '...');
        
        return $isConfigured;
    }
    
    /**
     * Get response from OpenAI API with conversation context
     */
    private function getOpenAIResponse($message, $language, $context, $conversationHistory = []) {
        $systemPrompt = $this->buildSystemPrompt($language, $context);
        
        // Build messages array with history
        $messages = [
            [
                'role' => 'system',
                'content' => $systemPrompt
            ]
        ];
        
        // Add conversation history for context
        foreach ($conversationHistory as $hist) {
            $messages[] = [
                'role' => 'user',
                'content' => $hist['message']
            ];
            $messages[] = [
                'role' => 'assistant',
                'content' => $hist['response']
            ];
        }
        
        // Add current message
        $messages[] = [
            'role' => 'user',
            'content' => $message
        ];
        
        $requestData = [
            'model' => $this->model,
            'messages' => $messages,
            'temperature' => $this->temperature,
            'max_tokens' => $this->maxTokens
        ];
        
        error_log("OpenAI Request Data: " . json_encode($requestData));
        
        // Make API request using cURL
        $ch = curl_init('https://api.openai.com/v1/chat/completions');
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => json_encode($requestData),
            CURLOPT_HTTPHEADER => [
                'Content-Type: application/json',
                'Authorization: Bearer ' . $this->openaiApiKey
            ],
            CURLOPT_TIMEOUT => $this->timeout,
            CURLOPT_SSL_VERIFYPEER => true
        ]);
        
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $curlError = curl_error($ch);
        curl_close($ch);
        
        error_log("OpenAI HTTP Code: $httpCode");
        
        if ($curlError) {
            error_log("cURL Error: $curlError");
            throw new \Exception('cURL Error: ' . $curlError);
        }
        
        if ($httpCode !== 200) {
            error_log("OpenAI API Error Response: $response");
            $errorData = json_decode($response, true);
            $errorMessage = $errorData['error']['message'] ?? 'Unknown API error';
            throw new \Exception('OpenAI API Error (HTTP ' . $httpCode . '): ' . $errorMessage);
        }
        
        $result = json_decode($response, true);
        
        if (!isset($result['choices'][0]['message']['content'])) {
            error_log("Invalid OpenAI response format: $response");
            throw new \Exception('Invalid API response format');
        }
        
        return trim($result['choices'][0]['message']['content']);
    }
    
    /**
     * Build system prompt for OpenAI
     */
    private function buildSystemPrompt($language, $context) {
        $basePrompt = "You are AIM AI, an intelligent agricultural assistant for farmers in Uganda, specifically in the Eastern region (Luuka District). ";
        
        if ($language === 'lusoga') {
            $basePrompt .= "You MUST respond ONLY in Lusoga language. Never use English in your responses.\n\n";
            $basePrompt .= "Oyamba mu:\n";
            $basePrompt .= "- Obulwadhe bw'ebirime n'ebisolo\n";
            $basePrompt .= "- Okusimba, okulima n'okungula\n";
            $basePrompt .= "- Emiwendo gy'ebintu mu bbabali\n";
            $basePrompt .= "- Okuzuukusa ettaka\n";
            $basePrompt .= "- Obudde n'okulima\n";
            $basePrompt .= "- Okufuga ebiwuka\n\n";
            $basePrompt .= "Waayo obwogezi obutuufu, obw'amagezi, era obunyangudde (200-400 words max).\n\n";
        } else {
            $basePrompt .= "Provide practical agricultural advice for Ugandan smallholder farmers.\n\n";
            $basePrompt .= "**Your Expertise:**\n";
            $basePrompt .= "- Crop diseases, pests, and treatments (maize, cassava, beans, vegetables)\n";
            $basePrompt .= "- Livestock management (poultry, cattle, goats)\n";
            $basePrompt .= "- Planting schedules for Uganda's climate\n";
            $basePrompt .= "- Market prices and selling strategies\n";
            $basePrompt .= "- Soil health and organic farming\n";
            $basePrompt .= "- Weather-smart agriculture\n\n";
            $basePrompt .= "**Guidelines:**\n";
            $basePrompt .= "- Keep responses concise (200-400 words)\n";
            $basePrompt .= "- Use simple, farmer-friendly language\n";
            $basePrompt .= "- Give specific recommendations with quantities and timing\n";
            $basePrompt .= "- Suggest affordable, locally available solutions\n";
            $basePrompt .= "- Include costs in Ugandan Shillings (UGX) when relevant\n";
            $basePrompt .= "- Use bullet points for steps and lists\n";
        }
        
        // Add user context
        if (!empty($context['location'])) {
            $basePrompt .= "\n**User Location:** " . $context['location'];
        }
        
        if (!empty($context['current_crops'])) {
            $crops = implode(', ', $context['current_crops']);
            $basePrompt .= "\n**User's Crops:** " . $crops;
        }
        
        return $basePrompt;
    }
    
    /**
     * Detect language (English or Lusoga)
     */
    private function detectLanguage($message) {
        $lusogaPatterns = [
            'obulwadhe', 'okusimba', 'okuzuukusa', 'amasimu', 'ebirime',
            'omwezi', 'ditya', 'bwa', 'ndobulaba', 'ndisima', 'gange',
            'muwogo', 'emmere', 'okungula', 'omusaija', 'omukazi',
            'ebikoola', 'emiggo', 'ettaka', 'enkuba', 'obudde',
            'obulo', 'kasooli', 'bikooge', 'nakati', 'ensigo',
            'wasuze', 'osiibiile', 'oli otya', 'webale', 'mwebale',
            'ditya', 'ndiyinza', 'osobola', 'kyenkana',
            'okuva', 'okugenda', 'okula', 'okwogera', 'okulaba',
            'nze', 'gwe', 'ye', 'ffe', 'mmwe', 'bo'
        ];
        
        $messageLower = mb_strtolower($message, 'UTF-8');
        
        $matches = 0;
        foreach ($lusogaPatterns as $pattern) {
            if (mb_strpos($messageLower, $pattern) !== false) {
                $matches++;
            }
        }
        
        return $matches >= 2 ? 'lusoga' : 'en';
    }
    
    /**
     * Get rule-based response (fallback)
     */
    private function getRuleBasedResponse($message, $language, $context) {
        $knowledgeBase = $this->getKnowledgeBase($language);
        $messageLower = mb_strtolower($message, 'UTF-8');
        
        foreach ($knowledgeBase as $pattern => $response) {
            if (preg_match($pattern, $messageLower)) {
                return $this->personalizeResponse($response, $context, $language);
            }
        }
        
        return $this->getDefaultResponse($language);
    }
    
    /**
     * Load knowledge base
     */
    private function getKnowledgeBase($language) {
        if (self::$knowledgeBase !== null && isset(self::$knowledgeBase[$language])) {
            return self::$knowledgeBase[$language];
        }
        
        if ($language === 'lusoga') {
            $kb = require __DIR__ . '/../config/knowledge-base-lusoga.php';
        } else {
            $kb = require __DIR__ . '/../config/knowledge-base-english.php';
        }
        
        self::$knowledgeBase[$language] = $kb;
        return $kb;
    }
    
    /**
     * Personalize response with user context
     */
    private function personalizeResponse($response, $context, $language) {
        if (!empty($context['location']) && strpos($response, 'Uganda') === false) {
            $suffix = $language === 'lusoga' 
                ? "\n\n*Ebyo bigwanidde " . htmlspecialchars($context['location']) . "*"
                : "\n\n*This applies to the " . htmlspecialchars($context['location']) . " region*";
            $response .= $suffix;
        }
        
        return $response;
    }
    
    /**
     * Get default response
     */
    private function getDefaultResponse($language) {
        if ($language === 'lusoga') {
            return "Nsonyiwa, simanyi bulungi ekyo. 🤔\n\n" .
                   "Ndiyinza okukuyamba mu:\n" .
                   "- **Obulwadhe bw'ebirime** (maize, muwogo, bikooge)\n" .
                   "- **Okusimba n'okungula** ebirime\n" .
                   "- **Emiwendo** gy'ebintu mu bbabali\n" .
                   "- **Okuzuukusa ettaka**\n" .
                   "- **Obudde** n'okulima\n" .
                   "- **Ebisolo** (enkoko, ente, embuzi)\n\n" .
                   "Buuza ekirungi era ekirambudde! 😊";
        } else {
            return "I'm here to help with agricultural questions! 😊\n\n" .
                   "I can assist you with:\n" .
                   "- **Crop Diseases & Pests**\n" .
                   "- **Planting Schedules**\n" .
                   "- **Market Prices**\n" .
                   "- **Soil Management**\n" .
                   "- **Weather & Climate**\n" .
                   "- **Livestock Care**\n\n" .
                   "Please ask a specific question about farming! 🌾";
        }
    }
    
    /**
     * Get error response
     */
    private function getErrorResponse($language) {
        if ($language === 'lusoga') {
            return "Nsonyiwa, waliwo ekizibu. Gezaako nate. 🙏";
        } else {
            return "Sorry, I encountered an error. Please try again. 🙏";
        }
    }
    
    /**
     * Save conversation to database
     */
    private function saveConversation($userId, $sessionId, $message, $response, $language, $source) {
        try {
            $sql = "INSERT INTO ai_conversations 
                    (user_id, session_id, message, response, language, source, created_at)
                    VALUES (?, ?, ?, ?, ?, ?, NOW())";
            
            $this->db->execute($sql, [
                $userId,
                $sessionId,
                $message,
                $response,
                $language,
                $source
            ]);
            
        } catch (\Exception $e) {
            error_log('Error saving AI conversation: ' . $e->getMessage());
        }
    }
    
    /**
     * Get conversation history (old method for compatibility)
     */
    public function getConversationHistory($userId, $limit = 20) {
        return $this->getUserSessions($userId, $limit);
    }
    
    /**
     * Clear conversation history for a user
     */
    public function clearHistory($userId) {
        try {
            $sql = "DELETE FROM ai_conversations WHERE user_id = ?";
            return $this->db->execute($sql, [$userId]);
        } catch (\Exception $e) {
            error_log('Error clearing conversation history: ' . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Get conversation statistics
     */
    public function getStats($userId) {
        try {
            $sql = "SELECT 
                        COUNT(DISTINCT session_id) as total_conversations,
                        COUNT(*) as total_messages,
                        SUM(CASE WHEN language = 'lusoga' THEN 1 ELSE 0 END) as lusoga_count,
                        SUM(CASE WHEN language = 'en' THEN 1 ELSE 0 END) as english_count,
                        SUM(CASE WHEN source = 'openai' THEN 1 ELSE 0 END) as openai_count,
                        SUM(CASE WHEN source = 'rule_based' THEN 1 ELSE 0 END) as rule_based_count,
                        MIN(created_at) as first_conversation,
                        MAX(created_at) as last_conversation
                    FROM ai_conversations 
                    WHERE user_id = ?";
            
            return $this->db->fetchOne($sql, [$userId]);
            
        } catch (\Exception $e) {
            error_log('Error fetching AI stats: ' . $e->getMessage());
            return null;
        }
    }
}