import { prisma } from '../config/database';
import { config } from '../config';
import { logger } from '../config/logger';
import { UnauthorizedError, ValidationError, ForbiddenError, NotFoundError } from '../middleware/errorHandler';
import jwt from 'jsonwebtoken';
import {
    ListPendingCoursesResponse,
    GetCourseDetailForAdminResponse,
    ApproveCourseResponse,
    RejectCourseResponse,
} from '../types/AdminCourseApproval.types';

export class AdminCourseApprovalService {

    /**
     * Get all pending courses for admin review
     */
    static async listPendingCourses(): Promise<ListPendingCoursesResponse> {
        try {
            const courses = await prisma.course.findMany({
                where: { status: 'PENDING' },
                orderBy: { updated_at: 'desc' },
                include: {
                    creator: {
                        select: { id: true, username: true, email: true }
                    },
                    instructors: {
                        include: {
                            user: {
                                select: { id: true, username: true, email: true }
                            }
                        }
                    },
                    chapters: {
                        include: {
                            lessons: true
                        }
                    },
                    courseApprovals: {
                        where: { action: 'SUBMITTED' },
                        orderBy: { created_at: 'desc' },
                        take: 1,
                        include: {
                            submitter: {
                                select: { id: true, username: true, email: true }
                            }
                        }
                    }
                }
            });

            const data = courses.map(course => ({
                id: course.id,
                title: course.title as { th: string; en: string },
                slug: course.slug,
                description: course.description as { th: string; en: string },
                thumbnail_url: course.thumbnail_url,
                status: course.status,
                created_at: course.created_at,
                updated_at: course.updated_at,
                created_by: course.created_by,
                creator: course.creator,
                instructors: course.instructors.map(i => ({
                    user_id: i.user_id,
                    is_primary: i.is_primary,
                    user: i.user
                })),
                chapters_count: course.chapters.length,
                lessons_count: course.chapters.reduce((sum, ch) => sum + ch.lessons.length, 0),
                latest_submission: course.courseApprovals[0] ? {
                    id: course.courseApprovals[0].id,
                    submitted_by: course.courseApprovals[0].submitted_by,
                    created_at: course.courseApprovals[0].created_at,
                    submitter: course.courseApprovals[0].submitter
                } : null
            }));

            return {
                code: 200,
                message: 'Pending courses retrieved successfully',
                data,
                total: data.length
            };
        } catch (error) {
            logger.error('Failed to list pending courses', { error });
            throw error;
        }
    }

    /**
     * Get course details for admin review
     */
    static async getCourseDetail(courseId: number): Promise<GetCourseDetailForAdminResponse> {
        try {
            const course = await prisma.course.findUnique({
                where: { id: courseId },
                include: {
                    category: {
                        select: { id: true, name: true }
                    },
                    creator: {
                        select: { id: true, username: true, email: true }
                    },
                    instructors: {
                        include: {
                            user: {
                                select: { id: true, username: true, email: true }
                            }
                        }
                    },
                    chapters: {
                        orderBy: { sort_order: 'asc' },
                        include: {
                            lessons: {
                                orderBy: { sort_order: 'asc' },
                                select: {
                                    id: true,
                                    title: true,
                                    type: true,
                                    sort_order: true,
                                    is_published: true
                                }
                            }
                        }
                    },
                    courseApprovals: {
                        orderBy: { created_at: 'desc' },
                        include: {
                            submitter: {
                                select: { id: true, username: true, email: true }
                            },
                            reviewer: {
                                select: { id: true, username: true, email: true }
                            }
                        }
                    }
                }
            });

            if (!course) {
                throw new NotFoundError('Course not found');
            }

            return {
                code: 200,
                message: 'Course details retrieved successfully',
                data: {
                    id: course.id,
                    title: course.title as { th: string; en: string },
                    slug: course.slug,
                    description: course.description as { th: string; en: string },
                    thumbnail_url: course.thumbnail_url,
                    price: Number(course.price),
                    is_free: course.is_free,
                    have_certificate: course.have_certificate,
                    status: course.status,
                    created_at: course.created_at,
                    updated_at: course.updated_at,
                    category: course.category ? {
                        id: course.category.id,
                        name: course.category.name as { th: string; en: string }
                    } : null,
                    creator: course.creator,
                    instructors: course.instructors.map(i => ({
                        user_id: i.user_id,
                        is_primary: i.is_primary,
                        user: i.user
                    })),
                    chapters: course.chapters.map(ch => ({
                        id: ch.id,
                        title: ch.title as { th: string; en: string },
                        sort_order: ch.sort_order,
                        is_published: ch.is_published,
                        lessons: ch.lessons.map(l => ({
                            id: l.id,
                            title: l.title as { th: string; en: string },
                            type: l.type,
                            sort_order: l.sort_order,
                            is_published: l.is_published
                        }))
                    })),
                    approval_history: course.courseApprovals.map(a => ({
                        id: a.id,
                        action: a.action,
                        comment: a.comment,
                        created_at: a.created_at,
                        submitter: a.submitter,
                        reviewer: a.reviewer
                    }))
                }
            };
        } catch (error) {
            logger.error('Failed to get course detail', { error });
            throw error;
        }
    }

    /**
     * Approve a course
     */
    static async approveCourse(token: string, courseId: number, comment?: string): Promise<ApproveCourseResponse> {
        try {
            const decoded = jwt.verify(token, config.jwt.secret) as { id: number };

            const course = await prisma.course.findUnique({ where: { id: courseId } });
            if (!course) {
                throw new NotFoundError('Course not found');
            }

            if (course.status !== 'PENDING') {
                throw new ValidationError('Course is not pending for approval');
            }

            await prisma.$transaction([
                // Update course status
                prisma.course.update({
                    where: { id: courseId },
                    data: { 
                        status: 'APPROVED',
                        approved_by: decoded.id,
                        approved_at: new Date()
                    }
                }),
                // Create approval record
                prisma.courseApproval.create({
                    data: {
                        course_id: courseId,
                        submitted_by: course.created_by,
                        reviewed_by: decoded.id,
                        action: 'APPROVED',
                        previous_status: course.status,
                        new_status: 'APPROVED',
                        comment: comment || null
                    }
                })
            ]);

            return {
                code: 200,
                message: 'Course approved successfully'
            };
        } catch (error) {
            logger.error('Failed to approve course', { error });
            throw error;
        }
    }

    /**
     * Reject a course
     */
    static async rejectCourse(token: string, courseId: number, comment: string): Promise<RejectCourseResponse> {
        try {
            const decoded = jwt.verify(token, config.jwt.secret) as { id: number };

            const course = await prisma.course.findUnique({ where: { id: courseId } });
            if (!course) {
                throw new NotFoundError('Course not found');
            }

            if (course.status !== 'PENDING') {
                throw new ValidationError('Course is not pending for approval');
            }

            if (!comment || comment.trim() === '') {
                throw new ValidationError('Comment is required when rejecting a course');
            }

            await prisma.$transaction([
                // Update course status back to DRAFT
                prisma.course.update({
                    where: { id: courseId },
                    data: { 
                        status: 'DRAFT',
                        rejection_reason: comment,
                        approved_by: null,
                        approved_at: null
                     }
                }),
                // Create rejection record
                prisma.courseApproval.create({
                    data: {
                        course_id: courseId,
                        submitted_by: course.created_by,
                        reviewed_by: decoded.id,
                        action: 'REJECTED',
                        previous_status: course.status,
                        new_status: 'DRAFT',
                        comment: comment
                    }
                })
            ]);

            return {
                code: 200,
                message: 'Course rejected successfully'
            };
        } catch (error) {
            logger.error('Failed to reject course', { error });
            throw error;
        }
    }
}
