<?php

namespace App\Http\Controllers;

use App\Models\Course;
use App\Models\CourseEnrollment;
use App\Models\User;
use App\Services\UserCourseStatusService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class CourseEnrollmentController extends Controller
{
    protected UserCourseStatusService $userCourseStatusService;

    public function __construct(UserCourseStatusService $userCourseStatusService)
    {
        $this->userCourseStatusService = $userCourseStatusService;

        $this->middleware('permission:course_enrollments view', ['only' => ['index']]);
        $this->middleware('permission:course_enrollments update', ['only' => ['edit', 'update']]);
        $this->middleware('permission:course_enrollments create', ['only' => ['create', 'store']]);
        $this->middleware('permission:course_enrollments delete', ['only' => ['destroy']]);
    }

    public function index()
    {
        $user = Auth::user();

        $query = CourseEnrollment::with([
            'course.category',
            'course.teacher',
            'student',
        ])->latest();

        if ($user->hasRole('teacher')) {
            $query->whereHas('course', function ($q) use ($user) {
                $q->where('teacher_id', $user->id);
            });
        } elseif ($user->hasRole('student')) {
            $query->where('student_id', $user->id);
        }

        $enrollments = $query->get();

        audit_log(
            'course_enrollments',
            null,
            'listed',
            'Course enrollments listed',
            ['count' => $enrollments->count()]
        );

        return view('course_enrollments.index', compact('enrollments'));
    }

    public function create()
    {
        $user = Auth::user();

        $courses = Course::with('category')
            ->where('status', 'approved')
            ->where(function ($query) {
                $query->whereNull('expire_date')
                    ->orWhereDate('expire_date', '>=', now()->toDateString());
            })
            ->latest()
            ->get();

        $students = collect();

        if ($user->hasRole('master-admin')) {
            $students = User::role('student')
                ->select('id', 'name')
                ->latest()
                ->get();
        }

        return view('course_enrollments.create', compact('courses', 'students'));
    }

    public function store(Request $request)
    {
        $user = Auth::user();

        if ($user->hasRole('teacher')) {
            abort(403);
        }

        $data = $request->validate([
            'course_id' => 'required|exists:courses,id',
            'student_id' => 'nullable|exists:users,id',
        ]);

        if ($user->hasRole('student')) {
            $data['student_id'] = $user->id;
        }

        if ($user->hasRole('master-admin') && empty($data['student_id'])) {
            return back()->withErrors([
                'student_id' => 'Please select a student.',
            ])->withInput();
        }

        $course = Course::findOrFail($data['course_id']);

        if ($course->isExpired()) {
            return back()->withErrors([
                'course_id' => 'This course has already expired.',
            ])->withInput();
        }

        $exists = CourseEnrollment::where('course_id', $data['course_id'])
            ->where('student_id', $data['student_id'])
            ->exists();

        if ($exists) {
            return back()->with('error', 'Already enrolled.')->withInput();
        }

        $enrollment = CourseEnrollment::create($data);

        $this->userCourseStatusService->syncEnrollmentParticipants($enrollment);

        return redirect()->route('course-enrollments.index')
            ->with('success', 'Enrollment created successfully.');
    }

    public function edit(CourseEnrollment $course_enrollment)
    {
        $user = Auth::user();

        if ($user->hasRole('teacher')) {
            abort(403);
        }

        if ($user->hasRole('student') && $course_enrollment->student_id !== $user->id) {
            abort(403);
        }

        $courses = Course::with('category')
            ->where('status', 'approved')
            ->where(function ($query) {
                $query->whereNull('expire_date')
                    ->orWhereDate('expire_date', '>=', now()->toDateString());
            })
            ->latest()
            ->get();

        $students = collect();

        if ($user->hasRole('master-admin')) {
            $students = User::role('student')
                ->select('id', 'name')
                ->latest()
                ->get();
        }

        return view('course_enrollments.edit', compact(
            'course_enrollment',
            'courses',
            'students'
        ));
    }

    public function update(Request $request, CourseEnrollment $course_enrollment)
    {
        $user = Auth::user();

        if ($user->hasRole('teacher')) {
            abort(403);
        }

        $data = $request->validate([
            'course_id' => 'required|exists:courses,id',
            'student_id' => 'nullable|exists:users,id',
        ]);

        if ($user->hasRole('student')) {
            if ($course_enrollment->student_id !== $user->id) {
                abort(403);
            }

            $data['student_id'] = $user->id;
        }

        if ($user->hasRole('master-admin') && empty($data['student_id'])) {
            return back()->withErrors([
                'student_id' => 'Please select a student.',
            ])->withInput();
        }

        $course = Course::findOrFail($data['course_id']);

        if ($course->isExpired()) {
            return back()->withErrors([
                'course_id' => 'This course has already expired.',
            ])->withInput();
        }

        $exists = CourseEnrollment::where('course_id', $data['course_id'])
            ->where('student_id', $data['student_id'])
            ->where('id', '!=', $course_enrollment->id)
            ->exists();

        if ($exists) {
            return back()->with('error', 'Already enrolled.')->withInput();
        }

        $course_enrollment->loadMissing('course');

        $previousStudentId = $course_enrollment->student_id;
        $previousTeacherId = optional($course_enrollment->course)->teacher_id;

        $course_enrollment->update($data);

        $this->userCourseStatusService->syncEnrollmentParticipants(
            $course_enrollment->fresh(),
            [$previousStudentId, $previousTeacherId]
        );

        return redirect()->route('course-enrollments.index')
            ->with('success', 'Enrollment updated successfully.');
    }

    public function destroy(CourseEnrollment $courseEnrollment)
    {
        $user = Auth::user();

        $courseEnrollment->loadMissing('course');

        if ($user->hasRole('teacher')) {
            abort_unless($courseEnrollment->course->teacher_id === $user->id, 403);
        }

        audit_log(
            'course_enrollments',
            $courseEnrollment->id,
            'deleted',
            'Enrollment deleted successfully',
            $courseEnrollment->toArray()
        );

        $participantIds = [
            $courseEnrollment->student_id,
            optional($courseEnrollment->course)->teacher_id,
        ];

        $courseEnrollment->delete();

        $this->userCourseStatusService->syncUsersByIds($participantIds);

        return back()->with('success', 'Enrollment deleted successfully.');
    }
}
