from datetime import timedelta
from unittest import mock

from django.contrib.auth import get_user_model
from django.core import mail
from django.test import TestCase
from django.utils import timezone

from bda.models import (
    Attribution,
    Participant,
    Salle,
    Spectacle,
    SpectacleRevente,
    Tirage,
)

User = get_user_model()


class SpectacleReventeTests(TestCase):
    def setUp(self):
        now = timezone.now()

        self.t = Tirage.objects.create(
            title="Tirage",
            ouverture=now - timedelta(days=7),
            fermeture=now - timedelta(days=3),
            active=True,
        )
        self.s = Spectacle.objects.create(
            title="Spectacle",
            date=now + timedelta(days=20),
            location=Salle.objects.create(name="Salle", address="Address"),
            price=10.5,
            slots=5,
            tirage=self.t,
            listing=False,
        )

        self.seller = Participant.objects.create(
            user=User.objects.create(username="seller", email="seller@mail.net"),
            tirage=self.t,
        )
        self.p1 = Participant.objects.create(
            user=User.objects.create(username="part1", email="part1@mail.net"),
            tirage=self.t,
        )
        self.p2 = Participant.objects.create(
            user=User.objects.create(username="part2", email="part2@mail.net"),
            tirage=self.t,
        )
        self.p3 = Participant.objects.create(
            user=User.objects.create(username="part3", email="part3@mail.net"),
            tirage=self.t,
        )

        self.attr = Attribution.objects.create(
            participant=self.seller, spectacle=self.s
        )

        self.rev = SpectacleRevente.objects.create(
            attribution=self.attr, seller=self.seller
        )

    def test_tirage(self):
        revente = self.rev

        wanted_by = [self.p1, self.p2, self.p3]
        revente.confirmed_entry.set(wanted_by)

        with mock.patch("bda.models.random.choice") as mc:
            # Set winner to self.p1.
            mc.return_value = self.p1

            revente.tirage()

            # Call to random.choice used participants in wanted_by.
            mc_args, _ = mc.call_args

            self.assertEqual(set(mc_args[0]), set(wanted_by))

        self.assertEqual(revente.soldTo, self.p1)
        self.assertTrue(revente.tirage_done)

        mails = {m.to[0]: m for m in mail.outbox}

        self.assertEqual(len(mails), 4)

        m_seller = mails["seller@mail.net"]
        self.assertListEqual(m_seller.to, ["seller@mail.net"])
        self.assertListEqual(m_seller.reply_to, ["part1@mail.net"])

        m_winner = mails["part1@mail.net"]
        self.assertListEqual(m_winner.to, ["part1@mail.net"])

        self.assertCountEqual(
            [mails["part2@mail.net"].to, mails["part3@mail.net"].to],
            [["part2@mail.net"], ["part3@mail.net"]],
        )
