<?php

namespace App\Http\Controllers;

use App\Models\AiDocument;
use App\Services\OllamaService;
use App\Services\RagService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;

class AiController extends Controller
{
    protected $ollama;
    protected $rag;

    public function __construct(OllamaService $ollama, RagService $rag)
    {
        $this->ollama = $ollama;
        $this->rag = $rag;
    }

    /**
     * Health check endpoint
     */
    public function health()
    {
        try {
            // Check if Ollama is accessible
            $response = \Illuminate\Support\Facades\Http::timeout(5)
                ->get(config('ollama.base_url', 'http://172.16.1.6:11434') . '/api/tags');

            return response()->json([
                'success' => $response->successful(),
                'message' => $response->successful() ? 'AI service is available' : 'AI service is not responding',
                'ollama_accessible' => $response->successful()
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Failed to connect to AI service',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Generate AI response (without RAG)
     */
    public function generate(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'prompt' => 'required|string|max:5000',
            'model' => 'nullable|string|in:phi3,llama2,mistral,codellama'
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'error' => $validator->errors()->first()
            ], 422);
        }

        try {
            $prompt = $request->input('prompt');
            $model = $request->input('model', 'phi3');

            Log::info('Generating AI response', [
                'prompt_length' => strlen($prompt),
                'model' => $model
            ]);

            $response = $this->ollama->generate($prompt, $model);

            if (!$response) {
                throw new \Exception('No response from AI service');
            }

            return response()->json([
                'success' => true,
                'answer' => $response,
                'model' => $model
            ]);

        } catch (\Exception $e) {
            Log::error('AI generation error: ' . $e->getMessage());
            
            return response()->json([
                'success' => false,
                'error' => 'Failed to generate response: ' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * Ask question with document context (RAG)
     */
    public function askWithContext(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'question' => 'required|string|max:5000',
            'model' => 'nullable|string|in:phi3,llama2,mistral,codellama'
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'error' => $validator->errors()->first()
            ], 422);
        }

        try {
            $question = $request->input('question');
            $model = $request->input('model', 'phi3');

            Log::info('RAG query received', [
                'question_length' => strlen($question),
                'model' => $model
            ]);

            // Check if we have any documents
            $hasDocuments = AiDocument::count() > 0;

            if (!$hasDocuments) {
                Log::info('No documents available, using direct generation');
                
                // No documents, just use direct generation
                $response = $this->ollama->generate($question, $model);
                
                return response()->json([
                    'success' => true,
                    'answer' => $response,
                    'used_documents' => false,
                    'model' => $model,
                    'message' => 'No documents available. Answered without document context.'
                ]);
            }

            // Use RAG with document context
            $response = $this->rag->answerWithContext($this->ollama, $question, $model);

            if (!$response) {
                throw new \Exception('No response from AI service');
            }

            return response()->json([
                'success' => true,
                'answer' => $response,
                'used_documents' => true,
                'model' => $model
            ]);

        } catch (\Exception $e) {
            Log::error('RAG query error: ' . $e->getMessage(), [
                'trace' => $e->getTraceAsString()
            ]);
            
            return response()->json([
                'success' => false,
                'error' => 'Failed to process question: ' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * Upload and process document
     */
    public function uploadDocument(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'title' => 'required|string|max:255',
            'file' => 'required|file|mimes:txt,pdf,docx|max:10240' // 10MB max
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'error' => $validator->errors()->first()
            ], 422);
        }

        try {
            $file = $request->file('file');
            $title = $request->input('title');
            
            // Store file temporarily
            $path = $file->store('temp_uploads');
            $fullPath = storage_path('app/' . $path);
            
            Log::info('Processing document upload', [
                'title' => $title,
                'filename' => $file->getClientOriginalName(),
                'size' => $file->getSize(),
                'type' => $file->getClientMimeType()
            ]);

            // Extract text from file
            $content = $this->rag->extractTextFromFile(
                $fullPath,
                $file->getClientMimeType()
            );

            if (empty(trim($content))) {
                throw new \Exception('No text content could be extracted from the file');
            }

            Log::info('Text extracted', [
                'content_length' => strlen($content),
                'word_count' => str_word_count($content)
            ]);

            // Process and index document
            $document = $this->rag->processDocument(
                $title,
                $content,
                $file->getClientOriginalName(),
                $file->getClientMimeType()
            );

            // Clean up temporary file
            \Illuminate\Support\Facades\Storage::delete($path);

            Log::info('Document processed successfully', [
                'document_id' => $document->id,
                'chunks' => $document->chunk_count
            ]);

            return response()->json([
                'success' => true,
                'message' => 'Document uploaded and processed successfully',
                'document' => [
                    'id' => $document->id,
                    'title' => $document->title,
                    'filename' => $document->filename,
                    'chunk_count' => $document->chunk_count,
                    'created_at' => $document->created_at
                ]
            ]);

        } catch (\Exception $e) {
            Log::error('Document upload error: ' . $e->getMessage(), [
                'trace' => $e->getTraceAsString()
            ]);
            
            // Clean up on error
            if (isset($path)) {
                \Illuminate\Support\Facades\Storage::delete($path);
            }

            return response()->json([
                'success' => false,
                'error' => 'Failed to process document: ' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * List all documents
     */
    public function listDocuments()
    {
        try {
            $documents = AiDocument::orderBy('created_at', 'desc')->get();

            return response()->json([
                'success' => true,
                'documents' => $documents,
                'count' => $documents->count()
            ]);

        } catch (\Exception $e) {
            Log::error('Failed to list documents: ' . $e->getMessage());
            
            return response()->json([
                'success' => false,
                'error' => 'Failed to fetch documents'
            ], 500);
        }
    }

    /**
     * Get single document
     */
    public function getDocument($id)
    {
        try {
            $document = AiDocument::with('chunks')->findOrFail($id);

            return response()->json([
                'success' => true,
                'document' => $document
            ]);

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'error' => 'Document not found'
            ], 404);
        }
    }

    /**
     * Delete document
     */
    public function deleteDocument($id)
    {
        try {
            $document = AiDocument::findOrFail($id);
            $title = $document->title;
            
            $document->delete(); // This will cascade delete chunks

            Log::info('Document deleted', [
                'document_id' => $id,
                'title' => $title
            ]);

            return response()->json([
                'success' => true,
                'message' => 'Document deleted successfully'
            ]);

        } catch (\Exception $e) {
            Log::error('Failed to delete document: ' . $e->getMessage());
            
            return response()->json([
                'success' => false,
                'error' => 'Failed to delete document'
            ], 500);
        }
    }

    /**
     * Get RAG statistics
     */
    public function getStatistics()
    {
        try {
            $stats = $this->rag->getStatistics();

            return response()->json([
                'success' => true,
                'statistics' => $stats
            ]);

        } catch (\Exception $e) {
            Log::error('Failed to get statistics: ' . $e->getMessage());
            
            return response()->json([
                'success' => false,
                'error' => 'Failed to fetch statistics'
            ], 500);
        }
    }

    /**
     * Search similar documents
     */
    public function searchSimilar(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'query' => 'required|string|max:1000',
            'top_k' => 'nullable|integer|min:1|max:20'
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'error' => $validator->errors()->first()
            ], 422);
        }

        try {
            $query = $request->input('query');
            $topK = $request->input('top_k', 5);

            $results = $this->rag->searchSimilar($query, $topK);

            return response()->json([
                'success' => true,
                'results' => $results,
                'count' => count($results)
            ]);

        } catch (\Exception $e) {
            Log::error('Search error: ' . $e->getMessage());
            
            return response()->json([
                'success' => false,
                'error' => 'Search failed: ' . $e->getMessage()
            ], 500);
        }
    }
}