<?php

namespace App\Http\Controllers\Api\V1\Student;

use App\Http\Controllers\Api\V1\BaseController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\File;
use App\Models\Book;
use App\Models\BookChapter;
use App\Models\BookNote;
use App\Models\Bookmark;
use App\Models\BookProgress;

class BookController extends BaseController
{
    /**
     * Get list of books.
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function index(Request $request)
    {
        try {
            $user = Auth::user();
            
            $query = Book::where('is_active', true);
            
            // Search
            if ($request->has('search') && $request->search) {
                $search = $request->search;
                $query->where(function($q) use ($search) {
                    $q->where('title', 'like', "%{$search}%")
                      ->orWhere('author', 'like', "%{$search}%");
                });
            }
            
            $books = $query->withCount(['chapters'])
                ->with(['chapters' => function($query) {
                    $query->orderBy('order');
                }])
                ->orderBy('order')
                ->orderBy('title')
                ->paginate($request->get('per_page', 20));
            
            $data = $books->map(function($book) use ($user) {
                // Get reading progress efficiently
                $totalChapters = $book->chapters_count;
                
                // Count completed chapters for this user
                $readChapters = BookProgress::where('user_id', $user->id)
                    ->where('book_id', $book->id)
                    ->where('is_completed', true)
                    ->count();
                
                $progress = $totalChapters > 0 ? ($readChapters / $totalChapters) * 100 : 0;
                
                return [
                    'id' => $book->id,
                    'title' => $book->title,
                    'author' => $book->author,
                    'description' => $book->description,
                    'thumbnail' => $book->cover_image,
                    'total_chapters' => $totalChapters,
                    'read_chapters' => $readChapters,
                    'progress' => round($progress, 2),
                ];
            });
            
            return $this->paginated($data, $books);
        } catch (\Exception $e) {
            Log::error('Student Books API error: ' . $e->getMessage());
            return $this->error('An error occurred while fetching books.', null, 500);
        }
    }
    
    /**
     * Get book details.
     *
     * @param int $id
     * @return \Illuminate\Http\JsonResponse
     */
    public function show($id)
    {
        try {
            $book = Book::where('is_active', true)
                ->with(['chapters' => function($query) {
                    $query->orderBy('order');
                }])
                ->findOrFail($id);
            
            $chapters = $book->chapters->map(function($chapter) {
                return [
                    'id' => $chapter->id,
                    'title' => $chapter->title,
                    'order' => $chapter->order,
                ];
            })->sortBy('order')->values();
            
            return $this->success([
                'id' => $book->id,
                'title' => $book->title,
                'author' => $book->author,
                'description' => $book->description,
                'thumbnail' => $book->cover_image,
                'chapters' => $chapters,
            ]);
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
            return $this->error('Book not found.', null, 404);
        } catch (\Exception $e) {
            Log::error('Student Book API error: ' . $e->getMessage());
            return $this->error('An error occurred while fetching book details.', null, 500);
        }
    }
    
    /**
     * Get chapter content.
     *
     * @param int $bookId
     * @param int $chapterId
     * @return \Illuminate\Http\JsonResponse
     */
    public function getChapter($bookId, $chapterId)
    {
        try {
            $user = Auth::user();
            
            $book = Book::where('is_active', true)->findOrFail($bookId);
            $chapter = BookChapter::where('book_id', $bookId)
                ->where('id', $chapterId)
                ->firstOrFail();
            
            // Read the chapter HTML file from public directory (like web version)
            $filePath = public_path($book->folder_path . '/' . $chapter->file_name);
            
            if (!File::exists($filePath)) {
                return $this->error('Chapter file not found.', null, 404);
            }
            
            $htmlContent = File::get($filePath);
            
            // Extract only the body content (remove head, html tags, etc.)
            // Use DOMDocument to parse and extract content
            $dom = new \DOMDocument();
            @$dom->loadHTML(mb_convert_encoding($htmlContent, 'HTML-ENTITIES', 'UTF-8'));
            
            // Get the chapter-container div content
            $xpath = new \DOMXPath($dom);
            $container = $xpath->query('//div[@class="chapter-container"]')->item(0);
            
            if ($container) {
                $chapterContent = '';
                foreach ($container->childNodes as $node) {
                    $chapterContent .= $dom->saveHTML($node);
                }
            } else {
                // Fallback: extract body content
                $body = $dom->getElementsByTagName('body')->item(0);
                if ($body) {
                    $chapterContent = '';
                    foreach ($body->childNodes as $node) {
                        $chapterContent .= $dom->saveHTML($node);
                    }
                } else {
                    $chapterContent = $htmlContent;
                }
            }
            
            // Replace HTML file links with API endpoints for mobile
            $chapterContent = $this->replaceHtmlLinksWithApiRoutes($chapterContent, $book);
            
            // Sanitize content to prevent XSS
            $chapterContent = $this->sanitizeHtmlContent($chapterContent);
            
            // Get progress
            $progress = BookProgress::where('user_id', $user->id)
                ->where('book_chapter_id', $chapterId)
                ->first();
            
            // Get notes count
            $notesCount = BookNote::where('user_id', $user->id)
                ->where('book_chapter_id', $chapterId)
                ->count();
            
            // Get next/previous chapters
            $nextChapter = BookChapter::where('book_id', $bookId)
                ->where('order', '>', $chapter->order)
                ->orderBy('order')
                ->first();
            
            $previousChapter = BookChapter::where('book_id', $bookId)
                ->where('order', '<', $chapter->order)
                ->orderBy('order', 'desc')
                ->first();
            
            // Check if bookmarked
            $isBookmarked = Bookmark::where('user_id', $user->id)
                ->where('book_id', $bookId)
                ->where('book_chapter_id', $chapterId)
                ->exists();
            
            return $this->success([
                'id' => $chapter->id,
                'title' => $chapter->title,
                'content' => $chapterContent, // HTML content from file
                'content_url' => asset($book->folder_path . '/' . $chapter->file_name), // Direct URL to HTML file
                'order' => $chapter->order,
                'book' => [
                    'id' => $book->id,
                    'title' => $book->title,
                ],
                'next_chapter' => $nextChapter ? [
                    'id' => $nextChapter->id,
                    'title' => $nextChapter->title,
                ] : null,
                'previous_chapter' => $previousChapter ? [
                    'id' => $previousChapter->id,
                    'title' => $previousChapter->title,
                ] : null,
                'reading_progress' => $progress ? [
                    'last_position' => $progress->last_page_position ?? 0,
                    'is_completed' => $progress->is_completed ?? false,
                    'last_read_at' => $progress->last_read_at,
                ] : null,
                'notes_count' => $notesCount,
                'is_bookmarked' => $isBookmarked,
            ]);
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
            return $this->error('Chapter not found.', null, 404);
        } catch (\Exception $e) {
            Log::error('Student Book Chapter API error: ' . $e->getMessage());
            return $this->error('An error occurred while fetching chapter.', null, 500);
        }
    }
    
    /**
     * Save reading progress.
     *
     * @param Request $request
     * @param int $bookId
     * @param int $chapterId
     * @return \Illuminate\Http\JsonResponse
     */
    public function saveProgress(Request $request, $bookId, $chapterId)
    {
        try {
            $user = Auth::user();
            
            $validated = $request->validate([
                'last_position' => 'nullable|integer|min:0',
                'progress_percentage' => 'nullable|numeric|min:0|max:100',
                'is_completed' => 'nullable|boolean',
            ]);
            
            $progress = BookProgress::updateOrCreate(
                [
                    'user_id' => $user->id,
                    'book_chapter_id' => $chapterId,
                ],
                [
                    'book_id' => $bookId,
                    'last_page_position' => $validated['last_position'] ?? 0,
                    'is_completed' => $validated['is_completed'] ?? false,
                    'last_read_at' => now(),
                ]
            );
            
            return $this->success(null, 'Progress saved successfully');
        } catch (\Illuminate\Validation\ValidationException $e) {
            return $this->error('Validation failed', $e->errors(), 422);
        } catch (\Exception $e) {
            Log::error('Student Book Progress API error: ' . $e->getMessage());
            return $this->error('An error occurred while saving progress.', null, 500);
        }
    }
    
    /**
     * Get chapter notes.
     *
     * @param int $bookId
     * @param int $chapterId
     * @return \Illuminate\Http\JsonResponse
     */
    public function getNotes($bookId, $chapterId)
    {
        try {
            $user = Auth::user();
            
            $notes = BookNote::where('user_id', $user->id)
                ->where('book_chapter_id', $chapterId)
                ->orderBy('created_at', 'desc')
                ->get();
            
            return $this->success($notes->map(function($note) {
                return [
                    'id' => $note->id,
                    'content' => $note->content,
                    'created_at' => $note->created_at,
                    'updated_at' => $note->updated_at,
                ];
            }));
        } catch (\Exception $e) {
            Log::error('Student Book Notes API error: ' . $e->getMessage());
            return $this->error('An error occurred while fetching notes.', null, 500);
        }
    }
    
    /**
     * Create or update note.
     *
     * @param Request $request
     * @param int $bookId
     * @param int $chapterId
     * @return \Illuminate\Http\JsonResponse
     */
    public function saveNote(Request $request, $bookId, $chapterId)
    {
        try {
            $user = Auth::user();
            
            $validated = $request->validate([
                'content' => 'required|string',
                'note_id' => 'nullable|exists:book_notes,id',
            ]);
            
            if ($request->has('note_id')) {
                // Update existing note
                $note = BookNote::where('id', $request->note_id)
                    ->where('user_id', $user->id)
                    ->where('book_chapter_id', $chapterId)
                    ->firstOrFail();
                
                $note->content = $validated['content'];
                $note->save();
            } else {
                // Create new note
                $note = BookNote::create([
                    'user_id' => $user->id,
                    'book_id' => $bookId,
                    'book_chapter_id' => $chapterId,
                    'content' => $validated['content'],
                ]);
            }
            
            return $this->success([
                'id' => $note->id,
                'content' => $note->content,
                'created_at' => $note->created_at,
            ], $request->has('note_id') ? 'Note updated successfully' : 'Note created successfully');
        } catch (\Illuminate\Validation\ValidationException $e) {
            return $this->error('Validation failed', $e->errors(), 422);
        } catch (\Exception $e) {
            Log::error('Student Book Note API error: ' . $e->getMessage());
            return $this->error('An error occurred while saving note.', null, 500);
        }
    }
    
    /**
     * Delete note.
     *
     * @param int $bookId
     * @param int $chapterId
     * @param int $noteId
     * @return \Illuminate\Http\JsonResponse
     */
    public function deleteNote($bookId, $chapterId, $noteId)
    {
        try {
            $user = Auth::user();
            
            $note = BookNote::where('id', $noteId)
                ->where('user_id', $user->id)
                ->where('book_chapter_id', $chapterId)
                ->firstOrFail();
            
            $note->delete();
            
            return $this->success(null, 'Note deleted successfully');
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
            return $this->error('Note not found.', null, 404);
        } catch (\Exception $e) {
            Log::error('Student Book Note Delete API error: ' . $e->getMessage());
            return $this->error('An error occurred while deleting note.', null, 500);
        }
    }
    
    /**
     * Create bookmark.
     *
     * @param Request $request
     * @param int $bookId
     * @param int $chapterId
     * @return \Illuminate\Http\JsonResponse
     */
    public function createBookmark(Request $request, $bookId, $chapterId)
    {
        try {
            $user = Auth::user();
            
            $validated = $request->validate([
                'page_number' => 'nullable|integer|min:1',
                'note' => 'nullable|string|max:500',
            ]);
            
            $bookmark = Bookmark::updateOrCreate(
                [
                    'user_id' => $user->id,
                    'book_id' => $bookId,
                    'book_chapter_id' => $chapterId,
                ],
                [
                    'page_number' => $validated['page_number'] ?? null,
                    'note' => $validated['note'] ?? null,
                ]
            );
            
            return $this->success([
                'id' => $bookmark->id,
                'page_number' => $bookmark->page_number,
                'note' => $bookmark->note,
                'created_at' => $bookmark->created_at,
            ], 'Bookmark created successfully', 201);
        } catch (\Illuminate\Validation\ValidationException $e) {
            return $this->error('Validation failed', $e->errors(), 422);
        } catch (\Exception $e) {
            Log::error('Student Book Bookmark API error: ' . $e->getMessage());
            return $this->error('An error occurred while creating bookmark.', null, 500);
        }
    }
    
    /**
     * Delete bookmark.
     *
     * @param int $bookId
     * @param int $chapterId
     * @return \Illuminate\Http\JsonResponse
     */
    public function deleteBookmark($bookId, $chapterId)
    {
        try {
            $user = Auth::user();
            
            $bookmark = Bookmark::where('user_id', $user->id)
                ->where('book_id', $bookId)
                ->where('book_chapter_id', $chapterId)
                ->firstOrFail();
            
            $bookmark->delete();
            
            return $this->success(null, 'Bookmark deleted successfully');
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
            return $this->error('Bookmark not found.', null, 404);
        } catch (\Exception $e) {
            Log::error('Student Book Bookmark Delete API error: ' . $e->getMessage());
            return $this->error('An error occurred while deleting bookmark.', null, 500);
        }
    }
    
    /**
     * Get practice exercises for a chapter.
     *
     * @param int $bookId
     * @param int $chapterId
     * @return \Illuminate\Http\JsonResponse
     */
    public function getPractices($bookId, $chapterId)
    {
        try {
            $book = Book::where('is_active', true)->findOrFail($bookId);
            $chapter = BookChapter::where('book_id', $bookId)
                ->where('id', $chapterId)
                ->firstOrFail();
            
            $practices = BookChapterPractice::where('book_chapter_id', $chapterId)
                ->where('is_active', true)
                ->orderBy('order')
                ->get()
                ->map(function($practice) {
                    return [
                        'id' => $practice->id,
                        'title' => $practice->title,
                        'description' => $practice->description,
                        'type' => $practice->type,
                        'dart_code' => $practice->dart_code,
                        'flutter_code' => $practice->flutter_code,
                        'instructions' => $practice->instructions,
                        'order' => $practice->order,
                    ];
                });
            
            return $this->success([
                'chapter' => [
                    'id' => $chapter->id,
                    'title' => $chapter->title,
                ],
                'book' => [
                    'id' => $book->id,
                    'title' => $book->title,
                ],
                'practices' => $practices,
                'total' => $practices->count(),
            ]);
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
            return $this->error('Chapter not found.', null, 404);
        } catch (\Exception $e) {
            Log::error('Student Book Practices API error: ' . $e->getMessage());
            return $this->error('An error occurred while fetching practices.', null, 500);
        }
    }
    
    /**
     * Get a specific practice exercise.
     *
     * @param int $bookId
     * @param int $chapterId
     * @param int $practiceId
     * @return \Illuminate\Http\JsonResponse
     */
    public function getPractice($bookId, $chapterId, $practiceId)
    {
        try {
            $book = Book::where('is_active', true)->findOrFail($bookId);
            $chapter = BookChapter::where('book_id', $bookId)
                ->where('id', $chapterId)
                ->firstOrFail();
            
            $practice = BookChapterPractice::where('book_chapter_id', $chapterId)
                ->where('id', $practiceId)
                ->where('is_active', true)
                ->firstOrFail();
            
            // Get next/previous practices
            $nextPractice = BookChapterPractice::where('book_chapter_id', $chapterId)
                ->where('order', '>', $practice->order)
                ->where('is_active', true)
                ->orderBy('order')
                ->first();
            
            $previousPractice = BookChapterPractice::where('book_chapter_id', $chapterId)
                ->where('order', '<', $practice->order)
                ->where('is_active', true)
                ->orderBy('order', 'desc')
                ->first();
            
            return $this->success([
                'id' => $practice->id,
                'title' => $practice->title,
                'description' => $practice->description,
                'type' => $practice->type,
                'dart_code' => $practice->dart_code,
                'flutter_code' => $practice->flutter_code,
                'instructions' => $practice->instructions,
                'order' => $practice->order,
                'chapter' => [
                    'id' => $chapter->id,
                    'title' => $chapter->title,
                ],
                'book' => [
                    'id' => $book->id,
                    'title' => $book->title,
                ],
                'next_practice' => $nextPractice ? [
                    'id' => $nextPractice->id,
                    'title' => $nextPractice->title,
                ] : null,
                'previous_practice' => $previousPractice ? [
                    'id' => $previousPractice->id,
                    'title' => $previousPractice->title,
                ] : null,
            ]);
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
            return $this->error('Practice not found.', null, 404);
        } catch (\Exception $e) {
            Log::error('Student Book Practice API error: ' . $e->getMessage());
            return $this->error('An error occurred while fetching practice.', null, 500);
        }
    }
    
    /**
     * Download chapter PDF.
     *
     * @param int $bookId
     * @param int $chapterId
     * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response
     */
    public function downloadChapter($bookId, $chapterId)
    {
        try {
            $chapter = BookChapter::where('book_id', $bookId)
                ->where('id', $chapterId)
                ->firstOrFail();
            
            // If PDF exists, return download link
            // Otherwise, generate PDF from content (you may need to implement this)
            return $this->error('PDF download not yet implemented.', null, 501);
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
            return $this->error('Chapter not found.', null, 404);
        } catch (\Exception $e) {
            Log::error('Student Book Download API error: ' . $e->getMessage());
            return $this->error('An error occurred while downloading chapter.', null, 500);
        }
    }
    
    /**
     * Replace HTML file links in content with API endpoints for mobile.
     */
    private function replaceHtmlLinksWithApiRoutes($htmlContent, $book)
    {
        // Create a mapping of file names to chapter IDs
        $chapters = $book->chapters;
        $fileToChapterMap = [];
        
        foreach ($chapters as $ch) {
            $fileToChapterMap[$ch->file_name] = $ch->id;
        }

        // Use DOMDocument to find and replace links
        // Wrap content in a temporary container for proper parsing
        $wrappedContent = '<div id="temp-container">' . $htmlContent . '</div>';
        $dom = new \DOMDocument();
        @$dom->loadHTML(mb_convert_encoding($wrappedContent, 'HTML-ENTITIES', 'UTF-8'), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
        
        $xpath = new \DOMXPath($dom);
        
        // Find all anchor tags with href attributes
        $links = $xpath->query('//a[@href]');
        
        foreach ($links as $link) {
            $href = $link->getAttribute('href');
            
            // Check if it's a link to an HTML file (relative path)
            // Match patterns like: chapter-1.html, introduction.html, etc.
            if (preg_match('/^([^\/]+\.html)(?:#.*)?$/', $href, $matches)) {
                $fileName = $matches[1];
                
                // Check if we have a chapter for this file
                if (isset($fileToChapterMap[$fileName])) {
                    $chapterId = $fileToChapterMap[$fileName];
                    // Replace with API endpoint
                    $newHref = url("/api/v1/student/books/{$book->id}/chapters/{$chapterId}");
                    $link->setAttribute('href', $newHref);
                }
            }
        }
        
        // Extract content from the temporary container
        $container = $xpath->query('//div[@id="temp-container"]')->item(0);
        if ($container) {
            $updatedContent = '';
            foreach ($container->childNodes as $node) {
                $updatedContent .= $dom->saveHTML($node);
            }
            return $updatedContent;
        }
        
        // Fallback: return original content
        return $htmlContent;
    }
    
    /**
     * Sanitize HTML content to prevent XSS attacks
     * 
     * @param string $content
     * @return string
     */
    private function sanitizeHtmlContent($content)
    {
        // Use DOMDocument to parse and clean HTML
        $dom = new \DOMDocument();
        @$dom->loadHTML(mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8'), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
        
        // Remove potentially dangerous elements and attributes
        $xpath = new \DOMXPath($dom);
        
        // Remove script tags
        $scripts = $xpath->query('//script');
        foreach ($scripts as $script) {
            $script->parentNode->removeChild($script);
        }
        
        // Remove event handlers from all elements
        $allElements = $xpath->query('//*');
        foreach ($allElements as $element) {
            // Remove event handler attributes
            $attributes = $element->attributes;
            if ($attributes) {
                $toRemove = [];
                foreach ($attributes as $attr) {
                    // Remove onclick, onerror, etc.
                    if (preg_match('/^on/i', $attr->name)) {
                        $toRemove[] = $attr->name;
                    }
                    // Remove javascript: protocol from href/src
                    if (in_array($attr->name, ['href', 'src', 'action']) && 
                        preg_match('/^javascript:/i', $attr->value)) {
                        $toRemove[] = $attr->name;
                    }
                }
                foreach ($toRemove as $attrName) {
                    $element->removeAttribute($attrName);
                }
            }
        }
        
        // Get the cleaned HTML
        $body = $dom->getElementsByTagName('body')->item(0);
        if ($body) {
            $cleanedContent = '';
            foreach ($body->childNodes as $node) {
                $cleanedContent .= $dom->saveHTML($node);
            }
            return $cleanedContent;
        }
        
        return $content;
    }
}
