import { Get, Body, Post, Route, Tags, SuccessResponse, Response, Security, Path, Request, Query } from 'tsoa';
import { ValidationError } from '../middleware/errorHandler';
import { CoursesStudentService } from '../services/CoursesStudent.service';
import {
    EnrollCourseResponse,
    ListEnrolledCoursesResponse,
    GetCourseLearningResponse,
    GetLessonContentResponse,
    CheckLessonAccessResponse,
    SaveVideoProgressResponse,
    SaveVideoProgressBody,
    GetVideoProgressResponse,
    CompleteLessonResponse,
    SubmitQuizResponse,
    SubmitQuizBody,
    GetQuizAttemptsResponse,
} from '../types/CoursesStudent.types';
import { EnrollmentStatus } from '@prisma/client';

@Route('api/students')
@Tags('CoursesStudent')
export class CoursesStudentController {

    private service = new CoursesStudentService();

    /**
     * ลงทะเบียนเรียนในคอร์ส
     * Enroll in a course
     * @param courseId - รหัสคอร์ส / Course ID
     */
    @Post('courses/{courseId}/enroll')
    @Security('jwt', ['student'])
    @SuccessResponse('200', 'Enrolled successfully')
    @Response('401', 'Invalid or expired token')
    @Response('404', 'Course not found')
    @Response('409', 'Already enrolled in this course')
    public async enrollCourse(@Request() request: any, @Path() courseId: number): Promise<EnrollCourseResponse> {
        const token = request.headers.authorization?.replace('Bearer ', '');
        if (!token) {
            throw new ValidationError('No token provided');
        }
        return await this.service.enrollCourse({ token, course_id: courseId });
    }

    /**
     * ดึงรายการคอร์สที่ลงทะเบียนเรียน
     * Get list of enrolled courses
     * @param page - หน้าที่ต้องการดึง / Page number
     * @param limit - จำนวนรายการต่อหน้า / Items per page
     * @param status - สถานะการลงทะเบียน / Enrollment status
     */
    @Get('courses')
    @Security('jwt', ['student'])
    @SuccessResponse('200', 'Enrolled courses retrieved successfully')
    @Response('401', 'Invalid or expired token')
    public async getEnrolledCourses(
        @Request() request: any,
        @Query() page?: number,
        @Query() limit?: number,
        @Query() status?: EnrollmentStatus
    ): Promise<ListEnrolledCoursesResponse> {
        const token = request.headers.authorization?.replace('Bearer ', '');
        if (!token) {
            throw new ValidationError('No token provided');
        }
        return await this.service.GetEnrolledCourses({ token, page, limit, status });
    }

    /**
     * ดึงข้อมูลหน้าเรียนคอร์ส (พร้อมสถานะการล็อคบทเรียน)
     * Get course learning page with lesson lock status
     * @param courseId - รหัสคอร์ส / Course ID
     */
    @Get('courses/{courseId}/learn')
    @Security('jwt', ['student'])
    @SuccessResponse('200', 'Course learning data retrieved successfully')
    @Response('401', 'Invalid or expired token')
    @Response('403', 'Not enrolled in this course')
    @Response('404', 'Course not found')
    public async getCourseLearning(@Request() request: any, @Path() courseId: number): Promise<GetCourseLearningResponse> {
        const token = request.headers.authorization?.replace('Bearer ', '');
        if (!token) {
            throw new ValidationError('No token provided');
        }
        return await this.service.getCourseLearning({ token, course_id: courseId });
    }

    /**
     * ดึงเนื้อหาบทเรียน (ตรวจสอบเงื่อนไขก่อนหน้า)
     * Get lesson content (checks prerequisites)
     * @param courseId - รหัสคอร์ส / Course ID
     * @param lessonId - รหัสบทเรียน / Lesson ID
     */
    @Get('courses/{courseId}/lessons/{lessonId}')
    @Security('jwt', ['student'])
    @SuccessResponse('200', 'Lesson content retrieved successfully')
    @Response('401', 'Invalid or expired token')
    @Response('403', 'Not enrolled in this course or lesson is locked')
    @Response('404', 'Lesson not found')
    public async getLessonContent(
        @Request() request: any,
        @Path() courseId: number,
        @Path() lessonId: number
    ): Promise<GetLessonContentResponse> {
        const token = request.headers.authorization?.replace('Bearer ', '');
        if (!token) {
            throw new ValidationError('No token provided');
        }
        return await this.service.getlessonContent({ token, course_id: courseId, lesson_id: lessonId });
    }

    /**
     * ตรวจสอบสิทธิ์เข้าถึงบทเรียน (ไม่โหลดเนื้อหา)
     * Check lesson access without loading content
     * @param courseId - รหัสคอร์ส / Course ID
     * @param lessonId - รหัสบทเรียน / Lesson ID
     */
    @Get('courses/{courseId}/lessons/{lessonId}/access-check')
    @Security('jwt', ['student'])
    @SuccessResponse('200', 'Access check completed')
    @Response('401', 'Invalid or expired token')
    @Response('404', 'Lesson not found')
    public async checkLessonAccess(
        @Request() request: any,
        @Path() courseId: number,
        @Path() lessonId: number
    ): Promise<CheckLessonAccessResponse> {
        const token = request.headers.authorization?.replace('Bearer ', '');
        if (!token) {
            throw new ValidationError('No token provided');
        }
        return await this.service.checkAccessLesson({ token, course_id: courseId, lesson_id: lessonId });
    }

    /**
     * บันทึกความคืบหน้าการดูวิดีโอ
     * Save video progress
     * @param lessonId - รหัสบทเรียน / Lesson ID
     */
    @Post('lessons/{lessonId}/progress')
    @Security('jwt', ['student'])
    @SuccessResponse('200', 'Video progress saved successfully')
    @Response('401', 'Invalid or expired token')
    @Response('403', 'Not enrolled in this course')
    @Response('404', 'Lesson not found')
    public async saveVideoProgress(
        @Request() request: any,
        @Path() lessonId: number,
        @Body() body: SaveVideoProgressBody
    ): Promise<SaveVideoProgressResponse> {
        const token = request.headers.authorization?.replace('Bearer ', '');
        if (!token) {
            throw new ValidationError('No token provided');
        }
        return await this.service.saveVideoProgress({
            token,
            lesson_id: lessonId,
            video_progress_seconds: body.video_progress_seconds,
            video_duration_seconds: body.video_duration_seconds,
        });
    }

    /**
     * ดึงความคืบหน้าการดูวิดีโอ
     * Get video progress
     * @param lessonId - รหัสบทเรียน / Lesson ID
     */
    @Get('lessons/{lessonId}/progress')
    @Security('jwt', ['student'])
    @SuccessResponse('200', 'Video progress retrieved successfully')
    @Response('401', 'Invalid or expired token')
    @Response('403', 'Not enrolled in this course')
    @Response('404', 'Lesson not found')
    public async getVideoProgress(
        @Request() request: any,
        @Path() lessonId: number
    ): Promise<GetVideoProgressResponse> {
        const token = request.headers.authorization?.replace('Bearer ', '');
        if (!token) {
            throw new ValidationError('No token provided');
        }
        return await this.service.getVideoProgress({ token, lesson_id: lessonId });
    }

    /**
     * ทำเครื่องหมายบทเรียนว่าเรียนจบ
     * Mark lesson as complete
     * @param courseId - รหัสคอร์ส / Course ID
     * @param lessonId - รหัสบทเรียน / Lesson ID
     */
    @Post('courses/{courseId}/lessons/{lessonId}/complete')
    @Security('jwt', ['student'])
    @SuccessResponse('200', 'Lesson marked as complete')
    @Response('401', 'Invalid or expired token')
    @Response('403', 'Not enrolled in this course')
    @Response('404', 'Lesson not found')
    public async completeLesson(
        @Request() request: any,
        @Path() courseId: number,
        @Path() lessonId: number
    ): Promise<CompleteLessonResponse> {
        const token = request.headers.authorization?.replace('Bearer ', '');
        if (!token) {
            throw new ValidationError('No token provided');
        }
        return await this.service.completeLesson({ token, lesson_id: lessonId });
    }

    /**
     * ส่งคำตอบ Quiz และรับผลคะแนน
     * Submit quiz answers and get score
     * @param courseId - รหัสคอร์ส / Course ID
     * @param lessonId - รหัสบทเรียน / Lesson ID
     */
    @Post('courses/{courseId}/lessons/{lessonId}/quiz/submit')
    @Security('jwt', ['student'])
    @SuccessResponse('200', 'Quiz submitted successfully')
    @Response('401', 'Invalid or expired token')
    @Response('403', 'Not enrolled in this course')
    @Response('404', 'Lesson or quiz not found')
    public async submitQuiz(
        @Request() request: any,
        @Path() courseId: number,
        @Path() lessonId: number,
        @Body() body: SubmitQuizBody
    ): Promise<SubmitQuizResponse> {
        const token = request.headers.authorization?.replace('Bearer ', '');
        if (!token) {
            throw new ValidationError('No token provided');
        }
        return await this.service.submitQuiz({
            token,
            course_id: courseId,
            lesson_id: lessonId,
            answers: body.answers,
        });
    }

    /**
     * ดึงคะแนน Quiz ที่เคยทำ
     * Get quiz attempts and scores for a lesson
     * @param courseId - รหัสคอร์ส / Course ID
     * @param lessonId - รหัสบทเรียน / Lesson ID
     */
    @Get('courses/{courseId}/lessons/{lessonId}/quiz/attempts')
    @Security('jwt', ['student'])
    @SuccessResponse('200', 'Quiz attempts retrieved successfully')
    @Response('401', 'Invalid or expired token')
    @Response('403', 'Not enrolled in this course')
    @Response('404', 'Lesson or quiz not found')
    public async getQuizAttempts(
        @Request() request: any,
        @Path() courseId: number,
        @Path() lessonId: number
    ): Promise<GetQuizAttemptsResponse> {
        const token = request.headers.authorization?.replace('Bearer ', '');
        if (!token) {
            throw new ValidationError('No token provided');
        }
        return await this.service.getQuizAttempts({
            token,
            course_id: courseId,
            lesson_id: lessonId,
        });
    }
}
