from dataclasses import dataclass, field
from glob import glob
from pathlib import Path
from typing import Any, Literal


@dataclass
class TargetDecorator:
    type: Literal["task", "file"]
    args: dict[str, Any]


@dataclass
class Target:
    name: str
    type: Literal["task", "file"]
    commands: list[str]
    deps: list[str] = field(default_factory=list)
    description: str = field(default_factory=str)
    default: bool = field(default_factory=bool)

    @property
    def file(self) -> Path:
        if self.type == "task":
            raise TypeError("A task Target has no file")
        return Path(self.name)

    def exists(self) -> bool:
        if self.type == "task":
            return True
        if "*" in self.file.name:  # glob pattern:
            return all([Path(p).exists() for p in glob(self.file.name)])
        return self.file.exists()

    @property
    def last_build_timestamp(self) -> float:
        return self.file.stat().st_mtime

    def should_rebuild(self, target_depending_on_self: "Target") -> bool:
        if target_depending_on_self.type == "task":
            return True
        elif not target_depending_on_self.exists():
            return True
        elif "*" in self.name:
            return any(
                [
                    target_depending_on_self.last_build_timestamp < Path(p).stat().st_mtime
                    for p in glob(self.file.name)
                ]
            )
        return target_depending_on_self.last_build_timestamp < self.last_build_timestamp
