"""Tests for remote control model and API module."""

from __future__ import annotations

import pytest

from pybyd._api.control import (
    _build_control_inner,
    _is_remote_control_ready,
    _parse_control_result,
)
from pybyd.config import BydConfig
from pybyd.exceptions import BydRemoteControlError
from pybyd.models.control import RemoteCommand, RemoteControlResult


class TestRemoteCommand:
    def test_enum_values(self) -> None:
        assert RemoteCommand.LOCK.value == "10"
        assert RemoteCommand.UNLOCK.value == "11"
        assert RemoteCommand.FLASH_LIGHTS.value == "20"
        assert RemoteCommand.HORN.value == "21"
        assert RemoteCommand.START_CLIMATE.value == "30"
        assert RemoteCommand.STOP_CLIMATE.value == "31"

    def test_string_coercion(self) -> None:
        assert str(RemoteCommand.LOCK) == "10"
        assert RemoteCommand.LOCK == "10"

    def test_all_members(self) -> None:
        assert len(RemoteCommand) == 6


class TestBuildControlInner:
    def test_payload_structure(self, test_config: BydConfig) -> None:
        inner = _build_control_inner(
            test_config,
            "VIN123",
            RemoteCommand.LOCK,
            1700000000000,
        )
        assert inner["vin"] == "VIN123"
        assert inner["instructionCode"] == "10"
        assert inner["timeStamp"] == "1700000000000"
        assert inner["deviceType"] == test_config.device.device_type
        assert inner["imeiMD5"] == test_config.device.imei_md5
        assert len(inner["random"]) == 32

    def test_with_request_serial(self, test_config: BydConfig) -> None:
        inner = _build_control_inner(
            test_config,
            "VIN",
            RemoteCommand.UNLOCK,
            0,
            request_serial="SERIAL123",
        )
        assert inner["requestSerial"] == "SERIAL123"

    def test_without_request_serial(self, test_config: BydConfig) -> None:
        inner = _build_control_inner(
            test_config,
            "VIN",
            RemoteCommand.HORN,
            0,
        )
        assert "requestSerial" not in inner

    def test_instruction_code_varies(self, test_config: BydConfig) -> None:
        lock = _build_control_inner(test_config, "V", RemoteCommand.LOCK, 0)
        climate = _build_control_inner(test_config, "V", RemoteCommand.START_CLIMATE, 0)
        assert lock["instructionCode"] == "10"
        assert climate["instructionCode"] == "30"


class TestIsRemoteControlReady:
    def test_empty_data(self) -> None:
        assert _is_remote_control_ready({}) is False

    def test_pending(self) -> None:
        assert _is_remote_control_ready({"controlState": 0}) is False
        assert _is_remote_control_ready({"controlState": "0"}) is False

    def test_success(self) -> None:
        assert _is_remote_control_ready({"controlState": 1}) is True
        assert _is_remote_control_ready({"controlState": "1"}) is True

    def test_failed(self) -> None:
        assert _is_remote_control_ready({"controlState": 2}) is True
        assert _is_remote_control_ready({"controlState": "2"}) is True

    def test_result_field(self) -> None:
        assert _is_remote_control_ready({"result": "ok"}) is True

    def test_no_control_state_no_result(self) -> None:
        assert _is_remote_control_ready({"requestSerial": "abc"}) is False


class TestParseControlResult:
    def test_success(self) -> None:
        data = {"controlState": 1, "requestSerial": "S1"}
        result = _parse_control_result(data)
        assert result.control_state == 1
        assert result.success is True
        assert result.request_serial == "S1"
        assert result.raw is data

    def test_failure(self) -> None:
        data = {"controlState": 2}
        result = _parse_control_result(data)
        assert result.control_state == 2
        assert result.success is False

    def test_pending(self) -> None:
        data = {"controlState": 0}
        result = _parse_control_result(data)
        assert result.control_state == 0
        assert result.success is False

    def test_missing_state(self) -> None:
        result = _parse_control_result({})
        assert result.control_state == 0
        assert result.success is False

    def test_string_state(self) -> None:
        result = _parse_control_result({"controlState": "1"})
        assert result.control_state == 1
        assert result.success is True


class TestRemoteControlResultModel:
    def test_frozen(self) -> None:
        rc = RemoteControlResult(
            control_state=1,
            success=True,
            request_serial=None,
            raw={},
        )
        with pytest.raises(AttributeError):
            rc.success = False  # type: ignore[misc]


class TestBydRemoteControlError:
    def test_is_api_error(self) -> None:
        from pybyd.exceptions import BydApiError

        err = BydRemoteControlError("fail", code="2", endpoint="/control/remoteControl")
        assert isinstance(err, BydApiError)
        assert err.code == "2"
        assert err.endpoint == "/control/remoteControl"
