"""Expand explicit date-only CSV spans locally; not an iCalendar parser/importer."""
import csv
from datetime import date, timedelta
import json
from pathlib import Path
import re
import sys

FIELDS = ["case_id", "start_date", "end_exclusive"]
def parse_date(value):
    if not re.fullmatch(r"[0-9]{4}-[0-9]{2}-[0-9]{2}", value):
        raise ValueError("Dates must be YYYY-MM-DD with no time or zone")
    return date.fromisoformat(value)

def expand(path):
    path = Path(path)
    if path.stat().st_size > 1024 * 1024:
        raise ValueError("Teaching limit: CSV must be at most 1 MiB")
    out = []
    seen = set()
    with path.open(encoding="utf-8", newline="") as file:
        reader = csv.DictReader(file)
        if reader.fieldnames != FIELDS:
            raise ValueError("Headers must be case_id,start_date,end_exclusive in that order")
        for row in reader:
            if len(out) >= 500:
                raise ValueError("Teaching limit: at most 500 cases")
            if set(row) != set(FIELDS) or any(v is None or not v.strip() for v in row.values()):
                raise ValueError("Each row needs three nonblank fields")
            if row["case_id"] in seen:
                raise ValueError("Duplicate case_id")
            seen.add(row["case_id"])
            start = parse_date(row["start_date"])
            end = parse_date(row["end_exclusive"])
            count = (end - start).days
            if not 1 <= count <= 366:
                raise ValueError("Teaching span must contain 1 to 366 dates")
            out.append({"case_id": row["case_id"], "start_date": start.isoformat(),
                        "end_exclusive": end.isoformat(), "date_count": count,
                        "included_dates": [(start + timedelta(days=i)).isoformat() for i in range(count)]})
    if not out:
        raise ValueError("CSV must contain at least one case")
    return out

if __name__ == "__main__":
    try:
        if len(sys.argv) != 2:
            raise ValueError("Usage: python3 expand_dates.py fictional-dates.csv")
        print(json.dumps(expand(sys.argv[1]), indent=2))
    except (ValueError, OSError, csv.Error) as error:
        print(str(error), file=sys.stderr)
        sys.exit(2)
