from .statements import *

viewstotest = [
    ('workout_view',
        {
        'anonymous': True,
        'anonymous_response':200,
        'own': 'basic',
        'own_response': 200,
        'own_nonperm': 302,
        'member': 'basic',
        'member_response': 200,
        'member_nonperm': 404,
        'coachee': 'coach',
        'coachee_response': 200,
        'coachee_nonperm': 404,
        'is_staff': False,
        'workoutid': True,
        'userid': False,
        'dotest': True,
        }
        ),
]

import pandas as pd
df = pd.read_csv('./rowers/tests/viewnames.csv')

for id, row in df.iterrows():
    view = row['view']
    tpl = (view,
           {
           'anonymous':row.anonymous,
           'anonymous_response':row.anonymous_response,
           'own': row.own,
           'own_response':row.own_response,
           'own_nonperm': row.own_nonperm,
           'member': row.member,
           'member_response':row.member_response,
           'member_nonperm': row.member_nonperm,
           'coachee': row.coachee,
           'coachee_response':row.coachee_response,
           'coachee_nonperm': row.coachee_nonperm,
           'is_staff':row.is_staff,
           'workoutid':row.workoutid,
           'userid':row.userid,
           'dotest':row.dotest,
           })
    if row.dotest:
        viewstotest.append(tpl)


plans = ['basic','plan','coach','pro']

@override_settings(TESTING=True)
class PermissionsViewTests(TestCase):
    def setUp(self):
        self.c = Client()
        ## Users - Pro, Basic, Coach & Self Coach

        ucoach = UserFactory(username='coachuser')
        rcoach = Rower.objects.create(user=ucoach,
                                      birthdate=faker.profile()['birthdate'],
                                      gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
                                           rowerplan='coach',clubsize=10)

        ucoach_workouts = WorkoutFactory.create_batch(5, user=rcoach)
        coachinggroup = CoachingGroup.objects.create()
        rcoach.mycoachgroup = coachinggroup
        rcoach.save()

        ucoachpassword = faker.word()
        ucoach.set_password(ucoachpassword)
        ucoach.save()

        self.ucoach = {
            'user': ucoach,
            'password': ucoachpassword,
            'username': ucoach.username,
            'workouts': ucoach_workouts,
        }

        uplan = UserFactory(username='planuser')
        rplan = Rower.objects.create(user=uplan,
                                      birthdate=faker.profile()['birthdate'],
                                      gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
                                           rowerplan='plan',clubsize=10)

        uplan_workouts = WorkoutFactory.create_batch(5, user=rplan)
        rcoach.save()

        uplanpassword = faker.word()
        uplan.set_password(uplanpassword)
        uplan.save()

        self.uplan = {
            'user': uplan,
            'password': uplanpassword,
            'username': uplan.username,
            'workouts': uplan_workouts,
        }

        uplan2 = UserFactory(username='plan2user')
        rplan2 = Rower.objects.create(user=uplan2,
                                      birthdate=faker.profile()['birthdate'],
                                      gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
                                           rowerplan='plan',clubsize=10)

        uplan2_workouts = WorkoutFactory.create_batch(5, user=rplan2)
        rcoach.save()

        uplan2password = faker.word()
        uplan2.set_password(uplan2password)
        uplan2.save()

        self.uplan2 = {
            'user': uplan2,
            'password': uplan2password,
            'username': uplan2.username,
            'workouts': uplan2_workouts,
        }

        upro = UserFactory(username='prouser')
        rpro = Rower.objects.create(user=upro,
                                      birthdate=faker.profile()['birthdate'],
                                      gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
                                           rowerplan='pro',clubsize=10)

        upro_workouts = WorkoutFactory.create_batch(5, user=rpro)
        rcoach.save()

        upropassword = faker.word()
        upro.set_password(upropassword)
        upro.save()

        self.upro = {
            'user': upro,
            'password': upropassword,
            'username': upro.username,
            'workouts': upro_workouts,
        }

        ubasic = UserFactory(username='basicuser')
        rbasic = Rower.objects.create(user=ubasic,
                                      birthdate=faker.profile()['birthdate'],
                                      gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
                                           rowerplan='basic',clubsize=10)

        ubasic_workouts = WorkoutFactory.create_batch(5, user=rbasic)
        rcoach.save()

        ubasicpassword = faker.word()
        ubasic.set_password(ubasicpassword)
        ubasic.save()

        self.ubasic = {
            'user': ubasic,
            'password': ubasicpassword,
            'username': ubasic.username,
            'workouts': ubasic_workouts,
        }

        ustrange = UserFactory(username='strangeuser')
        rstrange = Rower.objects.create(user=ustrange,
                                      birthdate=faker.profile()['birthdate'],
                                      gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
                                           rowerplan='basic',clubsize=10)

        ustrange_workouts = WorkoutFactory.create_batch(5, user=rstrange)
        rcoach.save()

        ustrangepassword = faker.word()
        ustrange.set_password(ustrangepassword)
        ustrange.save()

        self.ustrange = {
            'user': ustrange,
            'password': ustrangepassword,
            'username': ustrange.username,
            'workouts': ustrange_workouts,
        }


        ## TeamPro, TeamCoach, TeamSelfCoach

        self.teampro = Team.objects.create(
            name=faker.word(),
            notes=faker.text(),
            manager=self.upro['user'])

        self.teamplan = Team.objects.create(
            name=faker.word()+'2',
            notes=faker.text(),
            manager=self.uplan2['user'])

        self.teamcoach = Team.objects.create(
            name=faker.word()+'3',
            notes=faker.text(),
            manager=self.ucoach['user'])

        self.uplan['user'].rower.team.add(self.teamcoach)
        self.ubasic['user'].rower.team.add(self.teamcoach)
        self.ucoach['user'].rower.team.add(self.teamcoach)
        self.upro['user'].rower.team.add(self.teamcoach)

        self.upro['user'].rower.team.add(self.teamplan)
        self.uplan2['user'].rower.team.add(self.teamplan)

        self.upro['user'].rower.team.add(self.teampro)
        self.uplan['user'].rower.team.add(self.teampro)

        self.uplan['user'].rower.coachinggroups.add(coachinggroup)
        self.ubasic['user'].rower.coachinggroups.add(coachinggroup)


    # Test access for anonymous users
    @parameterized.expand(viewstotest)
    @patch('rowers.c2stuff.Session', side_effect=mocked_requests)
    @patch('rowers.c2stuff.c2_open')
    @patch('rowers.dataprep.create_engine')
    @patch('rowers.dataprep.read_df_sql')
    @patch('rowers.dataprep.getsmallrowdata_db')
    @patch('requests.get',side_effect=mocked_requests)
    @patch('requests.post',side_effect=mocked_requests)
    @patch('rowers.dataprep.get_video_data',side_effect=mocked_get_video_data)
    def test_permissions_anonymous(
        self,view,permissions,
        mock_Session,
        mock_c2open,
        mocked_sqlalchemy,
        mocked_read_df_sql,
        mocked_getsmallrowdata_db,
        mock_get,
        mock_post,
        mocked_get_video_data,
        ):

        print()
        print(view,'anonymous',permissions['anonymous'],permissions['is_staff'],permissions['dotest'])
        print()

        if permissions['anonymous'] and not permissions['is_staff'] and permissions['dotest']:
            urlstotest = []
            if permissions['workoutid']:
                url = reverse(view,kwargs={'id':encoder.encode_hex(self.ucoach['workouts'][0].id)})
                urlstotest.append(url)
            else:
                url = reverse(view)
                urlstotest.append(url)

            print(view,'anonymous',urlstotest)

            for url in urlstotest:
                result = self.c.get(url)
                self.assertEqual(result.status_code,permissions['anonymous_response'])

    # Test access for logged in  users - accessing own objects
    @parameterized.expand(viewstotest)
    @patch('rowers.c2stuff.Session', side_effect=mocked_requests)
    @patch('rowers.c2stuff.c2_open')
    @patch('rowers.dataprep.create_engine')
    @patch('rowers.dataprep.read_df_sql')
    @patch('rowers.dataprep.getsmallrowdata_db')
    @patch('requests.get',side_effect=mocked_requests)
    @patch('requests.post',side_effect=mocked_requests)
    @patch('rowers.dataprep.get_video_data',side_effect=mocked_get_video_data)
    def test_permissions_own(
        self,view,permissions,
        mock_Session,
        mock_c2open,
        mocked_sqlalchemy,
        mocked_read_df_sql,
        mocked_getsmallrowdata_db,
        mock_get,
        mock_post,
        mocked_get_video_data,
        ):

        print()
        print(view,'own')
        print()

        if permissions['own'] in plans and not permissions['is_staff'] and permissions['dotest']:
            urlstotest = []
            falseurlstotest = []
            otheruserurls = []

            thisuser = self.ubasic
            memberuser = self.uplan
            notuser = None

            print(view,'own')

            if permissions['own'] == 'basic':
                thisuser = self.ubasic
                memberuser = self.uplan
                notuser = None
            elif permissions['own'] == 'pro':
                thisuser = self.upro
                notuser = self.ubasic
            elif permissions['own'] == 'plan':
                thisuser = self.uplan
                notuser = self.upro
            elif permissions['own'] == 'coach':
                thisuser = self.ucoach
                notuser = self.uplan


            if permissions['workoutid']:
                workouts = thisuser['workouts']
                url = reverse(view,kwargs={'id':encoder.encode_hex(workouts[0].id)})
                urlstotest.append(url)
                if notuser:
                    workouts = notuser['workouts']
                    url = reverse(view,kwargs={'id':encoder.encode_hex(workouts[0].id)})
                    falseurlstotest.append(url)
            elif permissions['userid']:
                url = reverse(view,kwargs={'userid':thisuser['user'].id})
                urlstotest.append(url)

                url = reverse(view,kwargs={'userid':self.ustrange['user'].id})
                otheruserurls.append(url)
            else:
                url = reverse(view)
                urlstotest.append(url)

            print(view,'own',urlstotest,falseurlstotest,otheruserurls)

            # test logged in as user who has permissions
            for url in urlstotest:
                login = self.c.login(username = thisuser['username'],password = thisuser['password'])
                result = self.c.get(url)
                self.assertEqual(result.status_code, permissions['own_response'])

            # test logged as user with no permissions (e.g. too low plan)
            for url in falseurlstotest:
                login = self.c.login(username = notuser['username'],password = notuser['password'])
                result = self.c.get(url)
                self.assertEqual(result.status_code, permissions['own_nonperm'])

            # test as user with permissions, accessing object of non-related user
            for url in otheruserurls:
                login = self.c.login(username=thisuser['username'],password = thisuser['password'])
                result = self.c.get(url)
                self.assertEqual(result.status_code,403)

    # Test access for logged in  users - accessing team member objects
    @parameterized.expand(viewstotest)
    @patch('rowers.c2stuff.Session', side_effect=mocked_requests)
    @patch('rowers.c2stuff.c2_open')
    @patch('rowers.dataprep.create_engine')
    @patch('rowers.dataprep.read_df_sql')
    @patch('rowers.dataprep.getsmallrowdata_db')
    @patch('requests.get',side_effect=mocked_requests)
    @patch('requests.post',side_effect=mocked_requests)
    @patch('rowers.dataprep.get_video_data',side_effect=mocked_get_video_data)
    def test_permissions_member(
        self,view,permissions,
        mock_Session,
        mock_c2open,
        mocked_sqlalchemy,
        mocked_read_df_sql,
        mocked_getsmallrowdata_db,
        mock_get,
        mock_post,
        mocked_get_video_data,
        ):

        print()
        print(view,'member')
        print()

        if permissions['member'] in plans and permissions['is_staff'] is False and permissions['dotest']:
            urlstotest = []
            falseurlstotest = []
            otheruserurls = []

            thisuser = self.ubasic
            memberuser = self.uplan
            notuser = None

            print(view,'member')

            if permissions['member'] == 'basic':
                thisuser = self.ubasic
                memberuser = self.uplan
                notuser = None
            elif permissions['member'] == 'pro':
                thisuser = self.upro
                memberuser = self.uplan
                notuser = self.ubasic
            elif permissions['member'] == 'plan':
                thisuser = self.uplan
                memberuser = self.ubasic
                notuser = self.upro
            elif permissions['member'] == 'coach':
                thisuser = self.ucoach
                memberuser = self.uplan
                notuser = self.uplan


            if permissions['workoutid']:
                workouts = memberuser['workouts']
                url = reverse(view,kwargs={'id':encoder.encode_hex(workouts[0].id)})
                urlstotest.append(url)
                if notuser:
                    falseurlstotest.append(url)
            elif permissions['userid']:
                url = reverse(view,kwargs={'userid':memberuser['user'].id})
                urlstotest.append(url)

                url = reverse(view,kwargs={'userid':self.ustrange['user'].id})
                otheruserurls.append(url)
            else:
                url = reverse(view)
                urlstotest.append(url)

            print('member',urlstotest,falseurlstotest,otheruserurls)

            # test logged in as user who has permissions
            for url in urlstotest:
                login = self.c.login(username = thisuser['username'],password = thisuser['password'])
                result = self.c.get(url)
                self.assertEqual(result.status_code, permissions['member_response'])

            # test logged as user with no permissions (e.g. too low plan)
            for url in falseurlstotest:
                login = self.c.login(username = notuser['username'],password = notuser['password'])
                result = self.c.get(url)
                self.assertEqual(result.status_code, permissions['member_nonperm'])

            # test as user with permissions, accessing object of non-related user
            for url in otheruserurls:
                login = self.c.login(username=thisuser['username'],password = thisuser['password'])
                result = self.c.get(url)
                self.assertEqual(result.status_code,403)

    # Test access for logged in  users - accessing coachee
    @parameterized.expand(viewstotest)
    @patch('rowers.c2stuff.Session', side_effect=mocked_requests)
    @patch('rowers.c2stuff.c2_open')
    @patch('rowers.dataprep.create_engine')
    @patch('rowers.dataprep.read_df_sql')
    @patch('rowers.dataprep.getsmallrowdata_db')
    @patch('requests.get',side_effect=mocked_requests)
    @patch('requests.post',side_effect=mocked_requests)
    @patch('rowers.dataprep.get_video_data',side_effect=mocked_get_video_data)
    def test_permissions_coachee(
        self,view,permissions,
        mock_Session,
        mock_c2open,
        mocked_sqlalchemy,
        mocked_read_df_sql,
        mocked_getsmallrowdata_db,
        mock_get,
        mock_post,
        mocked_get_video_data,
        ):

        print()
        print(view,'coachee')
        print()

        if permissions['coachee'] in plans and not permissions['is_staff'] and permissions['dotest']:
            urlstotest = []
            falseurlstotest = []
            otheruserurls = []

            thisuser = self.ucoach
            coacheeuser = self.ubasic
            notuser = self.uplan



            if permissions['workoutid']:
                workouts = coacheeuser['workouts']
                url = reverse(view,kwargs={'id':encoder.encode_hex(workouts[0].id)})
                urlstotest.append(url)

            elif permissions['userid']:
                url = reverse(view,kwargs={'userid':coacheeuser['user'].id})
                urlstotest.append(url)

                url = reverse(view,kwargs={'userid':self.ustrange['user'].id})
                otheruserurls.append(url)
            else:
                url = reverse(view)
                urlstotest.append(url)

            print('coachee',urlstotest,falseurlstotest,otheruserurls)

            # test logged in as user who has permissions
            for url in urlstotest:
                login = self.c.login(username = thisuser['username'],password = thisuser['password'])
                result = self.c.get(url)
                self.assertEqual(result.status_code, permissions['coachee_response'])

            # test as user with permissions, accessing object of non-related user
            for url in otheruserurls:
                login = self.c.login(username=thisuser['username'],password = thisuser['password'])
                result = self.c.get(url)
                self.assertEqual(result.status_code,403)
