"""Count consecutive days on which an UNATTENDED brief succeeded.

The definition of done for this rail is "a brief lands on his phone for fourteen
consecutive days with no action from him". That is a claim about the past, and the
only honest way to make it is to have been counting at the time — reconstructing it
afterwards from memory is exactly the kind of thing this whole system exists to stop.

Hand-fired runs do not count and are not recorded here. Only `brief.py --scheduled`,
which is what the timer invokes.

Deliberately a sorted list of dates rather than a counter: a counter can only tell you
what it believes, a list can be read and argued with.
"""

from __future__ import annotations

import json
from datetime import date, datetime, timedelta
from typing import Any

from notify import ROOT

STREAK_PATH = ROOT / "state" / "unattended.json"


def _load() -> list[str]:
    if not STREAK_PATH.exists():
        return []
    try:
        value = json.loads(STREAK_PATH.read_text(encoding="utf-8"))
    except (ValueError, OSError):
        return []
    days = value.get("days", [])
    return sorted({d for d in days if isinstance(d, str)})


def _run_length(days: list[str]) -> int:
    """Consecutive days ending at the most recent entry."""
    if not days:
        return 0
    parsed = sorted({date.fromisoformat(d) for d in days})
    run = 1
    for earlier, later in zip(parsed, parsed[1:]):
        run = run + 1 if later - earlier == timedelta(days=1) else 1
    return run


def record(day: date | None = None) -> dict[str, Any]:
    """Record an unattended success for `day` (default: local today)."""
    day = day or datetime.now().astimezone().date()
    days = _load()
    if day.isoformat() not in days:
        days.append(day.isoformat())
        days = sorted(set(days))
    STREAK_PATH.parent.mkdir(parents=True, exist_ok=True)
    payload = {"days": days, "streak": _run_length(days)}
    temporary = STREAK_PATH.with_suffix(".json.tmp")
    temporary.write_text(json.dumps(payload, indent=2) + "\n", encoding="utf-8")
    temporary.replace(STREAK_PATH)
    return payload


def current() -> dict[str, Any]:
    days = _load()
    last = days[-1] if days else None
    run = _run_length(days)
    # A streak that ended yesterday is history, not a streak.
    if last:
        gap = (datetime.now().astimezone().date() - date.fromisoformat(last)).days
        if gap > 1:
            run = 0
    return {"days": days, "streak": run, "last": last}


if __name__ == "__main__":
    state = current()
    print(f"unattended briefs recorded : {len(state['days'])}")
    print(f"last                       : {state['last'] or 'never'}")
    print(f"current streak             : {state['streak']} / 14")
