import json
from rest_framework.test import APITestCase
from account.models import User
from rest_framework import status
from http.cookies import SimpleCookie
from main.models import Currency
from establishment.models import Establishment, EstablishmentType, EstablishmentSubType,\
    Menu, SocialChoice, SocialNetwork
# Create your tests here.
from translation.models import Language
from account.models import Role, UserRole
from location.models import Country, Address, City, Region
from pytz import timezone as py_tz
from main.models import SiteSettings
from timetable.models import Timetable


class BaseTestCase(APITestCase):
    def setUp(self):
        self.username = 'sedragurda'
        self.password = 'sedragurdaredips19'
        self.email = 'sedragurda@desoz.com'
        self.newsletter = True
        self.user = User.objects.create_user(
            username=self.username,
            email=self.email,
            password=self.password,
            is_staff=True,
        )
        # get tokens
        tokens = User.create_jwt_tokens(self.user)
        self.client.cookies = SimpleCookie(
            {'access_token': tokens.get('access_token'),
             'refresh_token': tokens.get('refresh_token')})

        self.establishment_type = EstablishmentType.objects.create(
            name="Test establishment type")

        # Create lang object
        self.lang = Language.objects.create(
            title='Russia',
            locale='ru-RU'
        )

        self.country_ru = Country.objects.create(
            name={'en-GB': 'Russian'},
            code='RU',
        )

        self.region = Region.objects.create(name='Moscow area', code='01',
                                            country=self.country_ru)
        self.region.save()

        self.city = City.objects.create(
            name='Mosocow', code='01',
            region=self.region,
            country=self.country_ru)
        self.city.save()

        self.address = Address.objects.create(
            city=self.city, street_name_1='Krasnaya',
            number=2, postal_code='010100')
        self.address.save()

        self.role = Role.objects.create(role=Role.ESTABLISHMENT_MANAGER)
        self.role.save()

        self.establishment = Establishment.objects.create(
            name="Test establishment",
            establishment_type_id=self.establishment_type.id,
            is_publish=True,
            slug="test",
            address=self.address
        )

        self.establishment.save()

        self.user_role = UserRole.objects.create(
            user=self.user, role=self.role,
            establishment=self.establishment)
        self.user_role.save()

        self.social_choice = SocialChoice.objects.create(title='facebook')
        self.social_network = SocialNetwork.objects.create(
            network=self.social_choice,
            url='https://testsocial.de',
            establishment=self.establishment,
        )


class EstablishmentBackTests(BaseTestCase):
    def test_establishment_CRUD(self):
        params = {'page': 1, 'page_size': 1, }
        response = self.client.get('/api/back/establishments/', params, format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        data = {
            'name': 'Test establishment',
            'type_id': self.establishment_type.id,
            'is_publish': True,
            'slug': 'test-establishment-slug',
            'tz': py_tz('Europe/Moscow').zone
        }

        response = self.client.post('/api/back/establishments/', data=data, format='json')
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

        response = self.client.get(f'/api/back/establishments/slug/{self.establishment.slug}/', format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        update_data = {
            'name': 'Test new establishment'
        }

        response = self.client.patch(f'/api/back/establishments/slug/{self.establishment.slug}/',
                                     data=update_data)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        response = self.client.delete(f'/api/back/establishments/slug/{self.establishment.slug}/',
                                      format='json')
        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)


class EmployeeTests(BaseTestCase):
    def test_employee_CRUD(self):
        response = self.client.get('/api/back/establishments/employees/', format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        data = {
            'user': self.user.id,
            'name': 'Test name'
        }

        response = self.client.post('/api/back/establishments/employees/', data=data)
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

        response = self.client.get('/api/back/establishments/employees/1/', format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        update_data = {
            'name': 'Test new name'
        }

        response = self.client.patch('/api/back/establishments/employees/1/', data=update_data)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        response = self.client.delete('/api/back/establishments/employees/1/', format='json')
        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)


class ChildTestCase(BaseTestCase):
    def setUp(self):
        super().setUp()


class EmailTests(ChildTestCase):
    def setUp(self):
        super().setUp()

    def test_get(self):
        response = self.client.get('/api/back/establishments/emails/', format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_post(self):
        data = {
            'email': "test@test.com",
            'establishment': self.establishment.id
        }

        response = self.client.post('/api/back/establishments/emails/', data=data)
        self.id_email = response.json()['id']
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

    def test_get_by_pk(self):
        self.test_post()
        response = self.client.get(f'/api/back/establishments/emails/{self.id_email}/', format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_patch(self):
        self.test_post()

        update_data = {
            'email': 'testnew@test.com'
        }

        response = self.client.patch(f'/api/back/establishments/emails/{self.id_email}/',
                                     data=update_data)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_email_CRUD(self):
        self.test_post()
        response = self.client.delete(f'/api/back/establishments/emails/{self.id_email}/')
        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)


class PhoneTests(ChildTestCase):
    def test_phone_CRUD(self):
        response = self.client.get('/api/back/establishments/phones/', format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        data = {
            'phone': "+79999999999",
            'establishment': self.establishment.id
        }

        response = self.client.post('/api/back/establishments/phones/', data=data)
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

        response = self.client.get('/api/back/establishments/phones/1/', format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        update_data = {
            'phone': '+79999999998'
        }

        response = self.client.patch('/api/back/establishments/phones/1/', data=update_data)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        response = self.client.delete('/api/back/establishments/phones/1/')
        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)


class SocialChoicesTests(ChildTestCase):
    def test_social_choices_CRUD(self):
        response = self.client.get('/api/back/establishments/social_choice/', format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        data = {
            'title': 'twitter',
        }

        response = self.client.post('/api/back/establishments/social_choice/', data=data)
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

        response = self.client.get(f'/api/back/establishments/social_choice/{self.social_choice.id}/', format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        update_data = {
            'title': 'vk'
        }

        response = self.client.patch(f'/api/back/establishments/social_choice/{self.social_choice.id}/',
                                     data=update_data)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        response = self.client.delete(f'/api/back/establishments/social_choice/{self.social_choice.id}/')
        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)


class SocialTests(ChildTestCase):
    def test_social_CRUD(self):
        response = self.client.get('/api/back/establishments/socials/', format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        data = {
            'network': self.social_choice.id,
            'url': 'https://testsocial.com',
            'establishment': self.establishment.id
        }

        response = self.client.post('/api/back/establishments/socials/', data=data)
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

        response = self.client.get(f'/api/back/establishments/socials/{self.social_network.id}/', format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        update_data = {
            'url': 'https://newtestsocial.com'
        }

        response = self.client.patch(f'/api/back/establishments/socials/{self.social_network.id}/', data=update_data)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        response = self.client.delete(f'/api/back/establishments/socials/{self.social_network.id}/')
        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)


class PlateTests(ChildTestCase):
    def test_plate_CRUD(self):
        response = self.client.get('/api/back/establishments/plates/', format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        menu = Menu.objects.create(
            category=json.dumps({"ru-RU": "Test category"}),
            establishment=self.establishment
        )
        currency = Currency.objects.create(name="Test currency")

        data = {
            'name': json.dumps({"ru-RU": "Test plate"}),
            'establishment': self.establishment.id,
            'price': 10,
            'menu': menu.id,
            'currency_id': currency.id
        }

        response = self.client.post('/api/back/establishments/plates/', data=data)
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

        response = self.client.get('/api/back/establishments/plates/1/', format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        update_data = {
            'name': json.dumps({"ru-RU": "Test new plate"})
        }

        response = self.client.patch('/api/back/establishments/plates/1/', data=update_data)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        response = self.client.delete('/api/back/establishments/plates/1/')
        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)


class MenuTests(ChildTestCase):
    def test_menu_CRUD(self):
        response = self.client.get('/api/back/establishments/menus/', format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        data = {
            'category': json.dumps({"ru-RU": "Test category"}),
            'establishment': self.establishment.id
        }

        response = self.client.post('/api/back/establishments/menus/', data=data)
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

        response = self.client.get('/api/back/establishments/menus/1/', format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        update_data = {
            'category': json.dumps({"ru-RU": "Test new category"})
        }

        response = self.client.patch('/api/back/establishments/menus/1/', data=update_data)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        response = self.client.delete('/api/back/establishments/menus/1/')
        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)


class EstablishmentShedulerTests(ChildTestCase):
    def setUp(self):
        super().setUp()

        self.lang, created = Language.objects.get_or_create(
            title='Russia',
            locale='ru-RU'
        )

        self.country_ru, created = Country.objects.get_or_create(
            name={"en-GB": "Russian"}
        )

        self.site_ru, created = SiteSettings.objects.get_or_create(
            subdomain='ru'
        )

        role, created = Role.objects.get_or_create(
            role=Role.ESTABLISHMENT_MANAGER,
            country_id=self.country_ru.id,
            site_id=self.site_ru.id
        )

        user_role, created = UserRole.objects.get_or_create(
            user=self.user,
            role=role,
            establishment_id=self.establishment.id
        )
        user_role.save()

    def test_schedule_CRUD(self):
        data = {
            'weekday': 1
        }

        response = self.client.post(f'/api/back/establishments/slug/{self.establishment.slug}/schedule/', data=data)
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        schedule = response.data

        response = self.client.get(f'/api/back/establishments/slug/{self.establishment.slug}/schedule/{schedule["id"]}/')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        update_data = {
            'weekday': 2
        }

        response = self.client.patch(f'/api/back/establishments/slug/{self.establishment.slug}/schedule/{schedule["id"]}/',
                                     data=update_data)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        response = self.client.delete(f'/api/back/establishments/slug/{self.establishment.slug}/schedule/{schedule["id"]}/')
        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)


# Web tests
class EstablishmentWebTests(BaseTestCase):

    def test_establishment_Read(self):
        params = {'page': 1, 'page_size': 1, }
        response = self.client.get('/api/web/establishments/', params, format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)


class EstablishmentWebTagTests(BaseTestCase):

    def test_tag_Read(self):
        response = self.client.get('/api/web/establishments/tags/', format='json')
        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)


class EstablishmentWebSlugTests(ChildTestCase):

    def test_slug_Read(self):
        response = self.client.get(f'/api/web/establishments/slug/{self.establishment.slug}/', format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)


class EstablishmentWebSimilarTests(ChildTestCase):

    def test_similar_Read(self):
        response = self.client.get(f'/api/web/establishments/slug/{self.establishment.slug}/similar/', format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)


class EstablishmentWebCommentsTests(ChildTestCase):

    def test_comments_CRUD(self):
        response = self.client.get(f'/api/web/establishments/slug/{self.establishment.slug}/comments/', format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        data = {
            'text': 'test',
            'user': self.user.id,
            'mark': 4
        }

        response = self.client.post(f'/api/web/establishments/slug/{self.establishment.slug}/comments/create/',
                                    data=data)

        comment = response.json()
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

        response = self.client.get(f'/api/web/establishments/slug/{self.establishment.slug}/comments/{comment["id"]}/',
                                   format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        update_data = {
            'text': 'Test new establishment'
        }

        response = self.client.patch(
            f'/api/web/establishments/slug/{self.establishment.slug}/comments/{comment["id"]}/',
            data=update_data)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        response = self.client.delete(
            f'/api/web/establishments/slug/{self.establishment.slug}/comments/{comment["id"]}/',
            format='json')
        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)


class EstablishmentWebFavoriteTests(ChildTestCase):

    def test_favorite_CR(self):
        data = {
            "user": self.user.id,
            "object_id": self.establishment.id
        }

        response = self.client.post(f'/api/web/establishments/slug/{self.establishment.slug}/favorites/',
                                    data=data)

        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

        response = self.client.delete(
            f'/api/web/establishments/slug/{self.establishment.slug}/favorites/',
            format='json')
        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)


class EstablishmentCarouselTests(ChildTestCase):

    def test_back_carousel_CR(self):
        data = {
            "object_id": self.establishment.id
        }

        response = self.client.post(f'/api/back/establishments/slug/{self.establishment.slug}/carousels/', data=data)
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

        response = self.client.delete(f'/api/back/establishments/slug/{self.establishment.slug}/carousels/')
        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
