from peewee import *
from datetime import datetime

import json
from typing import TextIO
from pathlib import Path

db = SqliteDatabase(None, autoconnect=False)

class BaseModel(Model):
    class Meta:
        database = db

class Class(BaseModel):
    name = CharField()
    created_at = DateTimeField(default=datetime.now)

class Student(BaseModel):
    prename = CharField()
    surname = CharField()
    sex = CharField()
    class_id = ForeignKeyField(Class, backref='class')
    created_at = DateTimeField(default=datetime.now)

class Lecture(BaseModel):
    title = CharField()
    points = IntegerField()
    class_id = ForeignKeyField(Class, backref='class')
    created_at = DateTimeField(default=datetime.now)

class Submission(BaseModel):
    student_id = ForeignKeyField(Student, backref='student')
    lecture_id = ForeignKeyField(Lecture, backref='lecture')
    points = FloatField()
    created_at = DateTimeField(default=datetime.now)

def load_from_json(fp: Path) -> None:
    '''
    Rebuilding Database from a given json
    '''
    with open(fp, "r") as file:
        data = json.load(file)
    
    for c_k, c_v in data.items():
        Class.create(
            name=c_k,
            id=c_v["DB ID"],
            created_at=c_v["Date"]
        )
        #print(f"KLASSE = {c.id} {c.name} ({c.created_at})")

        for student in c_v["Students"]:
            Student.create(
                id=student["DB ID"],
                created_at=student["Date"],
                prename=student["First Name"],
                surname=student["Last Name"],
                sex=student["Sex"],
                class_id=c_v["DB ID"]
            )
            #print(f"STUDENT = {s.id}. {s.prename} {s.surname} {s.sex} ({s.created_at}) Klasse: {s.class_id}")
            
            for submission in student["Submissions"]:
                Submission.create(
                    id=submission["DB ID"],
                    created_at=submission["Date"],
                    points=submission["Points"],
                    lecture_id=submission["Lecture ID"],
                    student_id=student["DB ID"]
                )
                #print(f"SUBMISSION = {sub.id}. {sub.points} Lecture: {sub.lecture_id} Student: {sub.student_id} ({sub.created_at})")

        for lecture in c_v["Lectures"]:
            Lecture.create(
                id=lecture["DB ID"],
                created_at=lecture["Date"],
                title=lecture["Title"],
                points=lecture["Points"],
                class_id=c_v["DB ID"]
            )
            #print(f"LECTURE = {l.id}. {l.title} {l.points} ({l.created_at}) Klasse: {l.class_id}")

def dump_to_json(fp: Path, indent=None) -> None:
    '''
    Dump existing Database to Json
    '''
    classes = Class.select()
    d = {c.name: {
            "DB ID": int(c.id),
            "Date": c.created_at.isoformat(),
            "Students": [
                    {
                    "DB ID": s.id,
                    "Date": s.created_at.isoformat(),
                    "First Name": s.prename,
                    "Last Name": s.surname,
                    "Sex": s.sex,
                    "Submissions": [
                        {
                        "DB ID": sub.id,
                        "Date": sub.created_at.isoformat(),
                        "Points": sub.points,
                        "Lecture ID": sub.lecture_id.id
                        }
                        for sub in Submission.select().where(Submission.student_id == s.id)
                        ]
                    } 
                    for s in Student.select().where(Student.class_id == c.id)
                ],
            "Lectures": [
                    {
                    "DB ID": l.id,
                    "Date": l.created_at.isoformat(),
                    "Title": l.title,
                    "Points": l.points
                    }
                    for l in Lecture.select().where(Lecture.class_id == c.id)
                ],
            } 
        for c in classes
    }
    
    with open(fp, "w") as file:
        json.dump(d, file, indent=indent)

db.init('test.db')
db.connect()
db.create_tables([Class, Student, Lecture, Submission])

def main():
    import random
    # Generate Test Data 
    class1 = Class.create(name="WiSe 22/23")
    class2 = Class.create(name="WiSe 23/24")
    class3 = Class.create(name="WiSe 24/25")

    phil = Student.create(prename="Phil", surname="Keier", sex="Male", class_id=class1.id)
    calvin = Student.create(prename="Calvin", surname="Brandt", sex="Male", class_id=class2.id)
    nova = Student.create(prename="Nova", surname="Eib", sex="Female", class_id=class1.id)
    kathi = Student.create(prename="Katharina", surname="Walz", sex="Female", class_id=class3.id)
    victoria = Student.create(prename="Victoria", surname="Möller", sex="Female", class_id=class3.id)

    lec1 = Lecture.create(title="Tutorial 1", points=30, class_id=class1.id)
    lec2 = Lecture.create(title="Tutorial 1", points=30, class_id=class3.id)
    lec3 = Lecture.create(title="Tutorial 2", points=20, class_id=class1.id)
    lec4 = Lecture.create(title="Tutorial 2", points=20, class_id=class2.id)
    lec5 = Lecture.create(title="Extended Applications", points=44, class_id=class1.id)

    sub1_phil = Submission.create(student_id=phil.id, lecture_id=lec1.id, points=random.randint(0, lec1.points))
    sub2_phil = Submission.create(student_id=phil.id, lecture_id=lec3.id, points=random.randint(0, lec3.points))
    sub3_phil = Submission.create(student_id=phil.id, lecture_id=lec5.id, points=random.randint(0, lec5.points))
    sub1_nova = Submission.create(student_id=nova.id, lecture_id=lec1.id, points=random.randint(0, lec1.points))
    sub2_nova = Submission.create(student_id=nova.id, lecture_id=lec3.id, points=random.randint(0, lec3.points))
    sub1_kathi = Submission.create(student_id=kathi.id, lecture_id=lec3.id, points=random.randint(0, lec3.points))
    sub1_vici = Submission.create(student_id=victoria.id, lecture_id=lec2.id, points=random.randint(0, lec2.points))
    
    return
    fp = Path().cwd()/"Test.json"
    dump_to_json(fp)
    db.close()
    db.init("Test.db")
    db.connect()
    db.create_tables([Class, Student, Lecture, Submission])
    load_from_json(fp)


if __name__ == "__main__":
    #    main()
    dump_to_json(Path().cwd()/"TEST.json")
