<?php

namespace App\Services;

use App\Models\Conversation;
use Illuminate\Support\Facades\Log;
use Exception;

class SynchronousImageGenerationService
{
    protected GoogleAiService $googleAi;
    protected int $delayBetweenImages = 3; // 3 seconds between images
    protected int $retryDelay = 3; // 3 seconds between retries
    protected int $maxRetries = 3;
    
    public function __construct(GoogleAiService $googleAi)
    {
        $this->googleAi = $googleAi;
    }
    
    /**
     * Process images synchronously one by one with proper delays and retries
     */
    public function processImagesSequentially(array $imageRequests, int $conversationId, int $userId): array
    {
        $results = [
            'completed' => [],
            'failed' => [],
            'total' => count($imageRequests),
            'success_count' => 0,
            'failure_count' => 0
        ];
        
        $conversation = Conversation::find($conversationId);
        
        Log::info("Starting synchronous image processing", [
            'conversation_id' => $conversationId,
            'total_images' => count($imageRequests),
            'delay_between_images' => $this->delayBetweenImages,
            'max_retries' => $this->maxRetries
        ]);
        
        foreach ($imageRequests as $index => $imageRequest) {
            $imageId = $imageRequest['id'];
            $prompt = $imageRequest['alt'];
            
            $currentImage = $index + 1;
            Log::info("Processing image {$currentImage}/{$results['total']}", [
                'image_id' => $imageId,
                'prompt' => substr($prompt, 0, 100) . (strlen($prompt) > 100 ? '...' : '')
            ]);
            
            // Clean prompt
            $cleanPrompt = $this->cleanImagePrompt($prompt);
            if (empty($cleanPrompt)) {
                Log::warning("Skipping image with empty prompt", ['image_id' => $imageId]);
                $results['failed'][$imageId] = 'Empty prompt after cleaning';
                $results['failure_count']++;
                continue;
            }
            
            // Process image with retries
            $imageResult = $this->processImageWithRetries($imageId, $cleanPrompt, $conversationId);
            
            if ($imageResult['success']) {
                $results['completed'][$imageId] = $imageResult;
                $results['success_count']++;
                
                // Update conversation
                if ($conversation) {
                    $generatedImages = $conversation->ai_responses['generated_images'] ?? [];
                    $generatedImages[$imageId] = [
                        'prompt' => $cleanPrompt,
                        'path' => $imageResult['image_path'],
                        'url' => $imageResult['image_url'],
                        'generated_at' => now()->toISOString(),
                        'retries_used' => $imageResult['retries_used'] ?? 0
                    ];
                    $conversation->updateAiResponse('generated_images', $generatedImages);
                }
                
                Log::info("Image processed successfully", [
                    'image_id' => $imageId,
                    'retries_used' => $imageResult['retries_used'] ?? 0
                ]);
            } else {
                $results['failed'][$imageId] = $imageResult['error'];
                $results['failure_count']++;
                
                Log::error("Image processing failed permanently", [
                    'image_id' => $imageId,
                    'error' => $imageResult['error'],
                    'retries_used' => $imageResult['retries_used'] ?? 0
                ]);
            }
            
            // Cache result for frontend polling
            $this->cacheImageResult($conversationId, $imageId, $imageResult);
            
            // Delay before next image (except for the last one)
            if ($index < count($imageRequests) - 1) {
                Log::info("Waiting {$this->delayBetweenImages} seconds before next image");
                sleep($this->delayBetweenImages);
            }
        }
        
        Log::info("Synchronous image processing completed", [
            'conversation_id' => $conversationId,
            'success_count' => $results['success_count'],
            'failure_count' => $results['failure_count'],
            'success_rate' => round(($results['success_count'] / $results['total']) * 100, 1) . '%'
        ]);
        
        return $results;
    }
    
    /**
     * Process single image with retry logic
     */
    protected function processImageWithRetries(string $imageId, string $prompt, int $conversationId): array
    {
        $lastError = '';
        
        for ($attempt = 1; $attempt <= $this->maxRetries; $attempt++) {
            Log::info("Image generation attempt {$attempt}/{$this->maxRetries}", [
                'image_id' => $imageId
            ]);
            
            try {
                $result = $this->googleAi->generateImage($prompt, $imageId);
                
                if ($result['success']) {
                    return array_merge($result, ['retries_used' => $attempt - 1]);
                } else {
                    $lastError = $result['error'];
                    Log::warning("Image generation attempt {$attempt} failed", [
                        'image_id' => $imageId,
                        'error' => $lastError
                    ]);
                }
                
            } catch (Exception $e) {
                $lastError = $e->getMessage();
                Log::warning("Image generation attempt {$attempt} exception", [
                    'image_id' => $imageId,
                    'error' => $lastError
                ]);
            }
            
            // Wait before retry (except for the last attempt)
            if ($attempt < $this->maxRetries) {
                Log::info("Waiting {$this->retryDelay} seconds before retry");
                sleep($this->retryDelay);
            }
        }
        
        return [
            'success' => false,
            'error' => $lastError,
            'image_id' => $imageId,
            'retries_used' => $this->maxRetries
        ];
    }
    
    /**
     * Cache image result for frontend polling
     */
    protected function cacheImageResult(int $conversationId, string $imageId, array $result): void
    {
        $eventData = [
            'conversation_id' => $conversationId,
            'image_id' => $imageId
        ];
        
        if ($result['success']) {
            $eventData = array_merge($eventData, [
                'type' => 'image_ready',
                'url' => $result['image_url'],
                'retries_used' => $result['retries_used'] ?? 0
            ]);
        } else {
            $eventData = array_merge($eventData, [
                'type' => 'image_error',
                'error' => $result['error'],
                'retries_used' => $result['retries_used'] ?? 0
            ]);
        }
        
        cache()->put(
            "image_event_{$conversationId}_{$imageId}",
            $eventData,
            300 // 5 minutes
        );
    }
    
    /**
     * Clean image prompt
     */
    protected function cleanImagePrompt(string $prompt): string
    {
        // Remove HTML tags
        $cleaned = strip_tags($prompt);
        
        // Remove extra whitespace
        $cleaned = preg_replace('/\s+/', ' ', $cleaned);
        
        // Trim
        $cleaned = trim($cleaned);
        
        // Minimum length check
        if (strlen($cleaned) < 3) {
            return '';
        }
        
        // Maximum length check
        if (strlen($cleaned) > 400) {
            $cleaned = substr($cleaned, 0, 400);
        }
        
        return $cleaned;
    }
}