<?php

namespace App\Http\Controllers\SelfPaced\Learner;

use App\Http\Controllers\Controller;
use App\Models\SelfPaced\Course;
use App\Models\SelfPaced\CourseTopic;
use App\Models\SelfPaced\CourseSubTopic;
use App\Models\SelfPaced\Enrollment;
use App\Models\SelfPaced\ExamResult;
use App\Models\Organization;
use App\Models\LoginAttempt;
use App\Services\ExamService;
use App\Services\SelfPacedCertificateService;
use App\Services\SelfPacedService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Response;

class LearnerController extends Controller
{
    public function __construct(
        protected SelfPacedService $selfPacedService,
        protected ExamService $examService,
        protected SelfPacedCertificateService $certificateService
    ) {
        //
    }

    // =========================================================================
    // MY COURSES — Trainee landing page (all enrolled courses)
    // =========================================================================

    /**
     * Show all courses the authenticated trainee is enrolled in.
     * This is the learner portal home page for Trainees.
     * Displays comprehensive dashboard with statistics, progress, and enrolled courses.
     */
    public function myCourses()
    {
        $user = Auth::user();
        $userId = $user->id;

        // Get all enrollments
        $enrollments = Enrollment::with(['course.category', 'course.instructor'])
            ->where('user_id', $userId)
            ->whereIn('status', ['active', 'completed', 'pending_payment', 'payment_failed'])
            ->latest()
            ->get();

        // Separate active and completed enrollments
        $activeEnrollments = $enrollments->filter(fn($e) => !$e->isDeregistered() && $e->isActive());
        $completedEnrollments = $enrollments->filter(fn($e) => $e->isCompleted());
        $pendingPaymentEnrollments = $enrollments->filter(fn($e) => $e->isPendingPayment());

        // Calculate statistics
        $stats = [
            'active_registrations' => $activeEnrollments->count(),
            'completed_courses' => $completedEnrollments->count(),
            'pending_payment' => $pendingPaymentEnrollments->count(),
            'total_enrollments' => $enrollments->count(),
        ];

        // Get all certificates earned by this user
        $certificates = \App\Models\SelfPaced\SelfPacedCertificate::where('user_id', $userId)
            ->where('status', 'issued')
            ->get();
        $stats['certificates_earned'] = $certificates->count();

        // Get registration/enrollment date (first enrollment)
        $firstEnrollment = Enrollment::where('user_id', $userId)
            ->orderBy('created_at')
            ->first();
        $stats['registration_date'] = $firstEnrollment?->created_at ?? now();
        $stats['days_in_system'] = $firstEnrollment ? $firstEnrollment->created_at->diffInDays(now()) : 0;

        // Get registered IP address (from login attempts or user info)
        $loginAttempt = \App\Models\LoginAttempt::where('user_id', $userId)
            ->where('status', 'success')
            ->latest()
            ->first();
        $stats['registered_ip'] = $loginAttempt?->ip_address ?? 'N/A';

        // Calculate overall progress percentage
        $totalProgress = 0;
        if ($enrollments->isNotEmpty()) {
            $totalProgress = $enrollments->avg(function ($enrollment) {
                return $enrollment->getProgressPercentage();
            });
        }
        $stats['overall_progress'] = (int) $totalProgress;

        // Get organization details
        $organization = \App\Models\Organization::first();

        return view('self-paced.learner.my-courses', compact(
            'user',
            'enrollments',
            'activeEnrollments',
            'completedEnrollments',
            'pendingPaymentEnrollments',
            'certificates',
            'stats',
            'organization'
        ));
    }

    // =========================================================================
    // PHASE 1 — Course Overview
    // =========================================================================

    /**
     * Show the course overview (Phase 1).
     * Requirement 6.1, 6.2, 6.3, 6.4
     */
    public function overview(Course $course)
    {
        $enrollment = $this->getActiveEnrollment($course);
        $course->load(['category', 'instructor', 'topics.subtopics']);

        $progressPercentage = $enrollment->getProgressPercentage();

        // Mark phase 1 as visited in session so Phase 2 becomes accessible
        session(["sp_phase1_done_{$enrollment->id}" => true]);

        return view('self-paced.learner.overview', compact('course', 'enrollment', 'progressPercentage'));
    }

    // =========================================================================
    // PHASE 2 — Course Content
    // =========================================================================

    /**
     * Show a specific subtopic (Phase 2).
     * Enforces: topic access control, topic timing requirements
     *
     * Requirement: 7.1, 7.2, 7.3, 7.5, 7.7, 7.8, 7.9, 3.9, 3.10
     */
    public function content(Course $course, ?int $subtopicId = null)
    {
        $enrollment = $this->getActiveEnrollment($course);

        // Enforce phase 1 completion
        if (!session("sp_phase1_done_{$enrollment->id}")) {
            return redirect()->route('self-paced.learn.overview', $course)
                ->with('info', 'Please review the course overview first.');
        }

        // Post-exam 30-day window: if all attempts used AND last result > 30 days old,
        // redirect to results (Post-Lock State — Requirement 5.4, 8.1).
        if ($enrollment->getRemainingAttempts() === 0) {
            $latestResult = $enrollment->examResults()->latest('created_at')->first();
            if ($latestResult && $latestResult->created_at->diffInDays(now()) > 30) {
                return redirect()->route('self-paced.learn.results', [$course, $latestResult])
                    ->with('info', 'Your 30-day access window has ended. You may re-enroll from the course catalogue to start fresh.');
            }
        }

        // Resolve which subtopic to show
        if ($subtopicId) {
            $subtopic = CourseSubTopic::with(['topic', 'media'])->findOrFail($subtopicId);
            abort_unless($subtopic->topic->course_id === $course->id, 404);

            // Validate topic access (sequential unlock + timing)
            $topic = $subtopic->topic;
            if (!$this->selfPacedService->isTopicAccessible($enrollment, $topic)) {
                return redirect()->route('self-paced.learn.overview', $course)
                    ->with('error', 'You cannot access this topic yet. Complete previous topics first.');
            }
        } else {
            // Resume from last visited or start from first
            $subtopic = $this->selfPacedService->getLastVisitedSubtopic($enrollment);
            if (!$subtopic) {
                return redirect()->route('self-paced.learn.overview', $course)
                    ->with('info', 'No content available yet for this course.');
            }
            $subtopic->load(['topic.downloads', 'media']);
        }

        $topic              = $subtopic->topic;
        $progressPercentage = $enrollment->getProgressPercentage();
        $isRead             = $subtopic->isReadByEnrollment($enrollment->id);
        $topicTimer         = $this->selfPacedService->getOrCreateTopicTimer($enrollment, $topic);

        // Calculate remaining minimum time for countdown timer
        $minTimeSeconds      = (int) $topic->min_time_seconds ?? 0;
        $elapsedSeconds      = (int) $topicTimer->elapsed_seconds ?? 0;
        $remainingMinSeconds = max(0, $minTimeSeconds - $elapsedSeconds);

        // Get locked topics for sequential unlocking
        $lockedTopicIds = [];
        if (!$enrollment->isExamUnlocked()) {
            $allPublishedTopics = $course->topics()->where('is_published', true)->orderBy('sort_order')->get();
            foreach ($allPublishedTopics as $t) {
                if (!$t->isCompletedForEnrollment($enrollment->id)) {
                    $lockedTopicIds[] = $t->id;
                }
            }
        }

        // Build navigation: all topics with their subtopics + completion state
        $allTopics = $course->topics()->with('subtopics')->get()->map(function (CourseTopic $t) use ($enrollment) {
            $t->is_completed = $t->isCompletedForEnrollment($enrollment->id);
            $t->subtopics->each(function (CourseSubTopic $st) use ($enrollment) {
                $st->is_read = $st->isReadByEnrollment($enrollment->id);
            });
            return $t;
        });

        // Determine next subtopic
        $nextSubtopic = $this->resolveNextSubtopic($subtopic, $course);
        $allDone      = $progressPercentage >= 100.0;
        $isExamUnlocked = $enrollment->isExamUnlocked();

        return view('self-paced.learner.content', compact(
            'course', 'enrollment', 'topic', 'subtopic',
            'progressPercentage', 'isRead', 'topicTimer',
            'minTimeSeconds', 'elapsedSeconds', 'remainingMinSeconds',
            'lockedTopicIds', 'allTopics', 'nextSubtopic', 'allDone', 'isExamUnlocked'
        ));
    }

    /**
     * Mark a subtopic as read (AJAX POST).
     * Requirement 7.3, 7.4
     */
    public function markRead(Request $request, Course $course, CourseSubTopic $subtopic)
    {
        $enrollment = $this->getActiveEnrollment($course);

        abort_unless($subtopic->topic->course_id === $course->id, 404);

        $this->selfPacedService->markSubtopicRead($enrollment, $subtopic);

        $progressPercentage = $enrollment->getProgressPercentage();
        $topicComplete      = $subtopic->topic->isCompletedForEnrollment($enrollment->id);

        return response()->json([
            'success'            => true,
            'progress_percentage' => $progressPercentage,
            'topic_complete'     => $topicComplete,
            'all_done'           => $progressPercentage >= 100.0,
        ]);
    }

    /**
     * Ping to update topic timer (AJAX POST every 30 seconds).
     * Requirement 7.2
     */
    public function pingTimer(Request $request, Course $course, CourseTopic $topic)
    {
        $enrollment = $this->getActiveEnrollment($course);

        abort_unless($topic->course_id === $course->id, 404);

        $seconds = (int) $request->input('seconds', 30);
        $timer   = $this->selfPacedService->updateTopicTimer($enrollment, $topic, $seconds);

        return response()->json([
            'success'         => true,
            'elapsed_seconds' => $timer->elapsed_seconds,
            'formatted'       => $timer->getFormattedElapsed(),
        ]);
    }

    // =========================================================================
    // PHASE 4 — Results and Certificate
    // =========================================================================

    /**
     * Show exam results (Phase 4).
     * Requirement 9.1, 9.2, 9.3, 9.4, 9.5, 9.6
     */
    public function results(Course $course, ExamResult $result)
    {
        $enrollment = $this->getActiveEnrollment($course);

        // Ensure this result belongs to this enrollment
        abort_unless($result->enrollment_id === $enrollment->id, 403);

        $result->load(['attempt', 'certificate']);
        $incorrectAnswers  = $this->examService->getIncorrectAnswers($result->attempt);
        $remainingAttempts = $enrollment->getRemainingAttempts();
        $progressPercentage = $enrollment->getProgressPercentage();

        return view('self-paced.learner.results', compact(
            'course', 'enrollment', 'result',
            'incorrectAnswers', 'remainingAttempts', 'progressPercentage'
        ));
    }

    /**
     * Download result slip PDF.
     * Requirement 9.2
     */
    public function downloadResultSlip(Course $course, ExamResult $result)
    {
        $enrollment = $this->getActiveEnrollment($course);
        abort_unless($result->enrollment_id === $enrollment->id, 403);

        $pdfContent = $this->certificateService->streamResultSlip($result);

        return Response::make($pdfContent, 200, [
            'Content-Type'        => 'application/pdf',
            'Content-Disposition' => 'attachment; filename="result-slip-' . $result->id . '.pdf"',
        ]);
    }

    /**
     * Download certificate PDF.
     * Requirement 9.3, 9.4
     */
    public function downloadCertificate(Course $course, ExamResult $result)
    {
        $enrollment = $this->getActiveEnrollment($course);
        abort_unless($result->enrollment_id === $enrollment->id, 403);
        abort_unless($result->passed, 403, 'Certificate only available for passed results.');

        $certificate = $result->certificate;

        if (!$certificate) {
            $certificate = $this->certificateService->generate($result, Auth::id());
        }

        $pdfContent = $this->certificateService->streamPdf($certificate);

        return Response::make($pdfContent, 200, [
            'Content-Type'        => 'application/pdf',
            'Content-Disposition' => 'attachment; filename="certificate-' . $certificate->certificate_number . '.pdf"',
        ]);
    }

    // =========================================================================
    // HELPERS
    // =========================================================================

    /**
     * Get the authenticated user's active/completed enrollment for a course,
     * or abort 403 if none exists.
     */
    protected function getActiveEnrollment(Course $course): Enrollment
    {
        $enrollment = Enrollment::where('user_id', Auth::id())
            ->where('course_id', $course->id)
            ->whereIn('status', ['active', 'completed'])
            ->first();

        if (!$enrollment) {
            abort(403, 'You are not enrolled in this course or your enrollment is not active.');
        }

        return $enrollment;
    }

    /**
     * Resolve the next subtopic after the current one (for the "Next" button).
     */
    protected function resolveNextSubtopic(CourseSubTopic $current, Course $course): ?CourseSubTopic
    {
        // Next in same topic
        $next = CourseSubTopic::where('topic_id', $current->topic_id)
            ->where('is_published', true)
            ->where('sort_order', '>', $current->sort_order)
            ->orderBy('sort_order')
            ->first();

        if ($next) {
            return $next;
        }

        // First subtopic of next topic
        $nextTopic = CourseTopic::where('course_id', $course->id)
            ->where('is_published', true)
            ->where('sort_order', '>', $current->topic->sort_order)
            ->orderBy('sort_order')
            ->first();

        return $nextTopic
            ? $nextTopic->subtopics()->where('is_published', true)->orderBy('sort_order')->first()
            : null;
    }

    // =========================================================================
    // PAYMENT PROOF — Cash payment proof uploads
    // =========================================================================

    /**
     * Show the payment proof upload form
     */
    public function showPaymentProofForm(Course $course, Request $request)
    {
        $feeType = $request->query('fee_type', 'enrollment');
        $amount = $request->query('amount', 0);

        return view('self-paced.learner.payment-proof', compact('course', 'feeType', 'amount'));
    }

    /**
     * Store payment proof upload
     */
    public function storePaymentProof(Request $request, Course $course)
    {
        $validated = $request->validate([
            'fee_type' => 'required|in:enrollment,certificate,book,resit',
            'proof_type' => 'required|in:m_pesa,bank,receipt',
            'proof_file' => 'required|file|mimes:jpeg,png,gif,pdf|max:5120',
            'amount' => 'required|numeric|min:0.01',
        ]);

        $enrollment = $this->getActiveEnrollment($course);

        $file = $request->file('proof_file');
        $filePath = $file->store('payment-proofs', 'private');

        \App\Models\SelfPaced\PaymentProof::create([
            'enrollment_id' => $enrollment->id,
            'user_id' => Auth::id(),
            'course_id' => $course->id,
            'fee_type' => $validated['fee_type'],
            'proof_type' => $validated['proof_type'],
            'file_path' => $filePath,
            'file_name' => $file->getClientOriginalName(),
            'file_size' => $file->getSize(),
            'file_mime' => $file->getMimeType(),
            'amount' => $validated['amount'],
            'currency' => $course->currency ?? 'KES',
            'status' => 'pending',
        ]);

        return redirect()->back()
            ->with('success', 'Payment proof submitted successfully. Your manager will review and approve it shortly.');
    }
}
