# -*- coding: utf-8; -*-
#
# This file is part of Superdesk.
#
# Copyright 2013, 2014 Sourcefabric z.u. and contributors.
#
# For the full copyright and license information, please see the
# AUTHORS and LICENSE files distributed with this source code, or
# at https://www.sourcefabric.org/superdesk/license

import json

from unittest.mock import MagicMock
from datetime import timedelta

from eve.versioning import resolve_document_version
from eve.utils import ParsedRequest

from apps.archive.common import insert_into_versions, ARCHIVE
from superdesk import get_resource_service
from superdesk.tests import TestCase
from superdesk.utc import utcnow
from apps.legal_archive.commands import LegalArchiveImport


class LegalArchiveTestCase(TestCase):
    desks = [{"_id": "123", "name": "Sports"}]
    users = [{"_id": "123", "username": "test1", "first_name": "test", "last_name": "user", "email": "a@a.com"}]
    stages = [{"_id": "123", "name": "working stage", "desk": "123"}]
    archive = [
        {"task": {"desk": "123", "stage": "123"}},
        {"task": {"desk": "1234", "stage": None, "user": "123"}},
        {"task": {"desk": "1234", "stage": "dddd", "user": "test"}},
    ]

    def setUp(self):
        self.app.data.insert("desks", self.desks)
        self.app.data.insert("users", self.users)
        self.app.data.insert("stages", self.stages)

    def test_denormalize_desk_user(self):
        LegalArchiveImport()._denormalize_user_desk(self.archive[0], "")
        task = self.archive[0]["task"]
        self.assertEqual(task.get("desk"), "Sports")
        self.assertEqual(task.get("stage"), "working stage")
        self.assertEqual(task.get("user"), "")

    def test_denormalize_not_configured_desk(self):
        LegalArchiveImport()._denormalize_user_desk(self.archive[1], "")
        task = self.archive[1]["task"]
        self.assertEqual(task.get("desk"), "1234")
        self.assertEqual(task.get("stage"), None)
        self.assertEqual(task.get("user"), "test user")

    def test_denormalize_not_configured_desk_stage_user(self):
        LegalArchiveImport()._denormalize_user_desk(self.archive[2], "")
        task = self.archive[2]["task"]
        self.assertEqual(task.get("desk"), "1234")
        self.assertEqual(task.get("stage"), "dddd")
        self.assertEqual(task.get("user"), "")


class ImportLegalArchiveCommandTestCase(TestCase):
    desks = [{"name": "Sports"}]
    users = [{"username": "test1", "first_name": "test", "last_name": "user", "email": "a@a.com"}]

    def setUp(self):
        try:
            from apps.legal_archive.commands import ImportLegalArchiveCommand
        except ImportError:
            self.fail("Could not import class under test (ImportLegalArchiveCommand).")
        else:
            self.class_under_test = ImportLegalArchiveCommand
            self.app.data.insert("desks", self.desks)
            self.app.data.insert("users", self.users)
            self.validators = [
                {"schema": {}, "type": "text", "act": "publish", "_id": "publish_text"},
                {"schema": {}, "type": "text", "act": "correct", "_id": "correct_text"},
                {"schema": {}, "type": "text", "act": "kill", "_id": "kill_text"},
            ]

            self.products = [
                {"_id": "1", "name": "prod1"},
                {"_id": "2", "name": "prod2", "codes": "abc,def"},
                {"_id": "3", "name": "prod3", "codes": "xyz"},
            ]

            self.subscribers = [
                {
                    "name": "Test",
                    "is_active": True,
                    "subscriber_type": "wire",
                    "email": "test@test.com",
                    "sequence_num_settings": {"max": 9999, "min": 1},
                    "products": ["1"],
                    "destinations": [
                        {
                            "name": "test",
                            "delivery_type": "email",
                            "format": "nitf",
                            "config": {"recipients": "test@test.com"},
                        }
                    ],
                }
            ]
            self.app.data.insert("validators", self.validators)
            self.app.data.insert("products", self.products)
            self.app.data.insert("subscribers", self.subscribers)
            self.class_under_test = ImportLegalArchiveCommand
            self.archive_items = [
                {
                    "task": {"desk": self.desks[0]["_id"], "stage": self.desks[0]["incoming_stage"], "user": "123"},
                    "_id": "item1",
                    "state": "in_progress",
                    "headline": "item 1",
                    "type": "text",
                    "slugline": "item 1 slugline",
                    "_current_version": 1,
                    "_created": utcnow() - timedelta(minutes=3),
                    "expired": utcnow() - timedelta(minutes=30),
                },
                {
                    "task": {"desk": self.desks[0]["_id"], "stage": self.desks[0]["incoming_stage"], "user": "123"},
                    "_id": "item2",
                    "state": "in_progress",
                    "headline": "item 2",
                    "type": "text",
                    "slugline": "item 2 slugline",
                    "_current_version": 1,
                    "_created": utcnow() - timedelta(minutes=2),
                    "expired": utcnow() - timedelta(minutes=30),
                },
                {
                    "task": {"desk": self.desks[0]["_id"], "stage": self.desks[0]["incoming_stage"], "user": "123"},
                    "_id": "item3",
                    "state": "in_progress",
                    "headline": "item 2",
                    "type": "text",
                    "slugline": "item 2 slugline",
                    "_current_version": 1,
                    "_created": utcnow() - timedelta(minutes=1),
                    "expired": utcnow() - timedelta(minutes=30),
                },
            ]

            get_resource_service(ARCHIVE).post(self.archive_items)
            for item in self.archive_items:
                resolve_document_version(item, ARCHIVE, "POST")
                insert_into_versions(id_=item["_id"])

    def test_import_into_legal_archive(self):
        archive_publish = get_resource_service("archive_publish")
        archive_correct = get_resource_service("archive_correct")
        legal_archive = get_resource_service("legal_archive")
        archive = get_resource_service("archive_publish")
        published = get_resource_service("published")
        publish_queue = get_resource_service("publish_queue")

        self.original_method = LegalArchiveImport.upsert_into_legal_archive
        LegalArchiveImport.upsert_into_legal_archive = MagicMock()

        for item in self.archive_items:
            archive_publish.patch(
                item["_id"],
                {
                    "headline": "publishing",
                    "abstract": "publishing",
                    "subject": [
                        {"name": "test", "qcode": "test"},
                    ],
                },
            )

        for item in self.archive_items:
            legal_item = legal_archive.find_one(req=None, _id=item["_id"])
            self.assertIsNone(legal_item, "Item: {} is not none.".format(item["_id"]))

        archive_correct.patch(self.archive_items[1]["_id"], {"headline": "correcting", "abstract": "correcting"})

        LegalArchiveImport.upsert_into_legal_archive = self.original_method
        self.class_under_test().run(1)

        # items are not expired
        for item in self.archive_items:
            legal_item = legal_archive.find_one(req=None, _id=item["_id"])
            self.assertIsNone(legal_item, "Item: {} is not none.".format(item["_id"]))

        # expire the items
        for item in self.archive_items:
            original = archive.find_one(req=None, _id=item["_id"])
            archive.system_update(item["_id"], {"expiry": utcnow() - timedelta(minutes=30)}, original)
            published.update_published_items(item["_id"], "expiry", utcnow() - timedelta(minutes=30))

        # run the command after expiry
        self.class_under_test().run(1)

        # items are expired
        for item in self.archive_items:
            legal_item = legal_archive.find_one(req=None, _id=item["_id"])
            self.assertEqual(legal_item["_id"], item["_id"], "item {} not imported to legal".format(item["_id"]))

        # items are moved to legal
        for item in self.archive_items:
            published_items = list(published.get_other_published_items(item["_id"]))
            for published_item in published_items:
                self.assertEqual(published_item["moved_to_legal"], True)

        # items are moved to legal publish queue
        for item in self.archive_items:
            req = ParsedRequest()
            req.where = json.dumps({"item_id": item["_id"]})
            queue_items = list(publish_queue.get(req=req, lookup=None))
            self.assertGreaterEqual(len(queue_items), 1)
            for queue_item in queue_items:
                self.assertEqual(queue_item["moved_to_legal"], True)
