import re
from dataclasses import dataclass
from typing import ClassVar

from providers import DEFAULT_PROVIDER
from resources.base import CHECKPOINT, ESCALATED, FINISHED, PLAN_WAITS, PROJECT, STUCK, USER, Resource, ResourceDetails
from resources.shapes import FLAG, LIST, NUMBER, TEXT, Field, Placed

ROOT = "."
PROPOSED, CONFIRMED = "proposed", "confirmed"


@dataclass(frozen=True)
class Bases:
    root: str
    nested: dict[str, str]

    @classmethod
    def of(cls, tips: dict[str, str]) -> "Bases":
        return cls(tips.get(ROOT, ""), {name: base for name, base in tips.items() if name != ROOT})


CARD_PARTS = re.compile(r"(?:\*\*)?\b(What|Why|Touches|Done when|Risk):(?:\*\*)?\s*")


def card_back(brief: str) -> str:
    pieces = CARD_PARTS.split(brief)
    if len(pieces) < 5:
        return brief
    head, parts = pieces[0].strip(), zip(pieces[1::2], pieces[2::2])
    return "\n\n".join(part for part in [head, *(f"**{label}:** {text.strip()}" for label, text in parts)] if part)


class Ticket(Placed, Resource):
    details: ClassVar[ResourceDetails] = ResourceDetails(
        title="Ticket",
        abstract="A piece of work on a board, from the user, an agent or an outside source, run in an environment of its own",
        help="A ticket is the anchor for one piece of work: where it came from, which board and stage it sits in, who owns it, "
             "and the environment and plan it runs in once started. A ticket from an outside source carries that source's id, "
             "so the same event arriving again updates its ticket instead of making another.",
    )
    data_fields: ClassVar[list[Field]] = [
        Field(NUMBER, 0, name="board"),
        Field(TEXT, name="stage"),
        Field(TEXT, name="source"),
        Field(TEXT, name="source_id"),
        Field(TEXT, name="owner"),
        Field(TEXT, name="work_environment", journal_only=True),
        Field(TEXT, "", name="base", journal_only=True),
        Field(default=dict, name="bases", journal_only=True),
        Field(TEXT, DEFAULT_PROVIDER, name="provider"),
        Field(TEXT, "", name="model"),
        Field(NUMBER, 0.0, name="launched"),
        Field(NUMBER, 0.0, name="queued_at"),
        Field(NUMBER, 0, name="plan"),
        Field(FLAG, False, name="queued"),
        Field(FLAG, False, name="draft"),
        Field(FLAG, False, name="own_packages"),
        Field(FLAG, False, name="approved_early"),
        Field(NUMBER, 100, name="priority"),
        Field(default=dict, name="dependencies"),
        Field(default=list, name="declined"),
        Field(FLAG, False, name="hosted"),
        Field(NUMBER, 0.0, name="idle_since"),
        Field(FLAG, False, name="halted"),
        Field(NUMBER, 0, name="restarts"),
        Field(NUMBER, 0.0, name="told"),
        Field(NUMBER, 0.0, name="agent_seen"),
        Field(LIST, list, name="covers"),
        Field(NUMBER, 0, name="sent_back"),
    ]
    type = "ticket"
    held, eager = None, True
    indexed = ("board", "stage", "draft", "rank")
    moments = ("created", "completed", PLAN_WAITS, CHECKPOINT, FINISHED, STUCK, ESCALATED)
    icon = "ticket"
    scope = PROJECT
    created_in_viewer = True
    listed_open = True
    notified = (USER,)
    labels = {"brief": "What is wanted", "outcome": "How it ended", "board": "Board", "stage": "Stage", "source": "Source",
              "source_id": "Id at the source", "owner": "Owner", "work_environment": "Works in", "plan": "Plan"}
    shown_fields = ("board", "stage", "source", "owner", "work_environment", "plan")
    fixed_fields = ("source", "work_environment", "plan")

    def base_of(self, repository: str) -> str:
        return self.base if repository == ROOT else self.bases.get(repository, "")
