#!/usr/bin/env python3
"""Prepare a Colonnes day durably, then print that exact civil date."""
import argparse
import datetime
import json
import re
import subprocess
import sys


def run(executable, arguments):
    completed = subprocess.run(
        [executable, *arguments], capture_output=True, text=True, timeout=130
    )
    try:
        result = json.loads(completed.stdout)
    except (ValueError, TypeError) as error:
        raise RuntimeError("Colonnes returned no valid JSON result.") from error
    if not isinstance(result, dict) or not result.get("requestId"):
        raise RuntimeError("Colonnes returned an invalid response.")
    return completed.returncode, result


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--executable", default="colonnes", help="Colonnes executable path")
    parser.add_argument("--file", required=True, help="Document path")
    date = parser.add_mutually_exclusive_group(required=True)
    date.add_argument("--date", help="Civil date, YYYY-MM-DD")
    date.add_argument("-d", type=int, help="Local day offset (0 = today)")
    args = parser.parse_args()
    selector = ["--date", args.date] if args.date else ["-d", str(args.d)]
    code, prepared = run(
        args.executable, ["prepare-calendar", "--file", args.file, *selector]
    )
    if code == 2 and prepared.get("status") == "no_matching_rule":
        print(json.dumps(prepared))
        return 0
    if code != 0 or prepared.get("status") not in ("prepared", "already_prepared"):
        raise RuntimeError(prepared.get("message", "Preparation failed; nothing was printed."))
    exact_date = prepared.get("date", "")
    if not isinstance(exact_date, str) or not re.fullmatch(r"\d{4}-\d{2}-\d{2}", exact_date):
        raise RuntimeError("Preparation returned an invalid date; nothing was printed.")
    datetime.date.fromisoformat(exact_date)
    file = prepared.get("file")
    if not isinstance(file, str) or not file:
        raise RuntimeError("Preparation returned no document path; nothing was printed.")
    code, printed = run(
        args.executable,
        ["print", "calendar", "--file", file, "--date", exact_date, "--wait"],
    )
    if code != 0 or printed.get("status") != "printed":
        raise RuntimeError(printed.get("message", "Printing failed."))
    print(json.dumps(printed))
    return 0


if __name__ == "__main__":
    try:
        sys.exit(main())
    except (OSError, ValueError, RuntimeError, subprocess.TimeoutExpired) as error:
        print(str(error), file=sys.stderr)
        sys.exit(1)
