#!/usr/bin/env python
from __future__ import annotations

from collections import defaultdict
from typing import TYPE_CHECKING

from _common_tasks_stuff import _next_weekday

from smartschool import FutureTasks, PathCredentials, Smartschool, SmartschoolHours
from smartschool.common import IsSaved, save, send_email

if TYPE_CHECKING:
    from datetime import date

    from smartschool.objects import AgendaHour, FutureTaskOneTask


def _is_equal_task(a: FutureTaskOneTask, b: FutureTaskOneTask) -> bool:
    return (a.course, a.hourID, a.label, a.description, a.date) == (b.course, b.hourID, b.label, b.description, b.date)


def _email_text(session: Smartschool, task: FutureTaskOneTask) -> str:
    hour: AgendaHour = SmartschoolHours(session).search_by_hourId(task.hourID)

    return f"date: {task.date}\nlesuur: {hour.title}e lesuur\ntime: {hour.start} -> {hour.end}\nles: {task.course}\n\n{task.label}:\n  {task.description}\n"


def process_task(session: Smartschool, task: FutureTaskOneTask, all_tasks: dict) -> None:
    """Stores in an array + report if it's a new/updated task."""
    course_name = task.course
    hour: AgendaHour = SmartschoolHours(session).search_by_hourId(task.hourID)
    when = task.date

    all_tasks[when][hour.title].append(task)

    status = save(session, type_="todo", course_name=course_name, id_=task.assignmentID, data=task, is_eq=_is_equal_task)
    if status == IsSaved.SAME:
        return

    subject = f"📑 [{when} {hour.title}e lesuur] {course_name} ({task.label})"
    if status != IsSaved.NEW:
        subject = f"⚠⚠ {subject}"  # There is an update...

    text = _email_text(session, task)

    send_email(subject=subject, text=text, email_from=session.creds.other_info["email_from"], email_to=session.creds.other_info["email_to"])


def report_tasks_for_next_day(session: Smartschool, all_tasks: dict):
    next_weekday = _next_weekday()
    if not next_weekday:
        return

    if next_weekday not in all_tasks:
        return  # No tasks for 'tomorrow'

    tasks = all_tasks[next_weekday]

    text = []
    for _uur, subtasks in sorted(tasks.items(), key=lambda x: x[0]):  # type: str, list[FutureTaskOneTask]
        for task in subtasks:
            text.append(_email_text(session, task))

    text = "\n---------------------------------------\n\n".join(text)

    status = save(session, "todo", ".email", str(next_weekday), data=text, extension="txt")
    if status == IsSaved.SAME:
        return  # Don't re-send if nothing changed

    subject = f"🍕 Todo list {next_weekday}"
    if status != IsSaved.NEW:
        subject = f"⚠⚠ {subject}"  # There is an update...
    send_email(subject=subject, text=text, email_from=session.creds.other_info["email_from"], email_to=session.creds.other_info["email_to"])


def main():
    all_tasks: dict[date, dict[str, list]] = defaultdict(lambda: defaultdict(list))

    session = Smartschool(PathCredentials())
    assert "email_from" in session.creds.other_info
    assert "email_to" in session.creds.other_info

    for day in FutureTasks(session):
        for course in day.courses:
            assert not course.items.materials, "Please correct the model to include this information."

            for task in course.items.tasks:
                process_task(session, task, all_tasks)

    report_tasks_for_next_day(session, all_tasks)


if __name__ == "__main__":
    main()
