<?php

namespace App\Http\Controllers;

use App\Models\Course;
use App\Models\CourseEnrollment;
use App\Models\CourseProgress;
use App\Models\CourseLesson;
use App\Models\Notification;
use App\Repositories\Contracts\CourseRepositoryInterface;
use App\Http\Traits\ResponseTrait;
use App\Http\Resources\ResponseCollection;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\DB;
use ZipArchive;

class CourseController extends Controller
{
    use ResponseTrait;

    private $courseRepository;

    public function __construct(CourseRepositoryInterface $courseRepository)
    {
        $this->courseRepository = $courseRepository;
    }

    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request)
    {
        $perPage = $request->per_page ? $request->per_page : 100;

        return new ResponseCollection(
            $this->paginateResponse($this->courseRepository->all($request), $perPage)
        );
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        // $request->validate([
        //     'name' => 'required|string|max:255',
        //     'location' => 'required|string|max:255',
        //     'owner_id' => 'required|numeric',
        // ]);

        $course = $this->courseRepository->create($request->toArray());

        return $this->successResponse($course, 'Course added successfully!');
    }

    /**
     * Display the specified resource.
     *
     * @param  \App\Models\Course  $course
     * @return \Illuminate\Http\Response
     */
    public function show(Course $course)
    {
        return $this->successResponse($course);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\Course  $course
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Course $course)
    {
        $this->courseRepository->update($course, $request->toArray());

        return $this->updateResponse('Course updated successfully!');
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Models\Course  $course
     * @return \Illuminate\Http\Response
     */
    public function destroy(Course $course)
    {
        $this->courseRepository->delete($course);

        return $this->updateResponse('Course deleted successfully!');
    }

    /**
     * Enroll user in a course
     */
    public function enroll(Request $request, $id)
    {
        $request->validate([
            'payment_method_id' => 'nullable|integer|exists:payment_methods,id',
        ]);

        $user = $request->user();
        $course = Course::findOrFail($id);

        // Check if already enrolled
        $existingEnrollment = CourseEnrollment::where('user_id', $user->id)
            ->where('course_id', $id)
            ->first();

        if ($existingEnrollment) {
            return response()->json([
                'code' => 422,
                'error' => true,
                'status' => 'error',
                'message' => 'You are already enrolled in this course'
            ], 422);
        }

        // Check if course is paid and process payment
        if ($course->is_paid && $course->price > 0) {
            if (!$request->payment_method_id) {
                return response()->json([
                    'code' => 422,
                    'error' => true,
                    'status' => 'error',
                    'message' => 'Payment method required for paid courses'
                ], 422);
            }
            // TODO: Process payment here
        }

        try {
            $enrollment = CourseEnrollment::create([
                'user_id' => $user->id,
                'course_id' => $id,
                'progress' => 0,
                'enrollment_date' => now(),
                'status' => 'enrolled',
                'payment_method_id' => $request->payment_method_id,
            ]);

            // Create initial progress record
            CourseProgress::create([
                'enrollment_id' => $enrollment->id,
                'course_id' => $id,
                'user_id' => $user->id,
                'progress_percentage' => 0,
                'lessons_completed' => 0,
                'time_spent_minutes' => 0,
            ]);

            return $this->successResponse([
                'enrollment' => [
                    'id' => $enrollment->id,
                    'course_id' => $enrollment->course_id,
                    'user_id' => $enrollment->user_id,
                    'enrolled_at' => $enrollment->enrollment_date->toISOString(),
                    'progress' => $enrollment->progress,
                    'status' => $enrollment->status,
                ],
            ], 'Enrolled in course successfully');

        } catch (\Exception $e) {
            return $this->errorResponse('Failed to enroll in course: ' . $e->getMessage());
        }
    }

    /**
     * Get user's progress in a course
     */
    public function getProgress(Request $request, $id)
    {
        $user = $request->user();
        $course = Course::findOrFail($id);
        
        $enrollment = CourseEnrollment::where('user_id', $user->id)
            ->where('course_id', $id)
            ->first();

        if (!$enrollment) {
            return response()->json([
                'code' => 404,
                'error' => true,
                'status' => 'error',
                'message' => 'You are not enrolled in this course'
            ], 404);
        }

        $progress = CourseProgress::where('enrollment_id', $enrollment->id)
            ->where('course_id', $id)
            ->whereNull('lesson_id')
            ->first();

        $totalLessons = CourseLesson::where('course_id', $id)->count();
        $lessonsCompleted = CourseProgress::where('enrollment_id', $enrollment->id)
            ->where('course_id', $id)
            ->whereNotNull('lesson_id')
            ->whereNotNull('completed_at')
            ->count();

        $progressPercentage = $totalLessons > 0 ? round(($lessonsCompleted / $totalLessons) * 100) : 0;

        return $this->successResponse([
            'enrollment_id' => $enrollment->id,
            'course_id' => $id,
            'progress_percentage' => $progressPercentage,
            'lessons_completed' => $lessonsCompleted,
            'total_lessons' => $totalLessons,
            'time_spent_minutes' => $progress->time_spent_minutes ?? 0,
            'last_accessed_at' => $enrollment->last_accessed_at?->toISOString(),
            'completed_at' => $enrollment->completed_at?->toISOString(),
            'certificate_eligible' => $progressPercentage >= 100 && ($course->certificate_available ?? false),
        ], 'Course progress retrieved successfully');
    }

    /**
     * Update course progress
     */
    public function updateProgress(Request $request, $id)
    {
        $request->validate([
            'lesson_id' => 'required|integer|exists:course_lessons,id',
            'completed' => 'required|boolean',
            'time_spent_seconds' => 'nullable|integer|min:0',
        ]);

        $user = $request->user();
        
        $enrollment = CourseEnrollment::where('user_id', $user->id)
            ->where('course_id', $id)
            ->first();

        if (!$enrollment) {
            return response()->json([
                'code' => 404,
                'error' => true,
                'status' => 'error',
                'message' => 'You are not enrolled in this course'
            ], 404);
        }

        // Verify lesson belongs to this course
        $lesson = CourseLesson::where('id', $request->lesson_id)
            ->where('course_id', $id)
            ->firstOrFail();

        try {
            DB::beginTransaction();

            // Update or create progress for this lesson
            $lessonProgress = CourseProgress::updateOrCreate(
                [
                    'enrollment_id' => $enrollment->id,
                    'lesson_id' => $request->lesson_id,
                ],
                [
                    'course_id' => $id,
                    'user_id' => $user->id,
                    'completed_at' => $request->completed ? now() : null,
                ]
            );

            // Update time spent
            if ($request->time_spent_seconds) {
                $lessonProgress->increment('time_spent_minutes', round($request->time_spent_seconds / 60));
            }

            // Update enrollment progress
            $totalLessons = CourseLesson::where('course_id', $id)->count();
            $lessonsCompleted = CourseProgress::where('enrollment_id', $enrollment->id)
                ->where('course_id', $id)
                ->whereNotNull('completed_at')
                ->count();

            $progressPercentage = $totalLessons > 0 ? round(($lessonsCompleted / $totalLessons) * 100) : 0;

            $enrollment->update([
                'progress' => $progressPercentage,
                'last_accessed_at' => now(),
            ]);

            // Update main progress record
            $mainProgress = CourseProgress::where('enrollment_id', $enrollment->id)
                ->where('course_id', $id)
                ->whereNull('lesson_id')
                ->first();

            if ($mainProgress) {
                $mainProgress->update([
                    'progress_percentage' => $progressPercentage,
                    'lessons_completed' => $lessonsCompleted,
                    'last_accessed_at' => now(),
                ]);
            }

            DB::commit();

            return $this->successResponse([
                'progress_percentage' => $progressPercentage,
                'lessons_completed' => $lessonsCompleted,
            ], 'Course progress updated successfully');

        } catch (\Exception $e) {
            DB::rollBack();
            return $this->errorResponse('Failed to update progress: ' . $e->getMessage());
        }
    }

    /**
     * Get course lessons
     */
    public function getLessons(Request $request, $id)
    {
        $user = $request->user();
        
        $enrollment = CourseEnrollment::where('user_id', $user->id)
            ->where('course_id', $id)
            ->first();

        if (!$enrollment) {
            return response()->json([
                'code' => 404,
                'error' => true,
                'status' => 'error',
                'message' => 'You are not enrolled in this course'
            ], 404);
        }

        $lessons = CourseLesson::where('course_id', $id)
            ->orderBy('order')
            ->get();

        // Get completed lessons for this enrollment
        $completedLessonIds = CourseProgress::where('enrollment_id', $enrollment->id)
            ->where('course_id', $id)
            ->whereNotNull('completed_at')
            ->pluck('lesson_id')
            ->toArray();

        $formattedLessons = $lessons->map(function($lesson, $index) use ($completedLessonIds) {
            $completed = in_array($lesson->id, $completedLessonIds);
            $unlocked = $index === 0 || in_array($lessons[$index - 1]->id ?? null, $completedLessonIds) || $lesson->is_free_preview;
            
            return [
                'id' => $lesson->id,
                'title' => $lesson->title,
                'description' => $lesson->description,
                'duration_minutes' => $lesson->duration_minutes,
                'video_url' => $lesson->video_url,
                'content_url' => $lesson->content_url,
                'order' => $lesson->order,
                'completed' => $completed,
                'unlocked' => $unlocked,
            ];
        });

        return $this->successResponse($formattedLessons->toArray(), 'Course lessons retrieved successfully');
    }

    /**
     * Download course for offline access
     */
    public function download(Request $request, $id)
    {
        $user = $request->user();
        
        $enrollment = CourseEnrollment::where('user_id', $user->id)
            ->where('course_id', $id)
            ->first();

        if (!$enrollment) {
            return response()->json([
                'code' => 404,
                'error' => true,
                'status' => 'error',
                'message' => 'You are not enrolled in this course'
            ], 404);
        }

        $course = Course::findOrFail($id);
        $lessons = CourseLesson::where('course_id', $id)->get();

        try {
            // Create temporary zip file
            $zipFilename = 'course_' . $id . '_' . time() . '.zip';
            $zipPath = storage_path('app/temp/' . $zipFilename);
            
            if (!file_exists(storage_path('app/temp'))) {
                mkdir(storage_path('app/temp'), 0755, true);
            }

            $zip = new ZipArchive();
            if ($zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== TRUE) {
                return $this->errorResponse('Failed to create download package');
            }

            // Add course info file
            $zip->addFromString('course_info.json', json_encode([
                'title' => $course->title,
                'description' => $course->description,
                'lessons_count' => $lessons->count(),
            ]));

            // Add lessons (metadata only - actual files would need to be downloaded separately)
            foreach ($lessons as $lesson) {
                $zip->addFromString("lessons/lesson_{$lesson->id}.json", json_encode([
                    'id' => $lesson->id,
                    'title' => $lesson->title,
                    'description' => $lesson->description,
                    'duration_minutes' => $lesson->duration_minutes,
                    'order' => $lesson->order,
                ]));
            }

            $zip->close();

            return response()->download($zipPath, $zipFilename)->deleteFileAfterSend(true);

        } catch (\Exception $e) {
            return $this->errorResponse('Failed to create download package: ' . $e->getMessage());
        }
    }

    /**
     * Mark course as completed
     */
    public function complete(Request $request, $id)
    {
        $user = $request->user();
        
        $enrollment = CourseEnrollment::where('user_id', $user->id)
            ->where('course_id', $id)
            ->first();

        if (!$enrollment) {
            return response()->json([
                'code' => 404,
                'error' => true,
                'status' => 'error',
                'message' => 'You are not enrolled in this course'
            ], 404);
        }

        $course = Course::findOrFail($id);
        $totalLessons = CourseLesson::where('course_id', $id)->count();
        $lessonsCompleted = CourseProgress::where('enrollment_id', $enrollment->id)
            ->where('course_id', $id)
            ->whereNotNull('completed_at')
            ->count();

        if ($lessonsCompleted < $totalLessons) {
            return response()->json([
                'code' => 422,
                'error' => true,
                'status' => 'error',
                'message' => 'Cannot complete course. Please complete all lessons first.'
            ], 422);
        }

        $enrollment->update([
            'status' => 'completed',
            'completed_at' => now(),
            'progress' => 100,
        ]);

        $certificateEligible = $course->certificate_available ?? false;
        $certificateUrl = null;

        // TODO: Generate certificate if eligible
        if ($certificateEligible) {
            // Certificate generation logic here
        }

        return $this->successResponse([
            'certificate_eligible' => $certificateEligible,
            'certificate_url' => $certificateUrl,
        ], 'Course completed successfully');
    }

    /**
     * Get user's enrolled courses
     */
    public function getEnrolled(Request $request)
    {
        $user = $request->user();
        $perPage = $request->input('limit', 20);
        $perPage = min($perPage, 100);

        $query = CourseEnrollment::where('user_id', $user->id)
            ->with('course')
            ->orderBy('last_accessed_at', 'desc')
            ->orderBy('created_at', 'desc');

        // Filter by status
        if ($request->has('status')) {
            $statusMap = [
                'active' => 'enrolled',
                'completed' => 'completed',
                'paused' => 'dropped',
            ];
            $query->where('status', $statusMap[$request->status] ?? $request->status);
        }

        $enrollments = $query->paginate($perPage);

        $formattedEnrollments = $enrollments->map(function($enrollment) {
            return [
                'id' => $enrollment->id,
                'course' => [
                    'id' => $enrollment->course->id,
                    'title' => $enrollment->course->title,
                    'description' => $enrollment->course->description,
                    'thumbnail' => $enrollment->course->image,
                ],
                'progress' => $enrollment->progress,
                'enrolled_at' => $enrollment->enrollment_date->toISOString(),
                'last_accessed_at' => $enrollment->last_accessed_at?->toISOString(),
                'status' => $enrollment->status,
            ];
        });

        return $this->paginatedResponse(
            $enrollments->setCollection($formattedEnrollments),
            'Enrolled courses retrieved successfully'
        );
    }

    /**
     * Sync offline course progress with server
     */
    public function syncProgress(Request $request, $id)
    {
        $request->validate([
            'lessons_completed' => 'required|array',
            'lessons_completed.*.lesson_id' => 'required|integer|exists:course_lessons,id',
            'lessons_completed.*.completed_at' => 'required|date',
            'lessons_completed.*.time_spent_seconds' => 'required|integer|min:0',
            'last_sync_at' => 'nullable|date',
        ]);

        $user = $request->user();
        
        $enrollment = CourseEnrollment::where('user_id', $user->id)
            ->where('course_id', $id)
            ->first();

        if (!$enrollment) {
            return response()->json([
                'code' => 404,
                'error' => true,
                'status' => 'error',
                'message' => 'You are not enrolled in this course'
            ], 404);
        }

        try {
            DB::beginTransaction();

            $syncedCount = 0;
            foreach ($request->lessons_completed as $lessonData) {
                // Verify lesson belongs to this course
                $lesson = CourseLesson::where('id', $lessonData['lesson_id'])
                    ->where('course_id', $id)
                    ->first();

                if (!$lesson) {
                    continue;
                }

                CourseProgress::updateOrCreate(
                    [
                        'enrollment_id' => $enrollment->id,
                        'lesson_id' => $lessonData['lesson_id'],
                    ],
                    [
                        'course_id' => $id,
                        'user_id' => $user->id,
                        'completed_at' => $lessonData['completed_at'],
                        'time_spent_minutes' => round($lessonData['time_spent_seconds'] / 60),
                    ]
                );

                $syncedCount++;
            }

            // Recalculate overall progress
            $totalLessons = CourseLesson::where('course_id', $id)->count();
            $lessonsCompleted = CourseProgress::where('enrollment_id', $enrollment->id)
                ->where('course_id', $id)
                ->whereNotNull('completed_at')
                ->count();

            $progressPercentage = $totalLessons > 0 ? round(($lessonsCompleted / $totalLessons) * 100) : 0;

            $enrollment->update([
                'progress' => $progressPercentage,
                'last_accessed_at' => now(),
            ]);

            // Update main progress record
            $mainProgress = CourseProgress::where('enrollment_id', $enrollment->id)
                ->where('course_id', $id)
                ->whereNull('lesson_id')
                ->first();

            if ($mainProgress) {
                $mainProgress->update([
                    'progress_percentage' => $progressPercentage,
                    'lessons_completed' => $lessonsCompleted,
                    'last_accessed_at' => now(),
                ]);
            }

            DB::commit();

            return $this->successResponse([
                'synced_count' => $syncedCount,
                'updated_progress' => $progressPercentage,
            ], 'Course progress synced successfully');

        } catch (\Exception $e) {
            DB::rollBack();
            return $this->errorResponse('Failed to sync progress: ' . $e->getMessage());
        }
    }
}
