<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class ListAvailableModels extends Command
{
    protected $signature = 'list:available-models 
                          {--test-model= : Test a specific model}';
    
    protected $description = 'List available Google AI models for image generation';

    public function handle()
    {
        $this->info('🔍 Checking Available Google AI Models');
        $this->newLine();

        $apiKey = config('google.api_key');
        $baseUrl = config('google.base_url');
        
        if (!$apiKey) {
            $this->error('❌ Google AI API key not configured');
            return self::FAILURE;
        }

        // Test specific model if provided
        if ($testModel = $this->option('test-model')) {
            return $this->testSpecificModel($testModel, $apiKey, $baseUrl);
        }

        try {
            // List all models
            $this->info('📋 Fetching available models...');
            $response = Http::timeout(30)
                ->get("{$baseUrl}/models", [
                    'key' => $apiKey
                ]);

            if (!$response->successful()) {
                $this->error('❌ Failed to fetch models: ' . $response->status() . ' ' . $response->body());
                return self::FAILURE;
            }

            $data = $response->json();
            
            if (!isset($data['models'])) {
                $this->error('❌ No models found in response');
                return self::FAILURE;
            }

            $this->info("✅ Found " . count($data['models']) . " models");
            $this->newLine();

            // Filter image generation models
            $imageModels = [];
            foreach ($data['models'] as $model) {
                $modelName = $model['name'] ?? '';
                $displayName = $model['displayName'] ?? '';
                
                // Check if it's an image generation model
                if (stripos($modelName, 'imagen') !== false || 
                    stripos($modelName, 'imagegeneration') !== false ||
                    stripos($displayName, 'image') !== false) {
                    
                    $supportedMethods = $model['supportedGenerationMethods'] ?? [];
                    $supportsPredict = in_array('generateContent', $supportedMethods) || 
                                     in_array('predict', $supportedMethods) ||
                                     !empty($supportedMethods);
                    
                    $imageModels[] = [
                        'name' => str_replace('models/', '', $modelName),
                        'display_name' => $displayName,
                        'supported_methods' => $supportedMethods,
                        'supports_predict' => $supportsPredict,
                        'full_model' => $model
                    ];
                }
            }

            if (empty($imageModels)) {
                $this->warn('⚠️  No image generation models found');
                return self::SUCCESS;
            }

            $this->info('🖼️  Available Image Generation Models:');
            $this->newLine();

            foreach ($imageModels as $index => $model) {
                $status = $model['supports_predict'] ? '✅' : '❌';
                $this->line(sprintf(
                    "%s %d. %s",
                    $status,
                    $index + 1,
                    $model['name']
                ));
                
                if (!empty($model['display_name'])) {
                    $this->line("      Display: {$model['display_name']}");
                }
                
                if (!empty($model['supported_methods'])) {
                    $this->line("      Methods: " . implode(', ', $model['supported_methods']));
                }
                
                $this->newLine();
            }

            // Recommend best models
            $this->info('🎯 Recommended Models (working with predict method):');
            $workingModels = array_filter($imageModels, fn($m) => $m['supports_predict']);
            
            if (empty($workingModels)) {
                $this->error('❌ No working models found');
                return self::FAILURE;
            }

            // Sort by preference (newer models first)
            usort($workingModels, function($a, $b) {
                // Prefer imagen-3 over older versions
                $aScore = $this->getModelScore($a['name']);
                $bScore = $this->getModelScore($b['name']);
                return $bScore - $aScore;
            });

            foreach (array_slice($workingModels, 0, 3) as $index => $model) {
                $this->line(sprintf(
                    "   %d. %s %s",
                    $index + 1,
                    $model['name'],
                    $index === 0 ? '(RECOMMENDED)' : ''
                ));
            }

            return self::SUCCESS;

        } catch (\Exception $e) {
            $this->error('❌ Error: ' . $e->getMessage());
            Log::error('Failed to list available models', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            return self::FAILURE;
        }
    }

    private function testSpecificModel(string $modelName, string $apiKey, string $baseUrl): int
    {
        $this->info("🧪 Testing model: {$modelName}");
        $this->newLine();

        try {
            $url = "{$baseUrl}/models/{$modelName}:predict";
            
            $testPayload = [
                'instances' => [
                    [
                        'prompt' => 'Simple test image: blue circle on white background'
                    ]
                ],
                'parameters' => [
                    'sampleCount' => 1,
                    'aspectRatio' => '1:1',
                    'safetyFilterLevel' => 'FILTER_MEDIUM',
                    'personGeneration' => 'DONT_ALLOW'
                ]
            ];

            $this->line("🔗 Testing URL: {$url}");
            
            $response = Http::timeout(60)
                ->withHeaders([
                    'Content-Type' => 'application/json',
                    'x-goog-api-key' => $apiKey,
                ])
                ->post($url, $testPayload);

            $this->line("📊 Response Status: " . $response->status());
            
            if ($response->successful()) {
                $data = $response->json();
                
                if (isset($data['predictions'][0]['bytesBase64Encoded']) && 
                    !empty($data['predictions'][0]['bytesBase64Encoded'])) {
                    $this->info("✅ Model {$modelName} works perfectly!");
                    $this->line("   Generated image data: " . strlen($data['predictions'][0]['bytesBase64Encoded']) . " characters");
                } else {
                    $this->warn("⚠️  Model {$modelName} responds but no image data");
                    $this->line("   Response: " . json_encode($data));
                }
            } else {
                $error = $response->json();
                $this->error("❌ Model {$modelName} failed:");
                $this->line("   Status: " . $response->status());
                $this->line("   Error: " . json_encode($error));
            }

            return self::SUCCESS;

        } catch (\Exception $e) {
            $this->error("❌ Exception testing model {$modelName}: " . $e->getMessage());
            return self::FAILURE;
        }
    }

    private function getModelScore(string $modelName): int
    {
        $score = 0;
        
        // Prefer imagen-3 over others
        if (stripos($modelName, 'imagen-3') !== false) {
            $score += 100;
        } elseif (stripos($modelName, 'imagen') !== false) {
            $score += 50;
        }
        
        // Prefer fast variants
        if (stripos($modelName, 'fast') !== false) {
            $score += 20;
        }
        
        // Prefer generate over other methods
        if (stripos($modelName, 'generate') !== false) {
            $score += 10;
        }
        
        // Prefer newer versions (higher numbers)
        if (preg_match('/(\d+)/', $modelName, $matches)) {
            $score += (int)$matches[1];
        }
        
        return $score;
    }
}