<?php

namespace App\Services;

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

class OllamaService
{
    protected $baseUrl;
    protected $timeout = 300; // 5 minutes for generation
    protected $modelMap = [
        'phi3' => 'phi3',
        'llama2' => 'llama2',
        'mistral' => 'mistral',
        'codellama' => 'codellama'
    ];

    public function __construct()
    {
        $this->baseUrl = config('ollama.base_url', 'http://172.16.1.6:11434');
    }

    /**
     * Generate text completion using Ollama
     */
    public function generate($prompt, $model = 'phi3', $stream = false)
    {
        try {
            $modelName = $this->modelMap[$model] ?? 'phi3';
            
            Log::info('Generating with Ollama', [
                'model' => $modelName,
                'prompt_length' => strlen($prompt),
                'stream' => $stream
            ]);

            $response = Http::timeout($this->timeout)
                ->retry(2, 1000) // Retry twice with 1 second delay
                ->post("{$this->baseUrl}/api/generate", [
                    'model' => $modelName,
                    'prompt' => $prompt,
                    'stream' => $stream,
                    'options' => [
                        'temperature' => 0.7,
                        'top_p' => 0.9,
                        'top_k' => 40,
                    ]
                ]);

            if (!$response->successful()) {
                Log::error('Ollama generation failed', [
                    'status' => $response->status(),
                    'body' => $response->body()
                ]);
                throw new \Exception('Failed to generate response from Ollama');
            }

            $data = $response->json();
            
            if (!isset($data['response'])) {
                Log::error('Invalid Ollama response format', ['data' => $data]);
                throw new \Exception('Invalid response format from Ollama');
            }

            $generatedText = $data['response'];
            
            Log::info('Generation successful', [
                'response_length' => strlen($generatedText),
                'model' => $modelName
            ]);

            return $generatedText;

        } catch (\Illuminate\Http\Client\ConnectionException $e) {
            Log::error('Ollama connection error: ' . $e->getMessage(), [
                'url' => $this->baseUrl,
                'model' => $model
            ]);
            throw new \Exception('Cannot connect to Ollama service. Please ensure it is running at ' . $this->baseUrl);
        } catch (\Exception $e) {
            Log::error('Ollama generation error: ' . $e->getMessage());
            throw $e;
        }
    }

    /**
     * Generate chat completion
     */
    public function chat($messages, $model = 'phi3')
    {
        try {
            $modelName = $this->modelMap[$model] ?? 'phi3';
            
            Log::info('Chat with Ollama', [
                'model' => $modelName,
                'message_count' => count($messages)
            ]);

            $response = Http::timeout($this->timeout)
                ->retry(2, 1000)
                ->post("{$this->baseUrl}/api/chat", [
                    'model' => $modelName,
                    'messages' => $messages,
                    'stream' => false,
                    'options' => [
                        'temperature' => 0.7,
                    ]
                ]);

            if (!$response->successful()) {
                throw new \Exception('Failed to get chat response from Ollama');
            }

            $data = $response->json();
            
            return $data['message']['content'] ?? null;

        } catch (\Exception $e) {
            Log::error('Ollama chat error: ' . $e->getMessage());
            throw $e;
        }
    }

    /**
     * List available models
     */
    public function listModels()
    {
        try {
            $response = Http::timeout(10)->get("{$this->baseUrl}/api/tags");

            if ($response->successful()) {
                return $response->json()['models'] ?? [];
            }

            return [];
        } catch (\Exception $e) {
            Log::error('Failed to list models: ' . $e->getMessage());
            return [];
        }
    }

    /**
     * Check if Ollama is accessible
     */
    public function isAccessible()
    {
        try {
            $response = Http::timeout(5)->get("{$this->baseUrl}/api/tags");
            return $response->successful();
        } catch (\Exception $e) {
            return false;
        }
    }
}