from src.errors.errors import *
from src.services.services import Services
from datetime import date
import re

class UI():
    def __init__(self,service:Services) -> None:
        self.__service = service
    
    def __print_menu(self) -> None:
        print("""
        1.Manage students
        2.Manage assignments
        3.Manage grades
        4.Statistics
        0.Exit
        """)
    
    def __print_student_menu(self) -> None:
        print("""
        1.Add student
        2.Remove student
        3.Update student
        4.List students
        5.Back
        """)
    
    def __print_assignment_menu(self) -> None:
        print("""
        1.Add assignment
        2.Remove assignment
        3.Update assignment
        4.List assignments
        5.Give assignment to a student
        6.Give assignment to a group of students
        7.Back
        """)
    
    def __print_statistics_menu(self) -> None:
        print("""
        1.List students with a given assignment
        2.List students late on an assignment
        3.List students with the best school situation
        4.Back
        """)
    
    def start(self) -> None:
        while True:
            self.__print_menu()
            command = input("Enter command: ")
            match command:
                case "1":
                    self.__manage_students()
                case "2":
                    self.__manage_assignments()
                case "3":
                    self.__manage_grades()
                case "4":
                    self.__statistics()
                case "0":
                    break
                case _:
                    print("Invalid command")
    
    def __manage_students(self) -> None:
        while True:
            self.__print_student_menu()
            command = input("Enter command: ")
            match command:
                case "1":
                    self.__add_student()
                case "2":
                    self.__remove_student()
                case "3":
                    self.__update_student()
                case "4":
                    self.__list_students()
                case "5":
                    break
                case _:
                    print("Invalid command")
    
    def __manage_assignments(self) -> None:
        while True:
            self.__print_assignment_menu()
            command = input("Enter command: ")
            match command:
                case "1":
                    self.__add_assignment()
                case "2":
                    self.__remove_assignment()
                case "3":
                    self.__update_assignment()
                case "4":
                    self.__list_assignments()
                case "5":
                    self.__give_assignment_to_student()
                case "6":
                    self.__give_assignment_to_group()
                case "7":
                    break
                case _:
                    print("Invalid command")
    
    def __manage_grades(self) -> None:
        try:
            student_id = input("Enter student id: ")
            ungraded_assignments = self.__service.list_ungraded_assignments_for_student(student_id)
            if len(ungraded_assignments) == 0:
                print("Student has no ungraded assignments")
                return
            for i,assignment in enumerate(ungraded_assignments):
                print(f"{i+1}. {assignment}")
            command = input("Enter assignment number: ")
            if re.fullmatch("\d+",command) is None or int(command) < 1 or int(command) > len(ungraded_assignments):
                print("Invalid command")
                return
            assignment = ungraded_assignments[int(command)-1]
            grade = input("Enter grade: ")
            if re.fullmatch("\d+(.\d)?+",grade) is None or float(grade) < 1 or float(grade) > 10:
                print("Invalid grade")
                return
            self.__service.add_grade(student_id,assignment.get_assignment_id(),float(grade))
        except StudentNotFoundError as e:
            print(e)
        

    def __statistics(self) -> None:
        while True:
            self.__print_statistics_menu()
            command = input("Enter command: ")
            match command:
                case "1":
                    self.__list_students_with_assignment()
                case "2":
                    self.__list_students_late_on_assignment()
                case "3":
                    self.__list_students_best_school_situation()
                case "4":
                    break
                case _:
                    print("Invalid command")
    
    def __add_student(self) -> None:
        student_id = input("Enter student id: ")
        name = input("Enter student name: ")
        group = input("Enter student group: ")
        if student_id == "" or name == "" or group == "":
            print("Invalid student")
            return
        try:
            self.__service.add_student(student_id, name, group)
        except StudentAlreadyExistsError as e:
            print(e)

    def __remove_student(self) -> None:
        student_id = input("Enter student id: ")
        try:
            self.__service.remove_student(student_id)
        except StudentNotFoundError as e:
            print(e)
    
    def __update_student(self) -> None:
        student_id = input("Enter student id: ")
        name = input("Enter student name: ")
        group = input("Enter student group: ")
        if student_id == "" or name == "" or group == "":
            print("Invalid student")
            return
        try:
            self.__service.update_student(student_id, name, group)
        except StudentNotFoundError as e:
            print(e)
    
    def __list_students(self) -> None:
        students = self.__service.list_students()
        for student in students:
            print(student)
    
    def __add_assignment(self) -> None:
        assignment_id = input("Enter assignment id: ")
        description = input("Enter assignment description: ")
        day = input("Enter assignment deadline day: ")
        month = input("Enter assignment deadline month: ")
        year = input("Enter assignment deadline year: ")
        if assignment_id == "" or description == "" or day == "" or month == "" or year == "":
            print("Invalid assignment")
            return
        try:
            deadline = date(int(year), int(month), int(day))
            self.__service.add_assignment(assignment_id, description, deadline)
        except AssignmentAlreadyExistsError as e:
            print(e)
        except ValueError as e:
            print("Invalid date")
    
    def __remove_assignment(self) -> None:
        assignment_id = input("Enter assignment id: ")
        try:
            self.__service.remove_assignment(assignment_id)
        except AssignmentNotFoundError as e:
            print(e)
    
    def __update_assignment(self) -> None:
        assignment_id = input("Enter assignment id: ")
        description = input("Enter assignment description: ")
        day = input("Enter assignment deadline day: ")
        month = input("Enter assignment deadline month: ")
        year = input("Enter assignment deadline year: ")
        if assignment_id == "" or description == "" or day == "" or month == "" or year == "":
            print("Invalid assignment")
            return
        try:
            deadline = date(int(year), int(month), int(day))
            self.__service.update_assignment(assignment_id, description, deadline)
        except AssignmentNotFoundError as e:
            print(e)
        except ValueError as e:
            print("Invalid date")
    
    def __list_assignments(self) -> None:
        assignments = self.__service.list_assignments()
        for assignment in assignments:
            print(assignment)

    def __give_assignment_to_student(self) -> None:
        student_id = input("Enter student id: ")
        assignment_id = input("Enter assignment id: ")
        try:
            self.__service.give_assignment_to_student(student_id, assignment_id)
        except StudentNotFoundError as e:
            print(e)
        except AssignmentNotFoundError as e:
            print(e)
        except GradeAlreadyExistsError as e:
            print(e)
        
    def __give_assignment_to_group(self) -> None:
        group = input("Enter group: ")
        assignment_id = input("Enter assignment id: ")
        try:
            self.__service.give_assignment_to_group(group, assignment_id)
        except AssignmentNotFoundError as e:
            print(e)

    def __list_students_with_assignment(self) -> None:
        assignment_id = input("Enter assignment id: ")
        students = self.__service.list_students_with_assignment(assignment_id)
        for student in students:
            print(student)
    
    def __list_students_late_on_assignment(self) -> None:
        assignment_id = input("Enter assignment id: ")
        students = self.__service.list_students_late_on_assignment(assignment_id)
        for student in students:
            print(student)
    
    def __list_students_best_school_situation(self) -> None:
        students = self.__service.list_students_best_school_situation()
        for student in students:
            print(student)
    
