"""Tests for the CLI."""

import json
from unittest.mock import patch

from flight_search.cli import main, format_text_output
from flight_search.search import Flight, SearchResult


class TestFormatTextOutput:
    """Tests for text output formatting."""

    def test_format_one_way(self):
        flight = Flight(
            airline="United",
            departure_time="10:00 AM",
            arrival_time="12:30 PM",
            duration="2 hr 30 min",
            stops=0,
            stop_info=None,
            price=199,
            is_best=True,
            arrival_ahead=None,
        )

        result = SearchResult(
            flights=[flight],
            current_price="typical",
            origin="DEN",
            destination="LAX",
            date="2025-03-01",
            return_date=None,
        )

        output = format_text_output(result)

        assert "DEN → LAX" in output
        assert "One way" in output
        assert "2025-03-01" in output
        assert "United" in output
        assert "BEST" in output
        assert "$199" in output
        assert "Nonstop" in output

    def test_format_round_trip(self):
        result = SearchResult(
            flights=[],
            current_price="low",
            origin="JFK",
            destination="LHR",
            date="2025-06-15",
            return_date="2025-06-22",
        )

        output = format_text_output(result)

        assert "Round trip" in output
        assert "2025-06-15 - 2025-06-22" in output

    def test_format_with_stops(self):
        flight = Flight(
            airline="Delta",
            departure_time="8:00 AM",
            arrival_time="5:00 PM",
            duration="9 hr",
            stops=1,
            stop_info="ATL",
            price=299,
            is_best=False,
            arrival_ahead=None,
        )

        result = SearchResult(
            flights=[flight],
            current_price=None,
            origin="LAX",
            destination="JFK",
            date="2025-04-01",
            return_date=None,
        )

        output = format_text_output(result)

        assert "1 stop" in output

    def test_format_no_flights(self):
        result = SearchResult(
            flights=[],
            current_price=None,
            origin="ABC",
            destination="XYZ",
            date="2025-01-01",
            return_date=None,
        )

        output = format_text_output(result)

        assert "No flights found" in output

    def test_format_next_day_arrival(self):
        flight = Flight(
            airline="Frontier",
            departure_time="11:00 PM",
            arrival_time="1:00 AM",
            duration="3 hr",
            stops=0,
            stop_info=None,
            price=84,
            is_best=True,
            arrival_ahead="+1",
        )

        result = SearchResult(
            flights=[flight],
            current_price="typical",
            origin="DEN",
            destination="LAX",
            date="2025-03-01",
            return_date=None,
        )

        output = format_text_output(result)

        assert "+1" in output


class TestCLI:
    """Tests for CLI main function."""

    @patch("flight_search.cli.search_flights")
    def test_basic_search(self, mock_search):
        """Test basic CLI invocation."""
        mock_search.return_value = SearchResult(
            flights=[],
            current_price="typical",
            origin="DEN",
            destination="LAX",
            date="2025-03-01",
            return_date=None,
        )

        result = main(["DEN", "LAX", "--date", "2025-03-01"])

        assert result == 0
        mock_search.assert_called_once()

    @patch("flight_search.cli.search_flights")
    def test_json_output(self, mock_search, capsys):
        """Test JSON output format."""
        flight = Flight(
            airline="United",
            departure_time="10:00 AM",
            arrival_time="12:30 PM",
            duration="2 hr 30 min",
            stops=0,
            stop_info=None,
            price=199,
            is_best=True,
            arrival_ahead=None,
        )

        mock_search.return_value = SearchResult(
            flights=[flight],
            current_price="typical",
            origin="DEN",
            destination="LAX",
            date="2025-03-01",
            return_date=None,
        )

        result = main(["DEN", "LAX", "--date", "2025-03-01", "--output", "json"])

        assert result == 0

        captured = capsys.readouterr()
        data = json.loads(captured.out)

        assert data["origin"] == "DEN"
        assert data["destination"] == "LAX"
        assert len(data["flights"]) == 1

    @patch("flight_search.cli.search_flights")
    def test_round_trip(self, mock_search):
        """Test round trip arguments."""
        mock_search.return_value = SearchResult(
            flights=[],
            current_price=None,
            origin="JFK",
            destination="LHR",
            date="2025-06-15",
            return_date="2025-06-22",
        )

        main(["JFK", "LHR", "-d", "2025-06-15", "-r", "2025-06-22"])

        call_kwargs = mock_search.call_args[1]
        assert call_kwargs["return_date"] == "2025-06-22"

    @patch("flight_search.cli.search_flights")
    def test_passengers_and_class(self, mock_search):
        """Test passenger count and class arguments."""
        mock_search.return_value = SearchResult(
            flights=[],
            current_price=None,
            origin="SFO",
            destination="NRT",
            date="2025-04-01",
            return_date=None,
        )

        main(["SFO", "NRT", "-d", "2025-04-01", "-a", "2", "-c", "1", "-C", "business"])

        call_kwargs = mock_search.call_args[1]
        assert call_kwargs["adults"] == 2
        assert call_kwargs["children"] == 1
        assert call_kwargs["seat_class"] == "business"

    @patch("flight_search.cli.search_flights")
    def test_uppercase_airports(self, mock_search):
        """Test that airport codes are uppercased."""
        mock_search.return_value = SearchResult(
            flights=[],
            current_price=None,
            origin="DEN",
            destination="LAX",
            date="2025-03-01",
            return_date=None,
        )

        main(["den", "lax", "-d", "2025-03-01"])

        call_kwargs = mock_search.call_args[1]
        assert call_kwargs["origin"] == "DEN"
        assert call_kwargs["destination"] == "LAX"

    @patch("flight_search.cli.search_flights")
    def test_error_handling(self, mock_search, capsys):
        """Test error handling."""
        mock_search.side_effect = Exception("API Error")

        result = main(["DEN", "LAX", "-d", "2025-03-01"])

        assert result == 1

        captured = capsys.readouterr()
        assert "Error" in captured.err

    @patch("flight_search.cli.search_flights")
    def test_limit_argument(self, mock_search):
        """Test limit argument."""
        mock_search.return_value = SearchResult(
            flights=[],
            current_price=None,
            origin="DEN",
            destination="LAX",
            date="2025-03-01",
            return_date=None,
        )

        main(["DEN", "LAX", "-d", "2025-03-01", "-l", "5"])

        call_kwargs = mock_search.call_args[1]
        assert call_kwargs["max_results"] == 5
