"""Tests for SkytellsError and related types."""

import pytest

from skytells import SkytellsError
from skytells.types.shared import ApiErrorId


class TestSkytellsError:
    def test_basic_construction(self):
        err = SkytellsError("Something went wrong", "UNAUTHORIZED", "Token invalid", 401)
        assert str(err) == "Something went wrong"
        assert err.error_id == "UNAUTHORIZED"
        assert err.details == "Token invalid"
        assert err.http_status == 401

    def test_default_http_status(self):
        err = SkytellsError("Network error", "NETWORK_ERROR", "No connection")
        assert err.http_status == 0

    def test_is_exception(self):
        err = SkytellsError("msg", "ID", "details", 500)
        assert isinstance(err, Exception)

    def test_isinstance_check(self):
        err = SkytellsError("msg", "ID", "details")
        assert isinstance(err, SkytellsError)

    def test_can_be_raised_and_caught(self):
        with pytest.raises(SkytellsError) as exc_info:
            raise SkytellsError("fail", "MODEL_NOT_FOUND", "No such model", 404)
        assert exc_info.value.error_id == "MODEL_NOT_FOUND"
        assert exc_info.value.http_status == 404

    def test_repr(self):
        err = SkytellsError("msg", "UNAUTHORIZED", "details", 401)
        r = repr(err)
        assert "SkytellsError" in r
        assert "UNAUTHORIZED" in r
        assert "401" in r


class TestApiErrorId:
    def test_api_error_values(self):
        """API-returned error IDs (from the server)."""
        assert ApiErrorId.UNAUTHORIZED == "UNAUTHORIZED"
        assert ApiErrorId.INVALID_PARAMETER == "INVALID_PARAMETER"
        assert ApiErrorId.INVALID_DATE_FORMAT == "INVALID_DATE_FORMAT"
        assert ApiErrorId.INVALID_DATE_RANGE == "INVALID_DATE_RANGE"
        assert ApiErrorId.MODEL_NOT_FOUND == "MODEL_NOT_FOUND"
        assert ApiErrorId.INTERNAL_ERROR == "INTERNAL_ERROR"
        assert ApiErrorId.INVALID_INPUT == "INVALID_INPUT"
        assert ApiErrorId.INSUFFICIENT_CREDITS == "INSUFFICIENT_CREDITS"
        assert ApiErrorId.ACCOUNT_SUSPENDED == "ACCOUNT_SUSPENDED"
        assert ApiErrorId.PAYMENT_REQUIRED == "PAYMENT_REQUIRED"
        assert ApiErrorId.SECURITY_VIOLATION == "SECURITY_VIOLATION"
        assert ApiErrorId.RATE_LIMIT_EXCEEDED == "RATE_LIMIT_EXCEEDED"
        assert ApiErrorId.INFRASTRUCTURE_ERROR == "INFRASTRUCTURE_ERROR"

    def test_client_error_values(self):
        """Client-side error IDs (raised by the SDK itself)."""
        assert ApiErrorId.PREDICTION_FAILED == "PREDICTION_FAILED"
        assert ApiErrorId.WAIT_TIMEOUT == "WAIT_TIMEOUT"
        assert ApiErrorId.REQUEST_TIMEOUT == "REQUEST_TIMEOUT"
        assert ApiErrorId.NETWORK_ERROR == "NETWORK_ERROR"
        assert ApiErrorId.SERVER_ERROR == "SERVER_ERROR"
        assert ApiErrorId.INVALID_JSON == "INVALID_JSON"

    def test_is_string_subclass(self):
        assert isinstance(ApiErrorId.UNAUTHORIZED, str)
        assert isinstance(ApiErrorId.INFRASTRUCTURE_ERROR, str)

    def test_all_members_count(self):
        assert len(ApiErrorId) == 19

    def test_error_id_usable_in_match(self):
        err = SkytellsError("Infrastructure down", "INFRASTRUCTURE_ERROR", "details", 503)
        assert err.error_id == ApiErrorId.INFRASTRUCTURE_ERROR
        assert err.error_id == "INFRASTRUCTURE_ERROR"
