# pylint: skip-file
import pytest
from posts.models import News, Post, Event, FetMeeting
from django.urls import reverse
from django.core.validators import ValidationError
import datetime
from urllib.request import URLError
import random 
import string

def get_random_string(size):
    chars = string.ascii_lowercase+string.ascii_uppercase+string.digits
    return ''.join(random.choice(chars) for _ in range(size))


@pytest.fixture
def mock_createpad(mocker):
    create_pad=mocker.patch('posts.models.createPadifNotExists',autospec=True, return_value="slug")
    return create_pad

@pytest.fixture
def post(db):
    return Post(title="asdf"+get_random_string(20), post_type="N")

@pytest.fixture
def post_saved(post, mock_createpad):
    post.save()
    return post

@pytest.fixture
def fetmeeting(db):
    return FetMeeting(event_start = datetime.datetime(2020,1,1,18,0))

@pytest.fixture
def fetmeeting_saved(fetmeeting):
    fetmeeting.save()
    return fetmeeting

def test_true():
    assert True


class TestPostModel:
    def test_model(self, post):
        assert isinstance(post,Post)

    def test_model_id(self, post_saved):
        assert post_saved.id==1

    def test_model_notnews(self, post):
        assert not isinstance(post, News)

    def test_post_slug_default(self, post_saved):
        assert "asdf" in post_saved.slug

    def test_url_attribute(self, post_saved):
        assert reverse("posts.show", kwargs={"id": post_saved.slug}) == post_saved.url

    def test_default_hidden(self, post_saved):
        assert post_saved.is_hidden==False

    def test_default_pinned(self, post_saved):
        assert post_saved.is_pinned==False

    def test_validate_title(self, post):
        post.title=""
        with pytest.raises(ValidationError):
            post.full_clean()

    def test_validate_eventdate(self, post):
        post.post_type="E"
        post.event_start=datetime.datetime(2020,10,1,18,0)
        post.event_end=datetime.datetime(2020,10,1,19,0)
        post.full_clean()
        assert True


    def test_validate_dates(self,post):
        post.post_type="E"
        post.event_start=datetime.datetime(2020,10,1,19,0)
        post.event_end=datetime.datetime(2020,10,1,18,0)
        with pytest.raises(ValidationError):
            post.full_clean()

    def test_validate_date2(self,post):
        post.post_type="N"
        post.event_start=datetime.datetime(2020,10,1,18,0)
        post.event_end=datetime.datetime(2020,10,1,19,0)
        with pytest.raises(ValidationError):
            post.full_clean()

    def test_clean_post(self, post):
        post.full_clean()
        assert True



class TestPostEtherpad:
    def setUp(self):
        print("running setup")
        
    def test_agenda_id(self,post_saved, mock_createpad):
        mock_createpad.return_value=post_saved.slug+"-agenda"
        k=post_saved.get_agenda_key()
        mock_createpad.assert_called_with(post_saved.slug+"-agenda")
        assert post_saved.slug in str(k)

    def test_protocol_id(self,post_saved,mock_createpad):
        mock_createpad.return_value=post_saved.slug+"-protocol"
        k=post_saved.get_protocol_key()
        mock_createpad.assert_called_with(post_saved.slug+"-protocol")
        assert post_saved.slug in str(k)

    def test_catch_url_error(self,post_saved,mock_createpad):
        def raise_url_error(key):
            raise URLError("Mocked Etherpad Down")
        mock_createpad.side_effect=raise_url_error
        k=post_saved.get_protocol_key()
        mock_createpad.assert_called()
        assert k == None

class TestFetmeetingModel:
    def test_clean_fetmeeting(self, fetmeeting, mock_createpad):
        fetmeeting.full_clean()
        fetmeeting.save()
        assert True
    
    def test_clean_fetmeeting(self, fetmeeting):
        fetmeeting.event_start=None
        with pytest.raises(ValidationError):
            fetmeeting.clean()

    def test_clean_fetmeeting(self, fetmeeting):
        fetmeeting.event_start=None
        with pytest.raises(ValidationError):
            fetmeeting.clean()
                    
    #Test Defaults for Fetmeeting
    def test_title(self, fetmeeting):
        fetmeeting.save()
        assert fetmeeting.title=="Fachschaftssitzung"

    def test_slug(self, fetmeeting_saved):
        assert "fachschaftssitzung" in fetmeeting_saved.slug

    def test_slug_fachschaftsitzung(self,fetmeeting_saved):
        assert "2020-01-01" in fetmeeting_saved.slug

    def test_sitzung_end(self, fetmeeting_saved):
        assert datetime.datetime(2020,1,1,20,0)==fetmeeting_saved.event_end    

    def test_sitzung_start(self, fetmeeting_saved):
        assert datetime.datetime(2020,1,1,18,0)==fetmeeting_saved.event_start

    def test_post_type(self, fetmeeting_saved):
        assert fetmeeting_saved.post_type == "F"

    def test_meeting_hasagenda(self, fetmeeting_saved):
        assert fetmeeting_saved.has_agenda == True

    def test_meeting_hasprotocol(self, fetmeeting_saved):
        assert fetmeeting_saved.has_protocol == True

class TestPostViews:
    def test_home(self,post_saved,client,db):
        res=client.get("/").content
        assert post_saved.title  in str(res)