"""Tests for DRS models."""

from __future__ import annotations

import pytest

from ai4gh.specs.drs.models import (
    DRSURI,
    AccessType,
    AccessURL,
    Checksum,
    ContentsObject,
    DRSAccessMethod,
    DRSObject,
)


class TestChecksum:
    def test_basic(self) -> None:
        c = Checksum(checksum="abc123", type="md5")
        assert c.checksum == "abc123"
        assert c.type == "md5"


class TestAccessURL:
    def test_basic(self) -> None:
        url = AccessURL(url="https://example.com/data")
        assert url.url == "https://example.com/data"
        assert url.headers is None

    def test_with_headers(self) -> None:
        url = AccessURL(url="https://example.com/data", headers=["Authorization: Bearer x"])
        assert url.headers == ["Authorization: Bearer x"]


class TestDRSAccessMethod:
    def test_basic(self) -> None:
        m = DRSAccessMethod(type=AccessType.https, access_id="abc")
        assert m.type == AccessType.https
        assert m.access_id == "abc"
        assert m.access_url is None

    def test_with_url(self) -> None:
        m = DRSAccessMethod(
            type=AccessType.s3,
            access_url=AccessURL(url="s3://bucket/key"),
        )
        assert m.access_url is not None
        assert m.access_url.url == "s3://bucket/key"


class TestContentsObject:
    def test_basic(self) -> None:
        c = ContentsObject(name="file.bam")
        assert c.name == "file.bam"
        assert c.id is None

    def test_nested(self) -> None:
        child = ContentsObject(name="child.bam", id="child-id")
        parent = ContentsObject(name="bundle", contents=[child])
        assert parent.contents is not None
        assert len(parent.contents) == 1
        assert parent.contents[0].name == "child.bam"


class TestDRSObject:
    def test_minimal(self) -> None:
        obj = DRSObject(
            id="drs-1",
            self_uri="drs://example.com/drs-1",
            size=1024,
            created_time="2024-01-01T00:00:00Z",
            checksums=[Checksum(checksum="abc", type="md5")],
        )
        assert obj.id == "drs-1"
        assert obj.size == 1024
        assert obj.is_bundle is False

    def test_bundle(self) -> None:
        obj = DRSObject(
            id="bundle-1",
            self_uri="drs://example.com/bundle-1",
            size=0,
            created_time="2024-01-01T00:00:00Z",
            checksums=[],
            contents=[ContentsObject(name="file.bam")],
        )
        assert obj.is_bundle is True

    def test_with_access_methods(self) -> None:
        obj = DRSObject(
            id="drs-2",
            self_uri="drs://example.com/drs-2",
            size=2048,
            created_time="2024-01-01T00:00:00Z",
            checksums=[Checksum(checksum="def", type="sha256")],
            access_methods=[
                DRSAccessMethod(type=AccessType.https, access_id="https-1"),
                DRSAccessMethod(type=AccessType.s3, access_id="s3-1"),
            ],
        )
        assert obj.access_methods is not None
        assert len(obj.access_methods) == 2


class TestDRSURI:
    def test_basic(self) -> None:
        uri = DRSURI("drs://example.com/abc123")
        assert uri.host == "example.com"
        assert uri.id == "abc123"
        assert uri.base_url == "https://example.com"

    def test_str(self) -> None:
        uri = DRSURI("drs://host.org/obj-id")
        assert str(uri) == "drs://host.org/obj-id"

    def test_repr(self) -> None:
        uri = DRSURI("drs://host.org/obj-id")
        assert "DRSURI" in repr(uri)

    def test_invalid_scheme(self) -> None:
        with pytest.raises(ValueError, match="must start with drs://"):
            DRSURI("https://example.com/abc")

    def test_nested_path(self) -> None:
        uri = DRSURI("drs://example.com/path/to/object")
        assert uri.id == "path/to/object"


class TestAccessType:
    def test_values(self) -> None:
        assert AccessType.s3.value == "s3"
        assert AccessType.https.value == "https"
        assert AccessType.gs.value == "gs"
