"""Core board operations — post, read, clear, archive."""

from __future__ import annotations

import os
import re
from datetime import datetime, timezone, timedelta
from pathlib import Path
from typing import Literal

_DEFAULT_DIR = Path(os.environ.get("ACTA_DIR", os.path.expanduser("~/notes/ACTA")))
_ARCHIVE = ".archive"

Severity = Literal["action", "info", "warning"]


def _slugify(text: str) -> str:
    s = text.lower().strip()
    s = re.sub(r"[^a-z0-9]+", "-", s)
    return s.strip("-")[:60]


def _parse(path: Path) -> dict:
    text = path.read_text()
    meta = {"id": path.stem, "path": str(path)}
    fm = re.match(r"^---\n(.+?)\n---\n(.*)$", text, re.DOTALL)
    if fm:
        for line in fm.group(1).splitlines():
            if ": " in line:
                k, v = line.split(": ", 1)
                meta[k.strip()] = v.strip()
        meta["body"] = fm.group(2).strip()
    else:
        meta["body"] = text.strip()
    return meta


def post(
    message: str,
    sender: str = "unknown",
    to: str = "all",
    severity: Severity = "info",
    subject: str | None = None,
    board: Path | str | None = None,
) -> Path:
    """Post a message. Returns path to created file."""
    d = Path(board) if board else _DEFAULT_DIR
    d.mkdir(parents=True, exist_ok=True)

    now = datetime.now(timezone(timedelta(hours=8)))
    ts = now.strftime("%Y-%m-%dT%H:%M%z")
    slug = _slugify(subject or message[:80])
    prefix = now.strftime("%Y-%m-%d-%H%M")
    path = d / f"{prefix}-{slug}.md"

    counter = 2
    while path.exists():
        path = d / f"{prefix}-{slug}-{counter}.md"
        counter += 1

    path.write_text(f"""---
from: {sender}
to: {to}
severity: {severity}
ts: {ts}
---

{message.strip()}
""")
    return path


def read(to: str | None = None, board: Path | str | None = None) -> list[dict]:
    """Read messages, newest first. Filter by recipient."""
    d = Path(board) if board else _DEFAULT_DIR
    if not d.exists():
        return []

    msgs = []
    for f in sorted(d.glob("*.md"), reverse=True):
        meta = _parse(f)
        if to:
            msg_to = meta.get("to", "all")
            if msg_to != "all" and msg_to != to:
                continue
        msgs.append(meta)
    return msgs


def clear(msg_id: str, board: Path | str | None = None) -> bool:
    d = Path(board) if board else _DEFAULT_DIR
    path = d / f"{msg_id}.md"
    if path.exists():
        path.unlink()
        return True
    return False


def clear_all(board: Path | str | None = None) -> int:
    d = Path(board) if board else _DEFAULT_DIR
    n = 0
    for f in d.glob("*.md"):
        f.unlink()
        n += 1
    return n


def archive(msg_id: str, board: Path | str | None = None) -> bool:
    d = Path(board) if board else _DEFAULT_DIR
    path = d / f"{msg_id}.md"
    if not path.exists():
        return False
    arc = d / _ARCHIVE
    arc.mkdir(exist_ok=True)
    path.rename(arc / path.name)
    return True


def archive_all(board: Path | str | None = None) -> int:
    d = Path(board) if board else _DEFAULT_DIR
    arc = d / _ARCHIVE
    arc.mkdir(exist_ok=True)
    n = 0
    for f in d.glob("*.md"):
        f.rename(arc / f.name)
        n += 1
    return n


def count(board: Path | str | None = None) -> int:
    d = Path(board) if board else _DEFAULT_DIR
    if not d.exists():
        return 0
    return len(list(d.glob("*.md")))
