"""Tests for hytop.core.validators."""

from __future__ import annotations

import pytest

from hytop.core.validators import (
    parse_csv_ints,
    parse_csv_strings,
    parse_positive_float,
)

# ---------------------------------------------------------------------------
# parse_csv_ints
# ---------------------------------------------------------------------------


class TestParseCsvInts:
    def test_single(self):
        assert parse_csv_ints("0", "--devices") == [0]

    def test_multiple(self):
        assert parse_csv_ints("0,1,2", "--devices") == [0, 1, 2]

    def test_whitespace_trimmed(self):
        assert parse_csv_ints(" 0 , 1 ", "--devices") == [0, 1]

    def test_empty_string_raises(self):
        with pytest.raises(ValueError, match="cannot be empty"):
            parse_csv_ints("", "--devices")

    def test_only_commas_raises(self):
        with pytest.raises(ValueError, match="cannot be empty"):
            parse_csv_ints(",,,", "--devices")

    def test_non_integer_raises(self):
        with pytest.raises(ValueError, match="non-integer"):
            parse_csv_ints("0,abc", "--devices")

    def test_negative_rejected(self):
        # negative numbers fail .isdigit() → non-integer error
        with pytest.raises(ValueError, match="non-integer"):
            parse_csv_ints("-1", "--devices")

    def test_flag_in_error_message(self):
        with pytest.raises(ValueError, match="--devices"):
            parse_csv_ints("x", "--devices")


# ---------------------------------------------------------------------------
# parse_csv_strings
# ---------------------------------------------------------------------------


class TestParseCsvStrings:
    def test_single(self):
        assert parse_csv_strings("localhost", "--hosts") == ["localhost"]

    def test_multiple(self):
        assert parse_csv_strings("node01,node02", "--hosts") == ["node01", "node02"]

    def test_whitespace_trimmed(self):
        assert parse_csv_strings(" node01 , node02 ", "--hosts") == ["node01", "node02"]

    def test_empty_string_raises(self):
        with pytest.raises(ValueError, match="cannot be empty"):
            parse_csv_strings("", "--hosts")

    def test_only_commas_raises(self):
        with pytest.raises(ValueError, match="cannot be empty"):
            parse_csv_strings(",", "--hosts")

    def test_flag_in_error_message(self):
        with pytest.raises(ValueError, match="--hosts"):
            parse_csv_strings("", "--hosts")


# ---------------------------------------------------------------------------
# parse_positive_float
# ---------------------------------------------------------------------------


class TestParsePositiveFloat:
    def test_integer_string(self):
        assert parse_positive_float("1", "--window") == 1.0

    def test_float_string(self):
        assert parse_positive_float("0.5", "--window") == pytest.approx(0.5)

    def test_zero_raises(self):
        with pytest.raises(ValueError, match="positive"):
            parse_positive_float("0", "--window")

    def test_negative_raises(self):
        with pytest.raises(ValueError, match="positive"):
            parse_positive_float("-1", "--window")

    def test_non_numeric_raises(self):
        with pytest.raises(ValueError, match="non-numeric"):
            parse_positive_float("abc", "--window")

    def test_flag_in_error_message(self):
        with pytest.raises(ValueError, match="--window"):
            parse_positive_float("0", "--window")
