#!/usr/bin/env python3
"""
Daily DM digest — summarizes which DMs are ready to send.

Scans data/dm_content/ for _preview.txt files modified since the last digest
run, groups by company and DM type (app, dm1, dm2), and prints a one-shot
summary suitable for Telegram delivery.

Cron contract: silent if no new DMs since last run. Prints a digest when
there are new previews.
"""
import json
import re
import sys
import time
from pathlib import Path

PROJ = Path(r"C:\Users\Rob\Business_Projects\Project_1_Job_Seeker")
DM_CONTENT_DIR = PROJ / "data" / "dm_content"
STATE_FILE = Path.home() / "AppData" / "Local" / "hermes" / "dm_digest.state.json"

# Filename pattern: <Company>_<Title>_<dm_type>_preview.txt
# Examples:
#   Acxiom_Sales-Business-Support_dm1_preview.txt
#   Docker-Inc_Staff-Integrated-Campaigns-Manager_app_preview.txt
FILENAME_RE = re.compile(
    r"^(?P<company>.+?)_(?P<dm_type>app|dm1|dm2)_preview\.txt$"
)

DM_TYPE_LABEL = {
    "app": "App DM",
    "dm1": "DM1 (48hr)",
    "dm2": "DM2 (4-day)",
}


def load_state() -> dict:
    if STATE_FILE.exists():
        try:
            return json.loads(STATE_FILE.read_text(encoding="utf-8"))
        except (json.JSONDecodeError, OSError):
            pass
    return {"last_run_ts": 0, "seen_files": []}


def save_state(state: dict) -> None:
    STATE_FILE.write_text(json.dumps(state, indent=2), encoding="utf-8")


def find_new_previews(since_ts: float) -> list[tuple[Path, dict, float]]:
    """Return [(path, parsed, mtime), ...] for preview files modified after since_ts."""
    if not DM_CONTENT_DIR.exists():
        return []
    results = []
    for p in DM_CONTENT_DIR.glob("*_preview.txt"):
        try:
            mtime = p.stat().st_mtime
        except OSError:
            continue
        if mtime <= since_ts:
            continue
        m = FILENAME_RE.match(p.name)
        if not m:
            continue
        results.append((p, m.groupdict(), mtime))
    # Sort by mtime so the digest reads chronologically
    results.sort(key=lambda x: x[2])
    return results


def group_by_company(items: list[tuple[Path, dict, float]]) -> dict[str, list[str]]:
    """Group DM types by company for the digest output."""
    grouped: dict[str, list[str]] = {}
    for _path, parsed, _mtime in items:
        co = parsed["company"].replace("-", " ").replace("_", " ")
        # Smarten common abbreviations
        co = re.sub(r"\bInc\b", "Inc.", co)
        grouped.setdefault(co, []).append(DM_TYPE_LABEL.get(parsed["dm_type"], parsed["dm_type"]))
    return grouped


def main() -> int:
    state = load_state()
    last_ts = state.get("last_run_ts", 0)
    seen = set(state.get("seen_files", []))

    new_items = find_new_previews(last_ts)
    # Filter out files we've already reported in a prior run
    new_items = [(p, d, t) for p, d, t in new_items if p.name not in seen]

    if not new_items:
        # Silent — nothing new
        return 0

    grouped = group_by_company(new_items)
    n_files = len(new_items)
    n_companies = len(grouped)

    print(f"📬 {n_files} DM{'s' if n_files != 1 else ''} ready across {n_companies} compan{'ies' if n_companies != 1 else 'y'}:")
    for company, types in sorted(grouped.items()):
        types_str = ", ".join(types)
        print(f"  • {company} — {types_str}")
    print(f"\nFiles in: data/dm_content/")

    # Update state so we don't re-report these
    state["last_run_ts"] = max(t for _, _, t in new_items)
    state["seen_files"] = list(seen | {p.name for p, _, _ in new_items})
    save_state(state)
    return 0


if __name__ == "__main__":
    sys.exit(main())
