"""Apply the owner's decisions — approve, reject, ship — wherever they are made.

The board in the browser and `feature-scout decide` both come through here, so there is one
set of rules about what may follow what.
"""
from __future__ import annotations

from typing import Any

from .store import Store


def _was_interrupted(store: Store, idea: dict[str, Any]) -> bool:
    from .build import was_interrupted           # imported here: build reads this module's rules
    return was_interrupted(store, idea)


ALLOWED_FROM = {"proposed": {"approve", "reject"}, "approved": {"reject"}, "building": set(),
                "built": {"ship", "reject"}, "blocked": {"approve", "reject"}, "failed": {"approve", "reject"},
                "rejected": {"approve"}, "shipped": set()}


def apply_commands(store: Store, commands: list[tuple[str, list[int]]]) -> list[str]:
    """Apply decisions; returns plain-English lines describing what happened."""
    lines: list[str] = []
    for verb, ids in commands:
        for idea_id in ids:
            idea = store.idea(idea_id)
            if not idea:
                lines.append(f"#{idea_id}: I don't have an idea with that number.")
                continue
            allowed = ALLOWED_FROM.get(idea["status"], set())
            # Nothing may follow a build that is running. One that was interrupted only looks
            # like it is running, and has to be recoverable — from here or from the page.
            stopped = verb in ("approve", "reject") and _was_interrupted(store, idea)
            if stopped:
                allowed = allowed | {"approve", "reject"}
            if verb not in allowed:
                lines.append(f"#{idea_id} {idea['title']}: can't {verb} it, it is currently {idea['status']}.")
                continue
            if stopped and verb == "approve":
                store.set_status(idea_id, "approved", error=None)
                lines.append(f"#{idea_id} {idea['title']}: back in the queue. It carries on from "
                             "where it stopped rather than starting over.")
                continue
            if verb == "approve":
                store.set_status(idea_id, "approved", error=None)
                lines.append(f"#{idea_id} {idea['title']}: approved — I'll build and test it next.")
            elif verb == "reject":
                store.set_status(idea_id, "rejected")
                lines.append(f"#{idea_id} {idea['title']}: rejected.")
            elif verb == "ship":
                store.request_ship(idea_id)
                lines.append(f"#{idea_id} {idea['title']}: will merge it into the app on the next pass.")
    return lines


def ideas_by_status(store: Store) -> dict[str, list[int]]:
    out: dict[str, list[int]] = {}
    for i in store.ideas():
        out.setdefault(i["status"], []).append(i["id"])
    return out
