<?php

namespace App\Modules\Examples;

use App\Contracts\TelegramModuleInterface;
use App\Services\Core\ModuleManager;
use App\Services\Core\EventBus;
use App\Services\Core\ConfigurationManager;
use App\DTOs\TelegramUpdateDTO;
use App\Models\User;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;

/**
 * Example Advanced Module
 * 
 * This is an advanced example module that demonstrates more complex features
 * like state management, database interactions, caching, and advanced event handling.
 * 
 * Use this as a reference for building sophisticated modules.
 */
class ExampleAdvancedModule implements TelegramModuleInterface
{
    private ModuleManager $moduleManager;
    private EventBus $eventBus;
    private ConfigurationManager $configManager;
    private array $userStates = [];
    
    public function __construct(
        ModuleManager $moduleManager,
        EventBus $eventBus,
        ConfigurationManager $configManager
    ) {
        $this->moduleManager = $moduleManager;
        $this->eventBus = $eventBus;
        $this->configManager = $configManager;
    }

    public function getName(): string
    {
        return 'ExampleAdvancedModule';
    }

    public function getVersion(): string
    {
        return '2.0.0';
    }

    public function getDescription(): string
    {
        return 'An advanced example module with state management, caching, and complex workflows';
    }

    public function getHandledCommands(): array
    {
        return [
            '/survey',
            '/quiz',
            '/workflow',
            '/advanced',
            '/stats'
        ];
    }

    public function getDependencies(): array
    {
        return ['AnalyticsModule']; // Depends on analytics for tracking
    }

    public function handleUpdate(TelegramUpdateDTO $update): bool
    {
        if (!$update->getMessage()) {
            return $this->handleAdvancedTextInput($update);
        }

        $text = $update->getMessage()->getText();
        $chatId = $update->getMessage()->getChat()->getId();
        $userId = $update->getMessage()->getFrom()->getId();

        $user = $this->findOrCreateUser($update->getMessage()->getFrom());

        // Check if user is in a workflow state
        if ($this->isUserInWorkflow($userId)) {
            return $this->handleWorkflowInput($user, $text, $chatId);
        }

        switch ($text) {
            case '/survey':
                return $this->startSurvey($chatId, $user);
                
            case '/quiz':
                return $this->startQuiz($chatId, $user);
                
            case '/workflow':
                return $this->startWorkflow($chatId, $user);
                
            case '/advanced':
                return $this->showAdvancedFeatures($chatId, $user);
                
            case '/stats':
                return $this->showUserStats($chatId, $user);
                
            default:
                return false;
        }
    }

    public function handleCallback(TelegramUpdateDTO $update): bool
    {
        if (!$update->getCallbackQuery()) {
            return false;
        }

        $callbackData = $update->getCallbackQuery()->getData();
        $chatId = $update->getCallbackQuery()->getMessage()->getChat()->getId();
        $messageId = $update->getCallbackQuery()->getMessage()->getMessageId();
        $userId = $update->getCallbackQuery()->getFrom()->getId();

        $user = User::where('telegram_id', $userId)->first();
        if (!$user) {
            return false;
        }

        // Parse callback data
        $parts = explode('_', $callbackData);
        $action = $parts[0] ?? '';

        switch ($action) {
            case 'survey':
                return $this->handleSurveyCallback($parts, $chatId, $messageId, $user);
                
            case 'quiz':
                return $this->handleQuizCallback($parts, $chatId, $messageId, $user);
                
            case 'workflow':
                return $this->handleWorkflowCallback($parts, $chatId, $messageId, $user);
                
            case 'advanced':
                return $this->handleAdvancedCallback($parts, $chatId, $messageId, $user);
                
            default:
                return false;
        }
    }

    public function initialize(): bool
    {
        // Set up complex event listeners
        $this->eventBus->listen('user.survey_completed', [$this, 'onSurveyCompleted']);
        $this->eventBus->listen('user.quiz_completed', [$this, 'onQuizCompleted']);
        $this->eventBus->listen('user.workflow_step', [$this, 'onWorkflowStep']);
        $this->eventBus->listen('system.daily_reset', [$this, 'onDailyReset']);
        
        // Initialize module database tables if needed
        $this->initializeDatabase();
        
        // Load and cache frequently used data
        $this->loadCachedData();
        
        return true;
    }

    public function shutdown(): bool
    {
        // Clean up event listeners
        $this->eventBus->removeListener('user.survey_completed', [$this, 'onSurveyCompleted']);
        $this->eventBus->removeListener('user.quiz_completed', [$this, 'onQuizCompleted']);
        $this->eventBus->removeListener('user.workflow_step', [$this, 'onWorkflowStep']);
        $this->eventBus->removeListener('system.daily_reset', [$this, 'onDailyReset']);
        
        // Clear cached data
        Cache::forget('advanced_module_questions');
        Cache::forget('advanced_module_workflows');
        
        return true;
    }

    public function getStatus(): array
    {
        return [
            'name' => $this->getName(),
            'version' => $this->getVersion(),
            'enabled' => true,
            'initialized' => true,
            'active_workflows' => count($this->userStates),
            'cache_status' => Cache::has('advanced_module_questions') ? 'active' : 'inactive',
            'database_status' => $this->checkDatabaseStatus(),
        ];
    }

    /**
     * Start a survey workflow
     */
    private function startSurvey(int $chatId, User $user): bool
    {
        $questions = $this->getSurveyQuestions();
        
        if (empty($questions)) {
            $this->eventBus->dispatch('telegram.send_message', [
                'chat_id' => $chatId,
                'text' => 'Sorry, no survey questions are available right now.'
            ]);
            return true;
        }

        // Initialize user survey state
        $this->setUserState($user->telegram_id, [
            'type' => 'survey',
            'current_question' => 0,
            'answers' => [],
            'started_at' => now(),
            'questions' => $questions
        ]);

        $this->sendSurveyQuestion($chatId, $user, 0);
        return true;
    }

    /**
     * Start a quiz workflow
     */
    private function startQuiz(int $chatId, User $user): bool
    {
        $questions = $this->getQuizQuestions();
        
        if (empty($questions)) {
            $this->eventBus->dispatch('telegram.send_message', [
                'chat_id' => $chatId,
                'text' => 'Sorry, no quiz questions are available right now.'
            ]);
            return true;
        }

        // Check if user has already taken quiz today
        $cacheKey = "quiz_taken_{$user->telegram_id}_" . now()->format('Y-m-d');
        if (Cache::has($cacheKey)) {
            $this->eventBus->dispatch('telegram.send_message', [
                'chat_id' => $chatId,
                'text' => 'You have already taken the quiz today. Come back tomorrow!'
            ]);
            return true;
        }

        // Initialize user quiz state
        $this->setUserState($user->telegram_id, [
            'type' => 'quiz',
            'current_question' => 0,
            'correct_answers' => 0,
            'answers' => [],
            'started_at' => now(),
            'questions' => $questions
        ]);

        $this->sendQuizQuestion($chatId, $user, 0);
        return true;
    }

    /**
     * Start a complex workflow
     */
    private function startWorkflow(int $chatId, User $user): bool
    {
        $workflow = $this->getWorkflowDefinition('user_onboarding');
        
        $this->setUserState($user->telegram_id, [
            'type' => 'workflow',
            'workflow_id' => 'user_onboarding',
            'current_step' => 0,
            'data' => [],
            'started_at' => now(),
            'workflow' => $workflow
        ]);

        $this->executeWorkflowStep($chatId, $user, 0);
        return true;
    }

    /**
     * Handle workflow input from user
     */
    private function handleWorkflowInput(User $user, string $input, int $chatId): bool
    {
        $state = $this->getUserState($user->telegram_id);
        
        if (!$state) {
            return false;
        }

        switch ($state['type']) {
            case 'survey':
                return $this->processSurveyAnswer($user, $input, $chatId);
                
            case 'quiz':
                return $this->processQuizAnswer($user, $input, $chatId);
                
            case 'workflow':
                return $this->processWorkflowInput($user, $input, $chatId);
                
            default:
                return false;
        }
    }

    /**
     * Process survey answer
     */
    private function processSurveyAnswer(User $user, string $answer, int $chatId): bool
    {
        $state = $this->getUserState($user->telegram_id);
        $currentQuestion = $state['current_question'];
        
        // Store the answer
        $state['answers'][$currentQuestion] = $answer;
        
        // Move to next question or complete survey
        $nextQuestion = $currentQuestion + 1;
        
        if ($nextQuestion >= count($state['questions'])) {
            // Survey completed
            $this->completeSurvey($user, $state, $chatId);
        } else {
            // Continue to next question
            $state['current_question'] = $nextQuestion;
            $this->setUserState($user->telegram_id, $state);
            $this->sendSurveyQuestion($chatId, $user, $nextQuestion);
        }
        
        return true;
    }

    /**
     * Process quiz answer
     */
    private function processQuizAnswer(User $user, string $answer, int $chatId): bool
    {
        $state = $this->getUserState($user->telegram_id);
        $currentQuestion = $state['current_question'];
        $question = $state['questions'][$currentQuestion];
        
        // Check if answer is correct
        $isCorrect = strtolower(trim($answer)) === strtolower(trim($question['correct_answer']));
        
        if ($isCorrect) {
            $state['correct_answers']++;
        }
        
        $state['answers'][$currentQuestion] = [
            'answer' => $answer,
            'correct' => $isCorrect,
            'correct_answer' => $question['correct_answer']
        ];
        
        // Move to next question or complete quiz
        $nextQuestion = $currentQuestion + 1;
        
        if ($nextQuestion >= count($state['questions'])) {
            // Quiz completed
            $this->completeQuiz($user, $state, $chatId);
        } else {
            // Continue to next question
            $state['current_question'] = $nextQuestion;
            $this->setUserState($user->telegram_id, $state);
            $this->sendQuizQuestion($chatId, $user, $nextQuestion);
        }
        
        return true;
    }

    /**
     * Send survey question to user
     */
    private function sendSurveyQuestion(int $chatId, User $user, int $questionIndex): void
    {
        $state = $this->getUserState($user->telegram_id);
        $question = $state['questions'][$questionIndex];
        
        $message = "📝 **Survey Question " . ($questionIndex + 1) . "/" . count($state['questions']) . "**\n\n";
        $message .= $question['text'] . "\n\n";
        $message .= "Please type your answer:";
        
        $this->eventBus->dispatch('telegram.send_message', [
            'chat_id' => $chatId,
            'text' => $message,
            'parse_mode' => 'Markdown'
        ]);
    }

    /**
     * Send quiz question to user
     */
    private function sendQuizQuestion(int $chatId, User $user, int $questionIndex): void
    {
        $state = $this->getUserState($user->telegram_id);
        $question = $state['questions'][$questionIndex];
        
        $message = "🧠 **Quiz Question " . ($questionIndex + 1) . "/" . count($state['questions']) . "**\n\n";
        $message .= $question['text'] . "\n\n";
        
        if (!empty($question['options'])) {
            $message .= "Options:\n";
            foreach ($question['options'] as $index => $option) {
                $message .= chr(65 + $index) . ". $option\n";
            }
            $message .= "\nType the letter of your answer (A, B, C, etc.):";
        } else {
            $message .= "Please type your answer:";
        }
        
        $this->eventBus->dispatch('telegram.send_message', [
            'chat_id' => $chatId,
            'text' => $message,
            'parse_mode' => 'Markdown'
        ]);
    }

    /**
     * Complete survey and show results
     */
    private function completeSurvey(User $user, array $state, int $chatId): void
    {
        // Save survey results to database
        DB::table('user_surveys')->insert([
            'user_id' => $user->id,
            'survey_type' => 'general',
            'answers' => json_encode($state['answers']),
            'completed_at' => now(),
            'duration_seconds' => now()->diffInSeconds($state['started_at'])
        ]);
        
        $message = "🎉 **Survey Completed!**\n\n";
        $message .= "Thank you for completing our survey. Your responses have been recorded.\n\n";
        $message .= "Duration: " . now()->diffInMinutes($state['started_at']) . " minutes";
        
        $this->eventBus->dispatch('telegram.send_message', [
            'chat_id' => $chatId,
            'text' => $message,
            'parse_mode' => 'Markdown'
        ]);
        
        // Clear user state
        $this->clearUserState($user->telegram_id);
        
        // Trigger event
        $this->eventBus->dispatch('user.survey_completed', [
            'user_id' => $user->id,
            'survey_type' => 'general',
            'answers_count' => count($state['answers'])
        ]);
    }

    /**
     * Complete quiz and show results
     */
    private function completeQuiz(User $user, array $state, int $chatId): void
    {
        $totalQuestions = count($state['questions']);
        $correctAnswers = $state['correct_answers'];
        $score = ($correctAnswers / $totalQuestions) * 100;
        
        // Save quiz results
        DB::table('user_quiz_results')->insert([
            'user_id' => $user->id,
            'total_questions' => $totalQuestions,
            'correct_answers' => $correctAnswers,
            'score' => $score,
            'answers' => json_encode($state['answers']),
            'completed_at' => now(),
            'duration_seconds' => now()->diffInSeconds($state['started_at'])
        ]);
        
        $message = "🎯 **Quiz Completed!**\n\n";
        $message .= "Score: $correctAnswers/$totalQuestions (" . round($score, 1) . "%)\n\n";
        
        if ($score >= 80) {
            $message .= "🏆 Excellent work!";
        } elseif ($score >= 60) {
            $message .= "👍 Good job!";
        } else {
            $message .= "📚 Keep studying and try again tomorrow!";
        }
        
        $this->eventBus->dispatch('telegram.send_message', [
            'chat_id' => $chatId,
            'text' => $message,
            'parse_mode' => 'Markdown'
        ]);
        
        // Mark quiz as taken today
        $cacheKey = "quiz_taken_{$user->telegram_id}_" . now()->format('Y-m-d');
        Cache::put($cacheKey, true, now()->endOfDay());
        
        // Clear user state
        $this->clearUserState($user->telegram_id);
        
        // Trigger event
        $this->eventBus->dispatch('user.quiz_completed', [
            'user_id' => $user->id,
            'score' => $score,
            'correct_answers' => $correctAnswers,
            'total_questions' => $totalQuestions
        ]);
    }

    /**
     * User state management
     */
    private function setUserState(int $userId, array $state): void
    {
        $this->userStates[$userId] = $state;
        Cache::put("user_state_{$userId}", $state, now()->addHours(2));
    }
    
    private function getUserState(int $userId): ?array
    {
        if (isset($this->userStates[$userId])) {
            return $this->userStates[$userId];
        }
        
        return Cache::get("user_state_{$userId}");
    }
    
    private function clearUserState(int $userId): void
    {
        unset($this->userStates[$userId]);
        Cache::forget("user_state_{$userId}");
    }
    
    private function isUserInWorkflow(int $userId): bool
    {
        return $this->getUserState($userId) !== null;
    }

    /**
     * Get survey questions from cache or database
     */
    private function getSurveyQuestions(): array
    {
        return Cache::remember('survey_questions', now()->addHours(24), function () {
            return [
                ['text' => 'How would you rate our bot service?'],
                ['text' => 'What features would you like to see added?'],
                ['text' => 'How often do you use our bot?'],
                ['text' => 'Any additional comments or suggestions?']
            ];
        });
    }

    /**
     * Get quiz questions from cache or database
     */
    private function getQuizQuestions(): array
    {
        return Cache::remember('quiz_questions', now()->addHours(24), function () {
            return [
                [
                    'text' => 'What is the capital of Iran?',
                    'options' => ['Tehran', 'Isfahan', 'Shiraz', 'Mashhad'],
                    'correct_answer' => 'A'
                ],
                [
                    'text' => 'Which programming language is this bot written in?',
                    'options' => ['Python', 'PHP', 'JavaScript', 'Java'],
                    'correct_answer' => 'B'
                ],
                [
                    'text' => 'What framework does this bot use?',
                    'options' => ['Django', 'Laravel', 'Express', 'Spring'],
                    'correct_answer' => 'B'
                ]
            ];
        });
    }

    /**
     * Additional helper methods for database initialization, workflow handling, etc.
     */
    private function initializeDatabase(): void
    {
        // Initialize required database tables if they don't exist
        // This would typically be done through migrations
    }
    
    private function loadCachedData(): void
    {
        // Pre-load frequently accessed data into cache
        $this->getSurveyQuestions();
        $this->getQuizQuestions();
    }
    
    private function checkDatabaseStatus(): string
    {
        try {
            DB::connection()->getPdo();
            return 'connected';
        } catch (\Exception $e) {
            return 'disconnected';
        }
    }

    // Additional event handlers
    public function onSurveyCompleted(array $data): void
    {
        \Log::info('Survey completed', $data);
    }
    
    public function onQuizCompleted(array $data): void
    {
        \Log::info('Quiz completed', $data);
    }
    
    public function onWorkflowStep(array $data): void
    {
        \Log::info('Workflow step completed', $data);
    }
    
    public function onDailyReset(array $data): void
    {
        // Clear daily quiz cache
        $keys = Cache::getRedis()->keys('quiz_taken_*');
        foreach ($keys as $key) {
            Cache::forget($key);
        }
    }

    // Placeholder methods for workflow and advanced features
    private function getWorkflowDefinition(string $workflowId): array { return []; }
    private function executeWorkflowStep(int $chatId, User $user, int $step): bool { return true; }
    private function processWorkflowInput(User $user, string $input, int $chatId): bool { return true; }
    private function handleSurveyCallback(array $parts, int $chatId, int $messageId, User $user): bool { return true; }
    private function handleQuizCallback(array $parts, int $chatId, int $messageId, User $user): bool { return true; }
    private function handleWorkflowCallback(array $parts, int $chatId, int $messageId, User $user): bool { return true; }
    private function handleAdvancedCallback(array $parts, int $chatId, int $messageId, User $user): bool { return true; }
    private function showAdvancedFeatures(int $chatId, User $user): bool { return true; }
    private function showUserStats(int $chatId, User $user): bool { return true; }
    private function handleAdvancedTextInput(TelegramUpdateDTO $update): bool { return false; }
    private function findOrCreateUser($from): User { return new User(); }
}