from __future__ import annotations

import json

from aegro.cli import app


class TestPurchaseOrdersGet:
    def test_get_purchase_order(self, runner, mock_settings, mock_client, temp_state):
        mock_client.get.return_value = {"_id": "po1", "orderDate": "2025-06-01"}
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(app, ["purchase-orders", "get", "po1"])
        assert result.exit_code == 0
        data = json.loads(result.stdout)
        assert data["orderDate"] == "2025-06-01"
        mock_client.get.assert_called_once_with("/pub/v1/purchase-orders/po1", api_key="key-1")

    def test_get_purchase_order_not_found(self, runner, mock_settings, mock_client, temp_state):
        mock_client.get.return_value = None
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(app, ["purchase-orders", "get", "missing"])
        assert result.exit_code == 0
        assert "nao encontrad" in result.stdout.lower()

    def test_get_purchase_order_no_farm(self, runner, mock_settings, temp_state):
        result = runner.invoke(app, ["purchase-orders", "get", "po1"])
        assert result.exit_code != 0


class TestPurchaseOrdersList:
    def test_list_no_filters(self, runner, mock_settings, mock_client, temp_state):
        mock_client.post.return_value = [{"_id": "po1", "orderDate": "2025-06-01"}]
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(app, ["purchase-orders", "list"])
        assert result.exit_code == 0
        data = json.loads(result.stdout)
        assert len(data) == 1
        call_body = mock_client.post.call_args.kwargs["json_body"]
        assert call_body["requiredPageNumber"] == 1
        assert call_body["maximumItemsPerPageCount"] == 50

    def test_list_with_filters(self, runner, mock_settings, mock_client, temp_state):
        mock_client.post.return_value = []
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(
            app,
            [
                "purchase-orders",
                "list",
                "--company-key",
                "c1",
                "--search-text",
                "sementes",
                "--start-date",
                "2025-01-01",
                "--end-date",
                "2025-12-31",
                "--delivery-status",
                "PENDING",
            ],
        )
        assert result.exit_code == 0
        call_body = mock_client.post.call_args.kwargs["json_body"]
        assert call_body["companyKey"] == "c1"
        assert call_body["searchText"] == "sementes"
        assert call_body["startDate"] == "2025-01-01"
        assert call_body["endDate"] == "2025-12-31"
        assert call_body["deliveryStatus"] == "PENDING"

    def test_list_with_page(self, runner, mock_settings, mock_client, temp_state):
        mock_client.post.return_value = []
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        runner.invoke(app, ["purchase-orders", "list", "--page", "3"])
        call_body = mock_client.post.call_args.kwargs["json_body"]
        assert call_body["requiredPageNumber"] == 3

    def test_list_empty_result(self, runner, mock_settings, mock_client, temp_state):
        mock_client.post.return_value = None
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(app, ["purchase-orders", "list"])
        assert result.exit_code == 0
        assert "nenhum" in result.stdout.lower()


class TestPurchaseOrdersCreate:
    def test_create_purchase_order(self, runner, mock_settings, mock_client, temp_state):
        mock_client.post.return_value = {"_id": "po-new", "orderDate": "2025-06-01"}
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        items_json = json.dumps([{"productKey": "p1", "quantity": 10}])
        result = runner.invoke(
            app,
            [
                "purchase-orders",
                "create",
                "--company-key",
                "c1",
                "--order-date",
                "2025-06-01",
                "--gross-amount",
                "5000",
                "--items",
                items_json,
            ],
        )
        assert result.exit_code == 0
        data = json.loads(result.stdout)
        assert data["_id"] == "po-new"
        call_body = mock_client.post.call_args.kwargs["json_body"]
        assert call_body["companyKey"] == "c1"
        assert call_body["orderDate"] == "2025-06-01"
        assert call_body["currencyCode"] == "BRL"
        assert call_body["grossAmount"] == 5000.0
        assert call_body["items"] == [{"productKey": "p1", "quantity": 10}]

    def test_create_purchase_order_with_optional_fields(
        self, runner, mock_settings, mock_client, temp_state
    ):
        mock_client.post.return_value = None
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        items_json = json.dumps([{"productKey": "p1", "quantity": 5}])
        result = runner.invoke(
            app,
            [
                "purchase-orders",
                "create",
                "--company-key",
                "c1",
                "--order-date",
                "2025-06-01",
                "--gross-amount",
                "3000",
                "--items",
                items_json,
                "--expected-delivery-date",
                "2025-07-01",
                "--description",
                "Compra de sementes",
                "--discount-amount",
                "150",
                "--company-order-code",
                "ORD-001",
                "--currency",
                "USD",
            ],
        )
        assert result.exit_code == 0
        assert "criada" in result.stdout.lower()
        call_body = mock_client.post.call_args.kwargs["json_body"]
        assert call_body["expectedDeliveryDate"] == "2025-07-01"
        assert call_body["description"] == "Compra de sementes"
        assert call_body["discountAmount"] == 150.0
        assert call_body["companyOrderCode"] == "ORD-001"
        assert call_body["currencyCode"] == "USD"

    def test_create_purchase_order_items_parsed(
        self, runner, mock_settings, mock_client, temp_state
    ):
        """Items JSON string is correctly parsed into a list."""
        mock_client.post.return_value = None
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        items_json = json.dumps(
            [
                {"productKey": "p1", "quantity": 10},
                {"productKey": "p2", "quantity": 20},
            ]
        )
        runner.invoke(
            app,
            [
                "purchase-orders",
                "create",
                "--company-key",
                "c1",
                "--order-date",
                "2025-06-01",
                "--gross-amount",
                "8000",
                "--items",
                items_json,
            ],
        )
        call_body = mock_client.post.call_args.kwargs["json_body"]
        assert len(call_body["items"]) == 2
        assert call_body["items"][0]["productKey"] == "p1"
        assert call_body["items"][1]["productKey"] == "p2"

    def test_create_purchase_order_no_farm(self, runner, mock_settings, temp_state):
        items_json = json.dumps([{"productKey": "p1", "quantity": 10}])
        result = runner.invoke(
            app,
            [
                "purchase-orders",
                "create",
                "--company-key",
                "c1",
                "--order-date",
                "2025-06-01",
                "--gross-amount",
                "5000",
                "--items",
                items_json,
            ],
        )
        assert result.exit_code != 0
