from __future__ import annotations

import tomllib
from dataclasses import dataclass

from .config import ROOT
from .table import print_table


@dataclass(frozen=True)
class Task:
    id: str
    name: str
    description: str
    group_id: str
    group_name: str
    number: int
    group_number: int
    index_in_group: int

    @property
    def selection(self) -> str:
        return f"{self.group_number}.{self.index_in_group}"


@dataclass(frozen=True)
class TaskGroup:
    id: str
    name: str
    number: int


def load_task_config() -> dict:
    path = ROOT / "config" / "tasks.toml"
    return tomllib.loads(path.read_text(encoding="utf-8"))


def load_groups() -> list[TaskGroup]:
    data = load_task_config()
    groups = []
    for index, group in enumerate(data.get("groups", []), 1):
        groups.append(TaskGroup(id=group["id"], name=group["name"], number=index))
    return groups


def load_tasks() -> list[Task]:
    data = load_task_config()
    tasks: list[Task] = []
    number = 1
    for group_number, group in enumerate(data.get("groups", []), 1):
        for index_in_group, row in enumerate(group.get("tasks", []), 1):
            tasks.append(
                Task(
                    id=row["id"],
                    name=row["name"],
                    description=row.get("description", ""),
                    group_id=group["id"],
                    group_name=group["name"],
                    number=number,
                    group_number=group_number,
                    index_in_group=index_in_group,
                )
            )
            number += 1
    return tasks


def task_by_number(tasks: list[Task], number: int) -> Task | None:
    for task in tasks:
        if task.number == number:
            return task
    return None


def task_by_selection(tasks: list[Task], selection: str) -> Task | None:
    normalized = selection.strip().lower()
    for task in tasks:
        if task.selection.lower() == normalized:
            return task
    return None


def tasks_by_selection_group(tasks: list[Task], groups: list[TaskGroup], selection: str) -> list[Task]:
    normalized = selection.strip().lower()
    if not normalized.endswith(".0"):
        return []
    try:
        group_number = int(normalized.split(".", 1)[0])
    except ValueError:
        return []
    return tasks_by_group_number(tasks, groups, group_number)


def tasks_by_group_number(tasks: list[Task], groups: list[TaskGroup], number: int) -> list[Task]:
    group = next((item for item in groups if item.number == number), None)
    if not group:
        return []
    return [task for task in tasks if task.group_id == group.id]


def print_task_list(tasks: list[Task]) -> None:
    groups = load_groups()
    for group in groups:
        group_tasks = [task for task in tasks if task.group_id == group.id]
        if not group_tasks:
            continue
        print()
        print("=" * 72)
        print(f"GRUPA {group.number}: {group.name.upper()}")
        print("=" * 72)
        print_table(
            ["Nr", "Zadanie", "Opis"],
            [[item.selection, item.name, item.description] for item in group_tasks],
        )

    print()
    print("Opcje zbiorcze")
    group_rows = [
        [f"{group.number}.0", f"Wszystkie zadania z grupy: {group.name}"]
        for group in groups
        if any(task.group_id == group.id for task in tasks)
    ]
    print_table(
        ["Nr", "Zakres"],
        group_rows + [["ALL", "Wszystkie zadania ze wszystkich grup"]],
    )
