from unittest import mock

import pytest
from django.core.files.base import ContentFile
from django.core.management import call_command

from petale.management.commands.clean import check_unknown_cuts
from petale.models import CUT, Partner, Petal


@pytest.fixture
def requests_post():
    post_return_value = mock.Mock()
    post_return_value.json.return_value = None
    with mock.patch('requests.post', return_value=post_return_value) as requests_post:
        yield requests_post


def test_check_unknown_cuts(requests_post):

    requests_post.return_value.json.return_value = {'unknown_uuids': ['1']}
    assert check_unknown_cuts(['1'], ('admin', 'admin')) == ['1']
    assert requests_post.call_args[0] == ('http://example.net/idp/api/users/synchronization/',)
    assert requests_post.call_args[1] == {
        'auth': ('admin', 'admin'),
        'json': {'known_uuids': ['1']},
        'timeout': 28,
    }


class TestClean:

    uuids = {str(i) for i in range(10)}
    uuids_no_petal = {str(i) for i in range(10, 12)}
    unknown_uuids = {str(i) for i in range(5)} | uuids_no_petal

    @pytest.fixture
    def other_partner(self, db):
        return Partner.objects.create(name='other')

    @pytest.fixture
    def partner(self, db):
        return Partner.objects.create(name='partner')

    @pytest.fixture
    def cuts(self, partner, other_partner, media):
        for uuid in ['a', 'b', 'c']:
            cut = CUT.objects.create(uuid=uuid)
            petal = Petal.objects.create(name='petal', partner=other_partner, cut=cut, size=0)
            petal.data.save('petal.dat', ContentFile(b'1234'))
        for uuid in self.uuids:
            cut = CUT.objects.create(uuid=uuid)
            petal = Petal.objects.create(name='petal', partner=partner, cut=cut, size=0)
            petal.data.save('petal.dat', ContentFile(b'1234'))
        for uuid in self.uuids_no_petal:
            cut = CUT.objects.create(uuid=uuid)
        assert len(list(media.rglob('petal'))) == 13
        assert len(list(media.glob('*/*/*/*'))) == 13

    @pytest.fixture
    def requests_post(self, requests_post):
        requests_post.return_value.json.return_value = {'unknown_uuids': self.unknown_uuids}
        return requests_post

    def test_dry(self, cuts, partner, requests_post, media):
        call_command('clean', 'partner', '1234', '5678')
        assert set(requests_post.call_args[1]['json']['known_uuids']) == self.uuids
        assert set(CUT.objects.filter(petal__partner=partner).values_list('uuid', flat=True)) == self.uuids
        assert len(list(media.rglob('petal'))) == 13
        assert len(list(media.glob('*/*/*/*'))) == 13

    def test_delete(self, cuts, partner, requests_post, media):
        call_command('clean', '--delete', 'partner', '1234', '5678')
        assert set(requests_post.call_args[1]['json']['known_uuids']) == self.uuids
        assert (
            set(CUT.objects.filter(petal__partner=partner).values_list('uuid', flat=True))
            == self.uuids - self.unknown_uuids
        )
        assert len(list(media.rglob('petal'))) == 8
        assert len(list(media.glob('*/*/*/*'))) == 8

        call_command('clean', '--delete', 'partner', '1234', '5678')
        assert set(requests_post.call_args[1]['json']['known_uuids']) == self.uuids - self.unknown_uuids
        assert len(list(media.rglob('*/partner/*/*/petal'))) == 5
        assert len(list(media.glob('*/partner/*/*'))) == 5
        assert len(list(media.rglob('*/*/*/petal'))) == 8
        assert len(list(media.glob('*/*/*/*/*'))) == 8
