import pytest

from hef.catalog import Record, validate, CatalogError


def make_record(**overrides):
    base = dict(
        id="nasa-apollo-earthrise",
        title="Earthrise",
        source_url="https://archive.org/details/earthrise",
        source_archive="internet_archive",
        license="public_domain",
        mode="video",
        left=1,
        right=4,
        dark=1,
        light=3,
        duration_s=600,
        file_path="/media/earthrise.mp4",
    )
    base.update(overrides)
    return Record(**base)


def test_valid_record_passes():
    validate(make_record())  # must not raise


def test_defaults_are_set():
    record = make_record()
    assert record.review_status == "proposed"
    assert record.attribution == ""
    assert record.reviewed_at is None


def test_invalid_mode_raises():
    with pytest.raises(CatalogError):
        validate(make_record(mode="hologram"))


def test_invalid_license_raises():
    with pytest.raises(CatalogError):
        validate(make_record(license="all_rights_reserved"))


def test_coordinate_out_of_range_raises():
    with pytest.raises(CatalogError):
        validate(make_record(left=5))
    with pytest.raises(CatalogError):
        validate(make_record(dark=-1))


def test_boolean_coordinate_rejected():
    with pytest.raises(CatalogError):
        validate(make_record(right=True))


def test_cc_by_requires_attribution():
    with pytest.raises(CatalogError):
        validate(make_record(license="cc_by", attribution=""))
    validate(make_record(license="cc_by", attribution="Jane Doe, CC BY 4.0"))


def test_empty_id_raises():
    with pytest.raises(CatalogError):
        validate(make_record(id=""))


def test_negative_duration_raises():
    with pytest.raises(CatalogError):
        validate(make_record(duration_s=-1))


from hef.catalog import record_to_dict, record_from_dict


def test_dict_round_trip():
    record = make_record()
    restored = record_from_dict(record_to_dict(record))
    assert restored == record


def test_record_from_dict_rejects_unknown_field():
    data = record_to_dict(make_record())
    data["bogus"] = 1
    with pytest.raises(CatalogError):
        record_from_dict(data)


def test_record_from_dict_rejects_missing_required_field():
    data = record_to_dict(make_record())
    del data["title"]
    with pytest.raises(CatalogError):
        record_from_dict(data)


from hef.catalog import load_catalog, save_catalog, append_record


def test_save_then_load_round_trip(tmp_path):
    path = tmp_path / "library.jsonl"
    records = [make_record(id="a"), make_record(id="b", mode="audio")]
    save_catalog(records, path)
    loaded = load_catalog(path)
    assert loaded == records


def test_load_skips_blank_lines(tmp_path):
    path = tmp_path / "library.jsonl"
    save_catalog([make_record(id="a")], path)
    with path.open("a", encoding="utf-8") as fh:
        fh.write("\n   \n")
    loaded = load_catalog(path)
    assert len(loaded) == 1


def test_load_empty_file_returns_empty_list(tmp_path):
    path = tmp_path / "library.jsonl"
    path.write_text("", encoding="utf-8")
    assert load_catalog(path) == []


def test_load_invalid_json_raises(tmp_path):
    path = tmp_path / "library.jsonl"
    path.write_text("{not json}\n", encoding="utf-8")
    with pytest.raises(CatalogError):
        load_catalog(path)


def test_load_validates_records(tmp_path):
    path = tmp_path / "library.jsonl"
    save_catalog([make_record(id="a")], path)
    import json
    bad = record_to_dict(make_record(id="bad"))
    bad["left"] = 9
    with path.open("a", encoding="utf-8") as fh:
        fh.write(json.dumps(bad) + "\n")
    with pytest.raises(CatalogError):
        load_catalog(path)


def test_append_record(tmp_path):
    path = tmp_path / "library.jsonl"
    save_catalog([make_record(id="a")], path)
    append_record(make_record(id="b"), path)
    loaded = load_catalog(path)
    assert [r.id for r in loaded] == ["a", "b"]


def test_save_rejects_invalid_record(tmp_path):
    path = tmp_path / "library.jsonl"
    with pytest.raises(CatalogError):
        save_catalog([make_record(mode="hologram")], path)
