#!/usr/bin/env python3
"""Create a metadata-free, consent-traceable Timmy training record."""
import argparse
import hashlib
import hmac
import io
import json
import os
import sys
from datetime import datetime, timezone
from pathlib import Path

from PIL import Image, ImageOps

COLORS = ("brown", "green", "yellow", "pale", "red", "black")
QUALITIES = ("good", "fair", "poor")
REVIEWERS = ("user-confirmed", "clinician-reviewed")


def parser() -> argparse.ArgumentParser:
    p = argparse.ArgumentParser()
    p.add_argument("--input", required=True)
    p.add_argument("--output-dir", required=True)
    p.add_argument("--subject-id", required=True)
    p.add_argument("--consent-version", required=True)
    p.add_argument("--bristol-type", required=True, type=int, choices=range(1, 8))
    p.add_argument("--color", required=True, choices=COLORS)
    p.add_argument("--quality", required=True, choices=QUALITIES)
    p.add_argument("--reviewer", required=True, choices=REVIEWERS)
    return p


def main() -> int:
    args = parser().parse_args()
    salt = os.environ.get("TIMMY_DATASET_SALT", "")
    if len(salt) < 8:
        raise SystemExit("TIMMY_DATASET_SALT must contain at least 8 characters")
    if not args.consent_version.strip():
        raise SystemExit("consent version is required")

    try:
        with Image.open(args.input) as source:
            image = ImageOps.exif_transpose(source).convert("RGB")
            image.thumbnail((1200, 1200))
            buffer = io.BytesIO()
            image.save(buffer, "JPEG", quality=85, optimize=True, exif=b"")
    except Exception as exc:
        raise SystemExit(f"input is not a decodable image: {exc}") from exc

    data = buffer.getvalue()
    image_id = hashlib.sha256(data).hexdigest()
    subject_key = hmac.new(salt.encode(), args.subject_id.encode(), hashlib.sha256).hexdigest()[:16]
    bucket = int(subject_key[:2], 16)
    split = "train" if bucket < 205 else "validation" if bucket < 230 else "test"

    output = Path(args.output_dir)
    images = output / "images"
    images.mkdir(parents=True, exist_ok=True)
    relative_path = f"images/{image_id}.jpg"
    target = output / relative_path
    if not target.exists():
        target.write_bytes(data)

    record = {
        "schemaVersion": 1,
        "imageId": image_id,
        "relativePath": relative_path,
        "subjectKey": subject_key,
        "split": split,
        "consentVersion": args.consent_version.strip(),
        "ingestedAt": datetime.now(timezone.utc).isoformat(),
        "labels": {
            "bristolType": args.bristol_type,
            "color": args.color,
            "quality": args.quality,
        },
        "review": {"status": args.reviewer},
        "derivation": {
            "format": "jpeg",
            "maxDimension": 1200,
            "metadataStripped": True,
        },
    }
    with (output / "manifest.jsonl").open("a", encoding="utf-8") as manifest:
        manifest.write(json.dumps(record, separators=(",", ":")) + "\n")
    print(json.dumps(record))
    return 0


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