"""Tests for Pydantic models.

Tests for telemetry and query models. This SDK is query-only.
"""

from datetime import datetime, UTC
from uuid import UUID, uuid4

import pytest
from pydantic import ValidationError as PydanticValidationError

from fishinfo.models.telemetry import DataType, TelemetryPoint
from fishinfo.models.query import (
    TelemetryQueryParams,
    OrderDirection,
    AggregationParams,
    AggregationType,
    DownsampleParams,
)


class TestTelemetryPoint:
    """Tests for TelemetryPoint model."""

    def test_create_position_point(self):
        """Test creating a position telemetry point."""
        now = datetime.now(UTC)
        vessel_id = uuid4()
        tenant_id = uuid4()

        point = TelemetryPoint(
            time=now,
            vessel_id=vessel_id,
            tenant_id=tenant_id,
            data_type=DataType.POSITION,
            latitude=64.1466,
            longitude=-21.9426,
            quality=95,
            source="gps",
        )

        assert point.time == now
        assert point.vessel_id == vessel_id
        assert point.tenant_id == tenant_id
        assert point.data_type == DataType.POSITION
        assert point.latitude == 64.1466
        assert point.longitude == -21.9426
        assert point.quality == 95
        assert point.source == "gps"

    def test_create_speed_point(self):
        """Test creating a speed telemetry point."""
        now = datetime.now(UTC)
        vessel_id = uuid4()
        tenant_id = uuid4()

        point = TelemetryPoint(
            time=now,
            vessel_id=vessel_id,
            tenant_id=tenant_id,
            data_type=DataType.SPEED,
            value=15.5,
            unit="knots",
        )

        assert point.data_type == DataType.SPEED
        assert point.value == 15.5
        assert point.unit == "knots"

    def test_invalid_latitude(self):
        """Test validation of invalid latitude."""
        with pytest.raises(PydanticValidationError) as exc_info:
            TelemetryPoint(
                time=datetime.now(UTC),
                vessel_id=uuid4(),
                tenant_id=uuid4(),
                data_type=DataType.POSITION,
                latitude=100.0,  # Invalid: > 90
                longitude=0.0,
            )

        errors = exc_info.value.errors()
        assert any("latitude" in str(err) for err in errors)

    def test_invalid_longitude(self):
        """Test validation of invalid longitude."""
        with pytest.raises(PydanticValidationError) as exc_info:
            TelemetryPoint(
                time=datetime.now(UTC),
                vessel_id=uuid4(),
                tenant_id=uuid4(),
                data_type=DataType.POSITION,
                latitude=0.0,
                longitude=200.0,  # Invalid: > 180
            )

        errors = exc_info.value.errors()
        assert any("longitude" in str(err) for err in errors)

    def test_quality_range(self):
        """Test validation of quality score range."""
        # Valid quality
        point = TelemetryPoint(
            time=datetime.now(UTC),
            vessel_id=uuid4(),
            tenant_id=uuid4(),
            data_type=DataType.POSITION,
            latitude=0.0,
            longitude=0.0,
            quality=100,
        )
        assert point.quality == 100

        # Invalid quality (> 100)
        with pytest.raises(PydanticValidationError):
            TelemetryPoint(
                time=datetime.now(UTC),
                vessel_id=uuid4(),
                tenant_id=uuid4(),
                data_type=DataType.POSITION,
                latitude=0.0,
                longitude=0.0,
                quality=101,
            )

    def test_json_serialization(self):
        """Test JSON serialization."""
        point = TelemetryPoint(
            time=datetime.now(UTC),
            vessel_id=uuid4(),
            tenant_id=uuid4(),
            data_type=DataType.POSITION,
            latitude=64.1466,
            longitude=-21.9426,
        )

        json_data = point.model_dump(mode="json")
        assert "time" in json_data
        assert "vessel_id" in json_data
        assert "data_type" in json_data


class TestTelemetryQueryParams:
    """Tests for TelemetryQueryParams model."""

    def test_valid_params(self):
        """Test valid query parameters."""
        params = TelemetryQueryParams(
            vessel_id=uuid4(),
            data_type="position,speed",
            start_time=datetime.now(UTC),
            end_time=datetime.now(UTC),
            limit=100,
            offset=0,
            order=OrderDirection.DESC,
        )

        assert params.limit == 100
        assert params.order == OrderDirection.DESC

    def test_invalid_data_type(self):
        """Test validation of invalid data type."""
        with pytest.raises(PydanticValidationError) as exc_info:
            TelemetryQueryParams(
                vessel_id=uuid4(),
                data_type="invalid_type",
            )

        errors = exc_info.value.errors()
        assert any("data_type" in str(err) for err in errors)

    def test_limit_validation(self):
        """Test limit validation."""
        # Valid limit
        params = TelemetryQueryParams(
            vessel_id=uuid4(),
            limit=5000,
        )
        assert params.limit == 5000

        # Too large limit
        with pytest.raises(PydanticValidationError):
            TelemetryQueryParams(
                vessel_id=uuid4(),
                limit=20000,  # > 10000
            )


class TestAggregationParams:
    """Tests for AggregationParams model."""

    def test_valid_interval(self):
        """Test valid interval formats."""
        valid_intervals = [
            "1 second",
            "5 minutes",
            "1 hour",
            "2 hours",
            "1 day",
            "7 days",
        ]

        for interval in valid_intervals:
            params = AggregationParams(
                vessel_id=uuid4(),
                data_type=DataType.SPEED,
                start_time=datetime.now(UTC),
                end_time=datetime.now(UTC),
                interval=interval,
            )
            assert params.interval == interval

    def test_invalid_interval(self):
        """Test invalid interval format."""
        with pytest.raises(PydanticValidationError) as exc_info:
            AggregationParams(
                vessel_id=uuid4(),
                data_type=DataType.SPEED,
                start_time=datetime.now(UTC),
                end_time=datetime.now(UTC),
                interval="invalid",
            )

        errors = exc_info.value.errors()
        assert any("interval" in str(err) for err in errors)


class TestDownsampleParams:
    """Tests for DownsampleParams model."""

    def test_valid_params(self):
        """Test valid downsample parameters."""
        params = DownsampleParams(
            vessel_id=uuid4(),
            data_type=DataType.POSITION,
            start_time=datetime.now(UTC),
            end_time=datetime.now(UTC),
            target_points=500,
        )

        assert params.target_points == 500

    def test_target_points_validation(self):
        """Test target_points validation."""
        # Too small
        with pytest.raises(PydanticValidationError):
            DownsampleParams(
                vessel_id=uuid4(),
                data_type=DataType.POSITION,
                start_time=datetime.now(UTC),
                end_time=datetime.now(UTC),
                target_points=5,  # < 10
            )

        # Too large
        with pytest.raises(PydanticValidationError):
            DownsampleParams(
                vessel_id=uuid4(),
                data_type=DataType.POSITION,
                start_time=datetime.now(UTC),
                end_time=datetime.now(UTC),
                target_points=20000,  # > 10000
            )
