"""Tests for Data Connect models."""

from __future__ import annotations

from ai4gh.specs.data_connect.models import (
    ColumnSchema,
    SearchRequest,
    TableData,
    TableInfo,
    TableListResponse,
    TableSchema,
)


class TestColumnSchema:
    def test_required_fields(self) -> None:
        col = ColumnSchema(name="sample_id")
        assert col.name == "sample_id"
        assert col.data_type is None

    def test_full(self) -> None:
        col = ColumnSchema(
            name="age",
            data_type="integer",
            description="Patient age",
            is_nullable=True,
            ontology_term="EFO:0000246",
        )
        assert col.data_type == "integer"
        assert col.is_nullable is True
        assert col.ontology_term == "EFO:0000246"


class TestTableSchema:
    def test_minimal(self) -> None:
        schema = TableSchema()
        assert schema.columns is None

    def test_with_columns(self) -> None:
        schema = TableSchema(
            columns=[
                ColumnSchema(name="id", data_type="string"),
                ColumnSchema(name="age", data_type="integer"),
            ],
            description="Patient table schema",
        )
        assert len(schema.columns) == 2
        assert schema.description == "Patient table schema"


class TestTableInfo:
    def test_required_fields(self) -> None:
        info = TableInfo(name="patients")
        assert info.name == "patients"
        assert info.description is None
        assert info.data_model is None

    def test_with_schema(self) -> None:
        info = TableInfo(
            name="variants",
            description="Genomic variants",
            data_model=TableSchema(columns=[ColumnSchema(name="chrom", data_type="string")]),
        )
        assert info.data_model is not None
        assert len(info.data_model.columns) == 1


class TestTableListResponse:
    def test_empty(self) -> None:
        resp = TableListResponse()
        assert resp.tables is None
        assert resp.pagination is None

    def test_with_tables(self) -> None:
        resp = TableListResponse(
            tables=[
                TableInfo(name="patients"),
                TableInfo(name="variants"),
            ],
            pagination={"next_page_url": "https://example.com/tables?page=2"},
        )
        assert len(resp.tables) == 2
        assert "next_page_url" in resp.pagination


class TestTableData:
    def test_empty(self) -> None:
        data = TableData()
        assert data.data is None
        assert data.data_model is None

    def test_with_rows(self) -> None:
        data = TableData(
            data=[
                {"id": "1", "name": "Alice", "age": 30},
                {"id": "2", "name": "Bob", "age": 25},
            ],
            data_model=TableSchema(
                columns=[
                    ColumnSchema(name="id", data_type="string"),
                    ColumnSchema(name="name", data_type="string"),
                    ColumnSchema(name="age", data_type="integer"),
                ]
            ),
        )
        assert len(data.data) == 2
        assert data.data[0]["name"] == "Alice"
        assert len(data.data_model.columns) == 3

    def test_with_pagination(self) -> None:
        data = TableData(
            data=[{"id": "1"}],
            pagination={
                "next_page_url": "https://example.com/data?page=2",
            },
        )
        assert "next_page_url" in data.pagination


class TestSearchRequest:
    def test_required_fields(self) -> None:
        req = SearchRequest(query="SELECT * FROM patients")
        assert req.query == "SELECT * FROM patients"
        assert req.page_size is None

    def test_with_pagination(self) -> None:
        req = SearchRequest(
            query="SELECT * FROM variants WHERE chrom = '1'",
            page_size=100,
            page_token="token-1",
        )
        assert req.page_size == 100
        assert req.page_token == "token-1"


class TestExtraFields:
    def test_allows_extra(self) -> None:
        info = TableInfo.model_validate({"name": "table1", "custom_prop": "value"})
        assert info.custom_prop == "value"
