"""Tests for CLI commands."""

from __future__ import annotations

import json

import pytest

from meridian_euid.cli import main


class TestValidateCommand:
    """Tests for 'validate' CLI command."""

    def test_valid_production(self, capsys: pytest.CaptureFixture[str]) -> None:
        """Valid production EUID returns 0 and prints VALID."""
        exit_code = main(["validate", "TX-1C", "--env", "production"])
        assert exit_code == 0
        captured = capsys.readouterr()
        assert "VALID: TX-1C" in captured.out

    def test_invalid_production(self, capsys: pytest.CaptureFixture[str]) -> None:
        """Invalid production EUID returns 1 and prints INVALID."""
        exit_code = main(["validate", "TX-1D", "--env", "production"])
        assert exit_code == 1
        captured = capsys.readouterr()
        assert "INVALID" in captured.err

    def test_valid_sandbox(self, capsys: pytest.CaptureFixture[str]) -> None:
        """Valid sandbox EUID with allowed prefix returns 0."""
        exit_code = main(
            ["validate", "X:TAP-3VX", "--env", "sandbox", "--allowed-prefixes", "X"]
        )
        assert exit_code == 0
        captured = capsys.readouterr()
        assert "VALID: X:TAP-3VX" in captured.out

    def test_sandbox_wrong_prefix(self, capsys: pytest.CaptureFixture[str]) -> None:
        """Sandbox EUID with wrong prefix returns 1."""
        exit_code = main(
            ["validate", "X:TAP-3VX", "--env", "sandbox", "--allowed-prefixes", "Y"]
        )
        assert exit_code == 1
        captured = capsys.readouterr()
        assert "INVALID" in captured.err

    def test_sandbox_multiple_prefixes(
        self, capsys: pytest.CaptureFixture[str]
    ) -> None:
        """Sandbox with multiple allowed prefixes works."""
        exit_code = main(
            ["validate", "X:TAP-3VX", "--env", "sandbox", "--allowed-prefixes", "X,Y,Z"]
        )
        assert exit_code == 0

    def test_lowercase_rejected(self, capsys: pytest.CaptureFixture[str]) -> None:
        """Lowercase EUID is rejected (no normalization)."""
        exit_code = main(["validate", "tx-1c", "--env", "production"])
        assert exit_code == 1
        captured = capsys.readouterr()
        assert "INVALID" in captured.err

    def test_one_char_category_rejected(
        self, capsys: pytest.CaptureFixture[str]
    ) -> None:
        """Single-character category is rejected."""
        exit_code = main(["validate", "T-14", "--env", "production"])
        assert exit_code == 1
        captured = capsys.readouterr()
        assert "INVALID" in captured.err


class TestComputeCheckCommand:
    """Tests for 'compute-check' CLI command."""

    def test_valid_payload(self, capsys: pytest.CaptureFixture[str]) -> None:
        """Valid payload prints check character and returns 0."""
        exit_code = main(["compute-check", "TX1"])
        assert exit_code == 0
        captured = capsys.readouterr()
        assert captured.out.strip() == "C"

    def test_invalid_payload(self, capsys: pytest.CaptureFixture[str]) -> None:
        """Invalid payload returns 1 with error."""
        exit_code = main(["compute-check", "t1"])  # lowercase
        assert exit_code == 1
        captured = capsys.readouterr()
        assert "ERROR" in captured.err


class TestEncodeCommand:
    """Tests for 'encode' CLI command."""

    def test_production_encode(self, capsys: pytest.CaptureFixture[str]) -> None:
        """Encode a production EUID."""
        exit_code = main(["encode", "1", "TX"])
        assert exit_code == 0
        captured = capsys.readouterr()
        assert captured.out.strip() == "TX-1C"

    def test_sandbox_encode(self, capsys: pytest.CaptureFixture[str]) -> None:
        """Encode a sandbox EUID."""
        exit_code = main(["encode", "123", "TAP", "--sandbox", "X"])
        assert exit_code == 0
        captured = capsys.readouterr()
        assert captured.out.strip() == "X:TAP-3VX"

    def test_invalid_category_returns_error(
        self, capsys: pytest.CaptureFixture[str]
    ) -> None:
        """Short category returns error."""
        exit_code = main(["encode", "1", "T"])
        assert exit_code == 1
        captured = capsys.readouterr()
        assert "ERROR" in captured.err

    def test_reserved_sandbox_returns_error(
        self, capsys: pytest.CaptureFixture[str]
    ) -> None:
        """Reserved sandbox prefix returns error."""
        exit_code = main(["encode", "1", "TX", "--sandbox", "A"])
        assert exit_code == 1
        captured = capsys.readouterr()
        assert "ERROR" in captured.err


class TestParseCommand:
    """Tests for 'parse' CLI command."""

    def test_production_parse(self, capsys: pytest.CaptureFixture[str]) -> None:
        """Parse a production EUID returns JSON."""
        exit_code = main(["parse", "TX-1C"])
        assert exit_code == 0
        captured = capsys.readouterr()
        result = json.loads(captured.out)
        assert result["category"] == "TX"
        assert result["integer"] == 1
        assert result["sandbox"] is None

    def test_sandbox_parse(self, capsys: pytest.CaptureFixture[str]) -> None:
        """Parse a sandbox EUID returns JSON."""
        exit_code = main(["parse", "X:TAP-3VX"])
        assert exit_code == 0
        captured = capsys.readouterr()
        result = json.loads(captured.out)
        assert result["category"] == "TAP"
        assert result["integer"] == 123
        assert result["sandbox"] == "X"

    def test_invalid_euid_returns_error(
        self, capsys: pytest.CaptureFixture[str]
    ) -> None:
        """Invalid EUID returns error."""
        exit_code = main(["parse", "TX-1D"])
        assert exit_code == 1
        captured = capsys.readouterr()
        assert "ERROR" in captured.err
