# -*- coding: utf-8 -*-
import unittest
from io import BytesIO
from unittest import mock

import django.core.mail as email
from django.core.files import File
from django.test import TestCase, override_settings

from oscar.core.loading import get_model

import ocyan.core.fender
from ocyan.plugin.oscar.pipeline import PIPELINE_STATUS_PAID

from ocyan.plugin.oscar_communications.order_extension.processing import EventHandler

Order = get_model("order", "Order")

BCC_EMAIL = {
    "django": {"email_to": "henk@nub.lol"},
    "oscar_communications": {
        "invoice": True,
        "send_shipping_email": True,
        "tracking_url_template": "http://posnl.nl/{{ code }}?activate_my_dick",
    },
}

invoice_creator_instance = mock.MagicMock()
attrs = {
    "name": "klaas.pdf",
    "document": File(BytesIO(b""), name="klaas.pdf"),
    "get_or_create_invoice.return_value": invoice_creator_instance,
}
invoice_creator_instance.configure_mock(**attrs)
InvoiceCreator = mock.MagicMock(return_value=invoice_creator_instance)


@override_settings(DEFAULT_TO_EMAIL=["henk@nub.lol"])
@mock.patch.object(ocyan.core.fender.config, "settings", BCC_EMAIL)
@mock.patch(
    "ocyan.plugin.oscar_communications.order_extension.spooler.InvoiceCreator",
    InvoiceCreator,
    create=True,
)
class CommunicationsTest(TestCase):
    fixtures = [
        "communications/auth",
        "communications/address",
        "communications/catalogue",
        "communications/order",
        "communications/basket",
        "communications/customer",
    ]

    def setUp(self):
        self.evt_handler = EventHandler()
        setattr(email, "outbox", [])

    def test_invoice_registered_user(self):
        with self.settings(
            EMAIL_BACKEND="django.core.mail.backends.locmem.EmailBackend"
        ):
            registered_order = Order.objects.get(pk=1)
            self.assertEqual(len(email.outbox), 0)
            self.evt_handler.handle_order_status_change(
                registered_order, PIPELINE_STATUS_PAID, note_msg="Test test"
            )
            self.assertEqual(len(email.outbox), 1)
            mail = email.outbox[0]
            self.assertEqual(mail.to, ["admin@admin.admin"])
            self.assertEqual(mail.attachments, [("klaas.pdf", b"", "application/pdf")])
            self.assertEqual(
                mail.recipients(),
                ["admin@admin.admin", "henk@nub.lol"],
                "The order mail should be sent to admin as well as customer",
            )
            self.assertEqual(
                mail.subject,
                "Klaas Berten admin@admin.admin example.com 2",
                "The subject should contain all the promoted variables",
            )
            self.assertTrue(
                mail.body.strip().startswith("Beste Klaas Berten,"),
                "The user should be greeted with his user.get_full_name",
            )
            self.assertTrue(
                mail.body.strip().endswith("Het example.com team"),
                "The message should conclude properly",
            )

            self.assertIn("Hallo Klaas Berten", str(mail.alternatives))
            self.assertIn("Zoekeenhuisstraat 3", str(mail.alternatives))
            self.assertIn("Het example.com team", str(mail.alternatives))

    def test_invoice_registered_user_with_billing_address(self):
        with self.settings(
            EMAIL_BACKEND="django.core.mail.backends.locmem.EmailBackend"
        ):
            registered_order = Order.objects.get(pk=3)
            self.assertEqual(len(email.outbox), 0)
            self.evt_handler.handle_order_status_change(
                registered_order, PIPELINE_STATUS_PAID, note_msg="Test test"
            )
            self.assertEqual(len(email.outbox), 2)
            billing_mail = email.outbox[0]
            mail = email.outbox[1]
            self.assertEqual(billing_mail.to, ["viggo@mandelblog.com"])
            self.assertEqual(mail.to, ["admin@admin.admin"])
            self.assertEqual(
                billing_mail.attachments, [("klaas.pdf", b"", "application/pdf")]
            )
            self.assertEqual(mail.attachments, [])
            self.assertEqual(
                mail.recipients(),
                ["admin@admin.admin", "henk@nub.lol"],
                "The order mail should be sent to admin as well as customer",
            )
            self.assertEqual(
                mail.subject,
                "Klaas Berten admin@admin.admin example.com 6",
                "The subject should contain all the promoted variables",
            )
            self.assertTrue(
                mail.body.strip().startswith("Beste Klaas Berten,"),
                "The user should be greeted with his user.get_full_name",
            )
            self.assertTrue(
                mail.body.strip().endswith("Het example.com team"),
                "The message should conclude properly",
            )

            self.assertIn("Hallo Klaas Berten", str(mail.alternatives))
            self.assertIn("Zoekeenhuisstraat 3", str(mail.alternatives))
            self.assertIn("Het example.com team", str(mail.alternatives))

    def test_invoice_registered_user_with_billing_address_same_email(self):
        with self.settings(
            EMAIL_BACKEND="django.core.mail.backends.locmem.EmailBackend"
        ):
            registered_order = Order.objects.get(pk=4)
            self.assertEqual(len(email.outbox), 0)
            self.evt_handler.handle_order_status_change(
                registered_order, PIPELINE_STATUS_PAID, note_msg="Test test"
            )
            self.assertEqual(len(email.outbox), 1)
            mail = email.outbox[0]
            self.assertEqual(mail.to, ["admin@admin.admin"])
            self.assertEqual(mail.attachments, [("klaas.pdf", b"", "application/pdf")])
            self.assertEqual(
                mail.recipients(),
                ["admin@admin.admin", "henk@nub.lol"],
                "The order mail should be sent to admin as well as customer",
            )
            self.assertEqual(
                mail.subject,
                "Klaas Berten admin@admin.admin shop2 8",
                "The subject should contain all the promoted variables",
            )
            self.assertTrue(
                mail.body.strip().startswith("Beste Klaas Berten,"),
                "The user should be greeted with his user.get_full_name",
            )
            self.assertTrue(
                mail.body.strip().endswith("Het shop2 team"),
                "The message should conclude properly",
            )

            self.assertIn("Hallo Klaas Berten", str(mail.alternatives))
            self.assertIn("Zoekeenhuisstraat 3", str(mail.alternatives))
            self.assertIn("Het shop2 team", str(mail.alternatives))

    def test_invoice_anonymous_user(self):
        with self.settings(
            EMAIL_BACKEND="django.core.mail.backends.locmem.EmailBackend"
        ):
            registered_order = Order.objects.get(pk=2)
            self.assertEqual(len(email.outbox), 0)
            self.evt_handler.handle_order_status_change(
                registered_order, PIPELINE_STATUS_PAID, note_msg="Test test"
            )
            self.assertEqual(len(email.outbox), 1)
            mail = email.outbox[0]
            self.assertEqual(mail.to, ["piet@example.com"])
            self.assertEqual(mail.attachments, [("klaas.pdf", b"", "application/pdf")])
            self.assertEqual(
                mail.recipients(),
                ["piet@example.com", "henk@nub.lol"],
                "The order mail should be sent to admin as well as customer",
            )
            self.assertEqual(
                mail.subject,
                "Piet Henken piet@example.com example.com 3",
                "The subject should contain all the promoted variables",
            )
            self.assertTrue(
                mail.body.strip().startswith("Beste Piet Henken,"),
                "The user should be greeted with his user.get_full_name",
            )
            self.assertTrue(
                mail.body.strip().endswith("Het example.com team"),
                "The message should conclude properly",
            )

            self.assertIn("Hallo Piet Henken", str(mail.alternatives))
            self.assertIn("zultieboi", str(mail.alternatives))
            self.assertIn("Het example.com team", str(mail.alternatives))

    @unittest.skip("geen zin meer in")
    def test_shipping_registered_user(self):
        self.test_invoice_registered_user()

    @unittest.skip("geen zin meer in")
    def test_shipping_anonymous_user(self):
        self.test_invoice_anonymous_user()


class CommunicationEventTest(TestCase):
    fixtures = [
        "communications/auth",
        "communications/address",
        "communications/catalogue",
        "communications/order",
        "communications/basket",
        "communications/customer",
        "communications/allreadysent",
    ]

    def setUp(self):
        self.evt_handler = EventHandler()
        setattr(email, "outbox", [])

    def test_idempotent_communication_event(self):
        with self.settings(
            EMAIL_BACKEND="django.core.mail.backends.locmem.EmailBackend"
        ):
            registered_order = Order.objects.get(pk=1)
            self.assertEqual(len(email.outbox), 0)
            self.evt_handler.handle_order_status_change(
                registered_order, PIPELINE_STATUS_PAID, note_msg="Test test"
            )
            self.assertEqual(len(email.outbox), 0)
