#!/usr/bin/env python3
"""Validate every shard of a BookTTS teacher dataset."""

from __future__ import annotations

import argparse
import hashlib
import json
import sys
from pathlib import Path

import numpy as np


def audit(args: argparse.Namespace) -> None:
    metadata_path = args.dataset / "dataset.json"
    metadata = json.loads(metadata_path.read_text(encoding="utf-8"))
    token_map = np.load(args.dataset / "token_id_map.npy")
    samples = 0
    tokens = 0
    bytes_total = metadata_path.stat().st_size + (args.dataset / "token_id_map.npy").stat().st_size
    digest = hashlib.sha256()
    for record in metadata.get("shards", []):
        path = args.dataset / record["file"]
        digest.update(path.read_bytes())
        bytes_total += path.stat().st_size
        with np.load(path) as shard:
            ids = shard["original_input_ids"]
            mask = shard["attention_mask"]
            teacher = shard["teacher"]
            if ids.shape != mask.shape or teacher.shape[:2] != ids.shape or teacher.shape[2:] != (768,):
                raise ValueError(f"Incompatible shapes in {path.name}: {ids.shape}, {mask.shape}, {teacher.shape}")
            if ids.shape[0] != record["samples"]:
                raise ValueError(f"Sample count mismatch in {path.name}")
            if ids.size and (ids.min() < 0 or ids.max() >= token_map.shape[0]):
                raise ValueError(f"Token id outside token map in {path.name}")
            if not np.isfinite(teacher).all():
                raise ValueError(f"Non-finite teacher value in {path.name}")
            if not np.all((mask == 0) | (mask == 1)):
                raise ValueError(f"Non-binary attention mask in {path.name}")
            samples += ids.shape[0]
            tokens += int(mask.sum())
    if samples != metadata["samples"]:
        raise ValueError(f"Dataset sample count is {samples}, metadata says {metadata['samples']}")
    report = {
        "dataset": str(args.dataset),
        "samples": samples,
        "shards": len(metadata.get("shards", [])),
        "tokens": tokens,
        "vocab_size": metadata["vocab_size"],
        "token_map_entries": int(token_map.shape[0]),
        "bytes": bytes_total,
        "shards_sha256": digest.hexdigest().upper(),
        "teacher_dtype": metadata.get("teacher_dtype"),
    }
    print(json.dumps(report, ensure_ascii=False, indent=2))


def parse_args() -> argparse.Namespace:
    parser = argparse.ArgumentParser()
    parser.add_argument("--dataset", type=Path, required=True)
    return parser.parse_args()


if __name__ == "__main__":
    sys.exit(audit(parse_args()) or 0)
