import pytest
import operator

import virtool.organize


@pytest.fixture
def subtraction_documents():
    return [
        {"_id": 1, "ready": True, "job": {"id": "345asd"}},
        {"_id": 2, "ready": False, "job": {"id": "3i4l1s"}},
        {"_id": 3, "ready": True, "job": {"id": "8jj3lq"}}
    ]


class TestJobId:

    async def test(self, test_motor, subtraction_documents):
        """
        Test that flat ``job`` fields are updated to the new subdocument format.

        """
        subtraction_documents[1]["job"] = subtraction_documents[1]["job"]["id"]

        await test_motor.hosts.insert_many(subtraction_documents)

        await virtool.organize.organize_subtraction(test_motor)

        subtractions = await test_motor.subtraction.find().to_list(None)

        assert sorted([s["job"] for s in subtractions], key=operator.itemgetter("id")) == [
            {"id": "345asd"},
            {"id": "3i4l1s"},
            {"id": "8jj3lq"}
        ]

    async def test_missing_job(self, test_motor, subtraction_documents):
        """
        Test that the ``job`` field is set to a default value of ``None`` if it doesn't exist.

        """
        del subtraction_documents[0]["job"]
        del subtraction_documents[2]["job"]

        await test_motor.hosts.insert_many(subtraction_documents)

        await virtool.organize.organize_subtraction(test_motor)

        subtractions = await test_motor.subtraction.find().to_list(None)

        assert [s["job"] for s in subtractions] == [None, {"id": "3i4l1s"}, None]

    async def test_no_change(self, test_motor, subtraction_documents):
        """
        Test that no changes are made if the document already contains a valid ``job`` field.

        """
        await test_motor.subtraction.insert_many(subtraction_documents)

        await virtool.organize.organize_subtraction(test_motor)

        subtractions = await test_motor.subtraction.find().to_list(None)

        assert [s["job"] for s in subtractions] == [
            {"id": "345asd"},
            {"id": "3i4l1s"},
            {"id": "8jj3lq"}
        ]


class TestAddedReady:

    async def test_only_ready(self, test_motor, subtraction_documents):
        """
        Test that conversion of the ``added`` field to ``ready`` does not corrupt documents that already have the
        ``ready`` field set.

        """
        await test_motor.subtraction.insert_many(subtraction_documents)

        await virtool.organize.organize_subtraction(test_motor)

        docs = await test_motor.subtraction.find({}, ["ready", "added"]).to_list(None)

        assert all(["added" not in d for d in docs])

        assert {d["ready"] for d in docs} == {True, False, True}

    async def test_has_ready(self, test_motor, subtraction_documents):
        """
        Test that conversion of the ``added`` field to ``ready`` is successful when some documents are using the
        ``added`` field.

        """

        del subtraction_documents[0]["ready"]
        subtraction_documents[0]["added"] = True

        test_motor.subtraction.insert_many(subtraction_documents)

        await virtool.organize.organize_subtraction(test_motor)

        docs = await test_motor.subtraction.find({}, ["ready", "added"]).to_list(None)

        assert all(["added" not in d for d in docs])

        assert {d["ready"] for d in docs} == {True, False, True}

    async def test_neither(self, test_motor, subtraction_documents):
        """
        Test that documents with no ``ready`` or ``added`` field will have their ``ready`` fields set to ``True`` by
        default.

        """
        del subtraction_documents[1]["ready"]

        await test_motor.subtraction.insert_many(subtraction_documents)

        await virtool.organize.organize_subtraction(test_motor)

        docs = await test_motor.subtraction.find({}, ["ready", "added"]).to_list(None)

        assert all(["added" not in d for d in docs])

        assert all(d["ready"] for d in docs)

@@ -7,22 +7,20 @@
  pytest%0A
-import
+from
  operato
@@ -20,16 +20,34 @@
 operator
+ import itemgetter
 %0A%0Aimport
@@ -848,17 +848,8 @@
 key=
-operator.
 item
@@ -1462,32 +1462,39 @@
 %0A        assert 
+sorted(
 %5Bs%5B%22job%22%5D for s 
@@ -1509,20 +1509,38 @@
 actions%5D
- == 
+, key=bool) == sorted(
 %5BNone, %7B
@@ -1561,16 +1561,27 @@
 %7D, None%5D
+, key=bool)
 %0A%0A    as
@@ -1991,16 +1991,23 @@
  assert 
+sorted(
 %5Bs%5B%22job%22
@@ -2030,20 +2030,50 @@
 actions%5D
- == 
+, key=itemgetter(%22id%22)) == sorted(
 %5B%0A      
@@ -2147,32 +2147,32 @@
 %22id%22: %228jj3lq%22%7D%0A
-
         %5D%0A%0A%0Aclas
@@ -2160,24 +2160,47 @@
 %22%7D%0A        %5D
+, key=itemgetter(%22id%22))
 %0A%0A%0Aclass Tes

Fix more failing tests on Travis