from __future__ import annotations

import json

from aegro.cli import app


class TestPurchaseRequisitionsGet:
    def test_get(self, runner, mock_settings, mock_client, temp_state):
        mock_client.get.return_value = {"_id": "pr1"}
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(app, ["purchase-requisitions", "get", "purchaseRequisition::abc"])
        assert result.exit_code == 0
        mock_client.get.assert_called_once_with(
            "/pub/v1/purchase-requisitions/purchaseRequisition::abc", api_key="key-1"
        )


class TestPurchaseRequisitionsList:
    def test_list_defaults(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-requisitions", "list"])
        assert result.exit_code == 0
        call = mock_client.post.call_args
        assert call.args[0] == "/pub/v1/purchase-requisitions/filter"

    def test_list_filters(self, runner, mock_settings, mock_client, temp_state):
        mock_client.post.return_value = []
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        runner.invoke(
            app,
            [
                "purchase-requisitions",
                "list",
                "--status",
                "OPEN",
                "--status",
                "APPROVED",
                "--start-date",
                "2025-01-01",
                "--end-due-date",
                "2025-12-31",
                "--element-key",
                "element::e1",
                "--tag",
                "safra",
            ],
        )
        body = mock_client.post.call_args.kwargs["json_body"]
        assert body["statuses"] == ["OPEN", "APPROVED"]
        assert body["startDate"] == "2025-01-01"
        assert body["endDueDate"] == "2025-12-31"
        assert body["elementKeys"] == ["element::e1"]
        assert body["tags"] == ["safra"]


class TestPurchaseRequisitionsCreate:
    def test_create(self, runner, mock_settings, mock_client, temp_state):
        mock_client.post.return_value = {"_id": "pr-new"}
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(
            app,
            [
                "purchase-requisitions",
                "create",
                "--date",
                "2025-06-01",
                "--due-date",
                "2025-06-15",
                "--status",
                "OPEN",
                "--requisitioners",
                '[{"userKey":"user::u1"}]',
                "--inputs",
                '[{"elementKey":"element::e1","quantity":10,"measuringUnit":"kg"}]',
            ],
        )
        assert result.exit_code == 0
        data = json.loads(result.stdout)
        assert data["_id"] == "pr-new"
        body = mock_client.post.call_args.kwargs["json_body"]
        assert body["date"] == "2025-06-01"
        assert body["status"] == "OPEN"
        assert body["requisitioners"] == [{"userKey": "user::u1"}]
        assert body["inputs"] == [
            {"elementKey": "element::e1", "quantity": 10, "measuringUnit": "kg"}
        ]

    def test_create_invalid_json(self, runner, mock_settings, mock_client, temp_state):
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(
            app,
            [
                "purchase-requisitions",
                "create",
                "--date",
                "2025-06-01",
                "--due-date",
                "2025-06-15",
                "--status",
                "OPEN",
                "--requisitioners",
                "not json",
                "--inputs",
                "[]",
            ],
        )
        assert result.exit_code == 4

    def test_create_requisitioners_not_list(self, runner, mock_settings, mock_client, temp_state):
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(
            app,
            [
                "purchase-requisitions",
                "create",
                "--date",
                "2025-06-01",
                "--due-date",
                "2025-06-15",
                "--status",
                "OPEN",
                "--requisitioners",
                '{"not":"list"}',
                "--inputs",
                "[]",
            ],
        )
        assert result.exit_code == 4


class TestPurchaseRequisitionsUpdate:
    def test_update(self, runner, mock_settings, mock_client, temp_state):
        mock_client.put.return_value = {"_id": "pr1"}
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(
            app,
            [
                "purchase-requisitions",
                "update",
                "purchaseRequisition::abc",
                "--body",
                '{"date":"2025-06-01","dueDate":"2025-06-15","status":"APPROVED","requisitioners":[],"inputs":[]}',
            ],
        )
        assert result.exit_code == 0
        mock_client.put.assert_called_once()
        call = mock_client.put.call_args
        assert call.args[0] == "/pub/v1/purchase-requisitions/purchaseRequisition::abc"
        assert call.kwargs["json_body"]["status"] == "APPROVED"

    def test_update_non_object(self, runner, mock_settings, mock_client, temp_state):
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(
            app,
            [
                "purchase-requisitions",
                "update",
                "purchaseRequisition::abc",
                "--body",
                "[]",
            ],
        )
        assert result.exit_code == 4
