import json
from pathlib import Path

from schemas_hf.sync import generate_from_cache


def _write_dataset_info(base: Path, repo: str, snapshot: str, info: dict) -> Path:
    repo_dir = base / repo
    file_path = repo_dir / "snapshots" / snapshot / "dataset_info.json"
    file_path.parent.mkdir(parents=True, exist_ok=True)
    file_path.write_text(json.dumps(info))
    return file_path


def test_generate_from_cache_creates_schema(tmp_path):
    cache_dir = tmp_path / "hub"
    info = {
        "features": {
            "text": {"_type": "Value", "dtype": "string"},
        }
    }
    _write_dataset_info(cache_dir, "datasets--owner--name", "abc", info)

    dataset_cache = tmp_path / "datasets"
    output_dir = tmp_path / "out"
    generated = generate_from_cache(
        cache_dir,
        output_dir,
        dataset_cache_dir=dataset_cache,
    )

    assert len(generated) == 1
    module_path = generated[0]
    assert module_path.name == "owner__name.py"
    assert "OwnerNameRecord" in module_path.read_text()


def test_generate_from_cache_dry_run(tmp_path):
    cache_dir = tmp_path / "hub"
    info = {
        "features": {
            "value": {"_type": "Value", "dtype": "int32"},
        }
    }
    _write_dataset_info(cache_dir, "datasets--another--set", "def", info)

    dataset_cache = tmp_path / "datasets"
    output_dir = tmp_path / "out"
    generated = generate_from_cache(
        cache_dir,
        output_dir,
        dataset_cache_dir=dataset_cache,
        dry_run=True,
    )

    assert generated == []
    assert not output_dir.exists()


def test_generate_from_cache_with_filters(tmp_path):
    cache_dir = tmp_path / "hub"
    info = {
        "features": {
            "value": {"_type": "Value", "dtype": "int32"},
        }
    }
    _write_dataset_info(cache_dir, "datasets--owner--keep", "a1", info)
    _write_dataset_info(cache_dir, "datasets--owner--skip", "a2", info)

    dataset_cache = tmp_path / "datasets"
    output_dir = tmp_path / "out"
    generated = generate_from_cache(
        cache_dir,
        output_dir,
        dataset_cache_dir=dataset_cache,
        only=["owner/keep"],
    )

    assert len(generated) == 1
    assert generated[0].name == "owner__keep.py"
    assert not (output_dir / "owner__skip.py").exists()


def test_generate_from_cache_respects_dataset_cache_configs(tmp_path):
    cache_dir = tmp_path / "hub"
    info = {
        "cfg": {
            "features": {
                "text": {"_type": "Value", "dtype": "string"},
            }
        }
    }
    _write_dataset_info(cache_dir, "datasets--owner--name", "z1", info)

    dataset_cache = tmp_path / "datasets_cache"
    (dataset_cache / "owner___name" / "cfg").mkdir(parents=True)

    output_dir = tmp_path / "out"
    generated = generate_from_cache(
        cache_dir,
        output_dir,
        dataset_cache_dir=dataset_cache,
    )

    assert generated[0].name == "owner__name__cfg.py"


def test_generate_from_cache_skips_existing_when_requested(tmp_path):
    cache_dir = tmp_path / "hub"
    info = {
        "features": {
            "text": {"_type": "Value", "dtype": "string"},
        }
    }
    _write_dataset_info(cache_dir, "datasets--owner--name", "abc", info)

    dataset_cache = tmp_path / "datasets"
    output_dir = tmp_path / "out"

    # First run: actually generate the schema.
    generated = generate_from_cache(
        cache_dir,
        output_dir,
        dataset_cache_dir=dataset_cache,
        skip_existing=False,
    )
    assert len(generated) == 1
    module_path = generated[0]
    initial_mtime = module_path.stat().st_mtime

    # Second run with skip_existing=True: should not rewrite the file.
    generated_again = generate_from_cache(
        cache_dir,
        output_dir,
        dataset_cache_dir=dataset_cache,
        skip_existing=True,
    )
    assert len(generated_again) == 1
    assert generated_again[0] == module_path
    assert module_path.stat().st_mtime == initial_mtime
