from dbmodel import *
from peewee import fn 
from markdown_pdf import Section
from functools import reduce 
from itertools import compress
import operator
from grader import get_grader
from collections import Counter
from .utils import error

def create_header(number_of_students: int) -> str:
    text = '## Ranking\n'
    text += f'#### Number of Students: {number_of_students}\n'
    text += '|Student|Points|Percentage|Passed|\n'
    text += '|-|-|-|-|\n'
    return text


def create_ranking_pdf(class_id: int, filter: list[Study]) -> list[Section]:
    if not filter:
        return error()

    filter = [(Student.study_id == study.id) for study in filter]
    expr = reduce(operator.or_, filter)
    students = [
        (student, Submission.select(fn.SUM(Submission.points)).where(Submission.student_id == student.id).scalar())
        for student in Student.select().where(expr).where(Student.class_id == class_id)
    ]
    students.sort(key = lambda tup: tup[1], reverse=True)
    
    sections = list()

    max_points = [lecture.points for lecture in Lecture.select().where(Lecture.class_id == students[0][0].class_id)]
    max = sum(max_points)
    
    # Table Header
    text = create_header(len(students))

    limit = 0
    for n, tup in enumerate(students, start=1):
        student, points = tup
        
        student_data = f'{n}. {student.prename} {student.surname}' 
        points = int(points) if points.is_integer() else points

        grader = get_grader(student.grader)
        p = [sub.points for sub in Submission.select().where(Submission.student_id == student.id)]
        passed = grader.get_final_grade(p, max_points)

        text += f'|{student_data}|{points}/{max}|{points/max:.1%}|{passed}|\n'

        limit += 1
        if limit > 29:
            sections.append(Section(text))
            limit = 0
            text = create_header(len(students))      

    if text:
        sections.append(Section(text))

    return sections
