import json
import os
from pathlib import Path
from pydantic import BaseModel
from rich.console import Console

from nixprstatus.pr import get_pr
from nixprstatus.output import OutputFormat

from typing import Self


class PRInfo(BaseModel):
    pr: int
    title: str


class Watchlist(BaseModel):
    prs: list[PRInfo]

    @classmethod
    def from_file(cls, path: str | None = None) -> Self:
        if not path:
            path = _default_path()

        p = Path(path).expanduser()

        if not p.exists():
            return cls(prs=[])

        with open(p, "r") as f:
            data = json.load(f)
        return cls(**data)

    def to_file(self, path: str | None = None) -> None:
        if not path:
            _ensure_default_path()
            path = _default_path()

        p = Path(path).expanduser()

        with open(p, "w") as f:
            f.write(self.model_dump_json())

    def add_pr(self, pr: int) -> PRInfo:
        # Lookup PR info
        raw_pr = get_pr(pr)

        title = raw_pr["title"]
        info = PRInfo(pr=pr, title=title)
        self.prs.append(info)
        return info

    def remove(self, pr: int) -> None:
        self.prs = [p for p in self.prs if p.pr != pr]

    def print(self, format: OutputFormat = OutputFormat.CONSOLE) -> None:
        match format:
            case OutputFormat.CONSOLE:
                console = Console()
                for pr in self.prs:
                    console.print(f"{pr.pr}: {pr.title}")
            case OutputFormat.JSON:
                print(self.model_dump_json())
            case _:
                raise ValueError(f"Unknown format: {format}")

    def pr(self, pr: int) -> PRInfo | None:
        for p in self.prs:
            if p.pr == pr:
                return p
        return None

    def __contains__(self, item: PRInfo | int) -> bool:
        match item:
            case PRInfo():
                return any([x == item for x in self.prs])
            case int():
                return any([x.pr == item for x in self.prs])


def _default_path() -> str:
    if "XDG_STATE_HOME" in os.environ:
        return f"{os.environ['XDG_STATE_HOME']}/nixprstatus/watchlist.json"
    return "~/.config/nixprstatus/watchlist.json"


def _ensure_default_path() -> None:
    p = Path(_default_path()).expanduser()
    p.parent.mkdir(parents=True, exist_ok=True)
