import json
from django.test import TestCase, Client

from BookStore import error, function

# Create your tests here.


# 注册并登录
from order import state
from order.models import Order
from order.views import auto_cancel
from store.models import Store, Book
from user.models import User


# class OrderInfoTest(TestCase):
#     def setUp(self) -> None:
#         register_and_login(self)
#
#     Store.object.create()
#
#     def test_success_order_info(self):
#         data = {
#             'order_id': 'id_1'
#         }

def login(self):
    data = {
        'user_id': 'stm',
        'password': '666666',
    }
    buyer = User.objects.create(username=data['user_id'], password=data['password'], balance=50000)

    seller = User.objects.create(username='yzm', password='999999')

    store = Store.objects.create(storeName='648全球连锁店', owner=seller, address='648')

    Book.objects.create(bookID='book_id_1', stock=10, store=store, isbn='1', title='1', price='1')
    Book.objects.create(bookID='book_id_2', stock=10, store=store, isbn='2', title='2', price='2')

    auto_cancel.start()
    # 未支付且买家支付得起的订单
    self.order1 = Order.objects.create(store=store, user=buyer, sumPrice=10, state=state.order_no_paid())
    auto_cancel.add_order_id(self.order1.id)
    # 已支付但未发货的订单
    self.order2 = Order.objects.create(store=store, user=buyer, sumPrice=10, state=state.order_paid_no_shipped(),
                                       paid=True)
    auto_cancel.add_order_id(self.order2.id)
    # 已失效订单
    self.order3 = Order.objects.create(store=store, user=buyer, sumPrice=10, state=state.order_invalid(), valid=False)
    auto_cancel.add_order_id(self.order3.id)
    # 未支付且买家支付不起的订单
    self.order4 = Order.objects.create(store=store, user=buyer, sumPrice=1000000, state=state.order_no_paid())
    auto_cancel.add_order_id(self.order4.id)
    # 买家未收货订单
    self.order5 = Order.objects.create(store=store, user=buyer, sumPrice=10, state=state.order_shipped(), paid=True)
    auto_cancel.add_order_id(self.order5.id)

    self.client = Client(HTTP_TOKEN=function.generate_token({'user_id': 'stm', 'terminal': '127.0.0.1'}))


class NewOrderTest(TestCase):
    def setUp(self) -> None:
        login(self)

    def test_store_id_not_exist(self):
        data = {
            'user_id': 'stm',
            "store_id": "华东师范大学",
            "books": [
                {
                    "id": "book_id_3",
                    "count": 1
                },
                {
                    "id": "book_id_4",
                    "count": 1
                }
            ],
            "address": "648"
        }

        response = self.client.post('/order/new_order/', data=data, content_type='application/json')

        code, message = error.store_id_doesnt_exist(data['store_id'])

        self.assertEqual(response.status_code, code)
        expect = {
            'message': message,
        }

        self.assertJSONEqual(response.content, expected_data=expect)

    def test_book_id_not_exist(self):
        data = {
            "user_id": "stm",
            "store_id": "648全球连锁店",
            "books": [
                {
                    "id": "book_id_3",
                    "count": 1
                },
                {
                    "id": "book_id_4",
                    "count": 1
                }
            ],
            "address": "648"
        }

        response = self.client.post('/order/new_order/', data=data, content_type='application/json')

        code, message = error.book_id_doesnt_exist(data['books'][0]['id'])

        self.assertEqual(response.status_code, code)
        expect = {
            'message': message,
        }
        self.assertJSONEqual(response.content, expected_data=expect)

    def test_stock_less(self):
        data = {
            "user_id": "stm",
            "store_id": "648全球连锁店",
            "books": [
                {
                    "id": "book_id_1",
                    "count": 11
                },
                {
                    "id": "book_id_2",
                    "count": 1
                }
            ],
            "address": "648"
        }

        response = self.client.post('/order/new_order/', data=data, content_type='application/json')

        code, message = error.stock_level_is_insufficient(data['books'][0]['id'])

        self.assertEqual(response.status_code, code)
        expect = {
            'message': message,
        }
        self.assertJSONEqual(response.content, expected_data=expect)

    def test_token_not_equal_userid(self):
        data = {
            "user_id": "yzm",
            "store_id": "648全球连锁店",
            "books": [
                {
                    "id": "book_id_1",
                    "count": 1
                },
                {
                    "id": "book_id_2",
                    "count": 1
                }
            ],
            "address": "648"
        }
        response = self.client.post('/order/new_order/', data=data, content_type='application/json')

        code, message = error.authorization_fail()

        self.assertEqual(response.status_code, code)
        expect = {
            'message': message,
        }
        self.assertJSONEqual(response.content, expected_data=expect)

    def test_new_order_success(self):
        data = {
            "user_id": "stm",
            "store_id": "648全球连锁店",
            "books": [
                {
                    "id": "book_id_1",
                    "count": 1
                },
                {
                    "id": "book_id_2",
                    "count": 1
                }
            ],
            "address": "648"
        }
        response = self.client.post('/order/new_order/', data=data, content_type='application/json')

        self.assertEqual(response.status_code, 200)
        expect = {
            'message': 'ok',
            'order_id': json.loads(response.content).get('order_id')
        }

        self.assertJSONEqual(response.content, expected_data=expect)


class PaymentTest(TestCase):
    def setUp(self) -> None:
        login(self)

    def test_pay_paid(self):
        print(self.order2.id)
        data = {
            "user_id": "stm",
            "order_id": self.order2.id,
            "password": "666666"
        }

        response = self.client.post('/buyer/payment/', data=data, content_type='application/json')

        code, message = error.authorization_fail()

        self.assertEqual(response.status_code, code)
        expect = {
            'message': message,
        }
        self.assertJSONEqual(response.content, expected_data=expect)

    def test_pay_invalid(self):
        data = {
            "user_id": "stm",
            "order_id": self.order3.id,
            "password": "666666"
        }

        response = self.client.post('/buyer/payment/', data=data, content_type='application/json')

        code, message = error.order_id_invalid(data["order_id"])

        self.assertEqual(response.status_code, code)
        expect = {
            'message': message,
        }
        self.assertJSONEqual(response.content, expected_data=expect)

    def test_order_id_not_exist(self):
        data = {
            "user_id": "stm",
            "order_id": 999,
            "password": "666666"
        }

        response = self.client.post('/buyer/payment/', data=data, content_type='application/json')

        code, message = error.order_id_doesnt_exist(int(data['order_id']))

        self.assertEqual(response.status_code, code)
        expect = {
            'message': message,
        }
        self.assertJSONEqual(response.content, expected_data=expect)

    def test_password_wrong(self):
        data = {
            "user_id": "stm",
            "order_id": self.order1.id,
            "password": "7777777"
        }

        response = self.client.post('/buyer/payment/', data=data, content_type='application/json')

        code, message = error.authorization_fail()

        self.assertEqual(response.status_code, code)
        expect = {
            'message': message,
        }
        self.assertJSONEqual(response.content, expected_data=expect)

    def test_user_not_dui(self):
        data = {
            "user_id": "zyx",
            "order_id": self.order1.id,
            "password": "7777777"
        }

        response = self.client.post('/buyer/payment/', data=data, content_type='application/json')

        code, message = error.authorization_fail()

        self.assertEqual(response.status_code, code)
        expect = {
            'message': message,
        }
        self.assertJSONEqual(response.content, expected_data=expect)

    def test_user_balances_not_enough(self):
        data = {
            "user_id": "stm",
            "order_id": self.order4.id,
            "password": "666666"
        }

        response = self.client.post('/buyer/payment/', data=data, content_type='application/json')

        code, message = error.balance_of_user_insufficient(data['user_id'])

        self.assertEqual(response.status_code, code)
        expect = {
            'message': message,
        }
        self.assertJSONEqual(response.content, expected_data=expect)

    def test_payment_success(self):
        data = {
            "user_id": "stm",
            "order_id": self.order1.id,
            "password": "666666"
        }

        response = self.client.post('/buyer/payment/', data=data, content_type='application/json')

        self.assertEqual(response.status_code, 200)
        expect = {
            'message': 'ok',
        }
        self.assertJSONEqual(response.content, expected_data=expect)


class AddFundsTest(TestCase):
    def setUp(self) -> None:
        login(self)

    def test_user_id_not_exist(self):
        data = {
            "user_id": "zyx",
            "password": "999999",
            "add_value": "1"
        }

        response = self.client.post('/buyer/add_funds/', data=data, content_type='application/json')

        code, message = error.user_id_doesnt_exist(data['user_id'])

        self.assertEqual(response.status_code, code)

        expect = {
            'message': message,
        }
        self.assertJSONEqual(response.content, expected_data=expect)

    def test_password_error(self):
        def test_user_id_not_exist(self):
            data = {
                "user_id": "stm",
                "password": "999999",
                "add_value": "1"
            }

            response = self.client.post('/buyer/add_funds/', data=data, content_type='application/json')

            code, message = error.authorization_fail()

            self.assertEqual(response.status_code, code)

            expect = {
                'message': message,
            }
            self.assertJSONEqual(response.content, expected_data=expect)

    def test_add_funds_error(self):
        def test_user_id_not_exist(self):
            data = {
                "user_id": "stm",
                "password": "666666",
                "add_value": "56"
            }

            response = self.client.post('/buyer/add_funds/', data=data, content_type='application/json')

            code, message = error.invalid_parameter()

            self.assertEqual(response.status_code, code)

            expect = {
                'message': message,
            }
            self.assertJSONEqual(response.content, expected_data=expect)

    def test_success_add_funds(self):
        def test_user_id_not_exist(self):
            data = {
                "user_id": "stm",
                "password": "666666",
                "add_value": "648"
            }

            response = self.client.post('/buyer/add_funds/', data=data, content_type='application/json')

            self.assertEqual(response.status_code, 200)

            expect = {
                'message': 'ok',
            }
            self.assertJSONEqual(response.content, expected_data=expect)


class MyOrdersTest(TestCase):
    def setUp(self) -> None:
        login(self)

    def test_success(self):
        response = self.client.get('/buyer/myorders/')

        self.assertEqual(response.status_code, 200)

        expect = {
            'message': 'ok',
            'num': json.loads(response.content).get('num'),
            'orders': json.loads(response.content).get('orders')
        }

        self.assertJSONEqual(response.content, expected_data=expect)


class CancelOrderTest(TestCase):
    def setUp(self) -> None:
        login(self)

    def test_order_id_not_exist(self):
        data = {
            "order_id": 99999
        }

        response = self.client.post('/buyer/cancel_order/', data=data, content_type='application/json')

        code, message = error.order_id_doesnt_exist(data['order_id'])

        self.assertEqual(response.status_code, code)

        expect = {
            'message': message,
        }
        self.assertJSONEqual(response.content, expected_data=expect)

    def test_order_invalid(self):
        data = {
            "order_id": self.order3.id
        }

        response = self.client.post('/buyer/cancel_order/', data=data, content_type='application/json')

        code, message = error.order_id_invalid(data['order_id'])

        self.assertEqual(response.status_code, code)

        expect = {
            'message': message,
        }
        self.assertJSONEqual(response.content, expected_data=expect)

    def test_success(self):
        data = {
            "order_id": self.order1.id
        }

        response = self.client.post('/buyer/cancel_order/', data=data, content_type='application/json')

        self.assertEqual(response.status_code, 200)

        expect = {
            'message': 'ok',
        }

        self.assertJSONEqual(response.content, expected_data=expect)


class CompleteOrderTest(TestCase):
    def setUp(self) -> None:
        login(self)

    def test_order_id_not_exist(self):
        data = {
            "order_id": 9999999
        }

        response = self.client.post('/buyer/complete_order/', data=data, content_type='application/json')

        code, message = error.order_id_doesnt_exist(data['order_id'])

        self.assertEqual(response.status_code, code)

        expect = {
            'message': message,
        }
        self.assertJSONEqual(response.content, expected_data=expect)

    def test_order_not_dui(self):
        data = {
            "order_id": self.order1.id
        }

        response = self.client.post('/buyer/complete_order/', data=data, content_type='application/json')

        code, message = error.authorization_fail()

        self.assertEqual(response.status_code, code)

        expect = {
            'message': message,
        }
        self.assertJSONEqual(response.content, expected_data=expect)

        data = {
            "order_id": self.order3.id
        }

        response = self.client.post('/buyer/complete_order/', data=data, content_type='application/json')

        code, message = error.authorization_fail()

        self.assertEqual(response.status_code, code)

        expect = {
            'message': message,
        }
        self.assertJSONEqual(response.content, expected_data=expect)

        data = {
            "order_id": self.order2.id
        }

        response = self.client.post('/buyer/complete_order/', data=data, content_type='application/json')

        code, message = error.authorization_fail()

        self.assertEqual(response.status_code, code)

        expect = {
            'message': message,
        }
        self.assertJSONEqual(response.content, expected_data=expect)

    def test_success(self):
        data = {
            "order_id": self.order5.id
        }

        response = self.client.post('/buyer/complete_order/', data=data, content_type='application/json')

        self.assertEqual(response.status_code, 200)

        expect = {
            'message': 'ok',
        }
        self.assertJSONEqual(response.content, expected_data=expect)


class OrderInfoTest(TestCase):
    def setUp(self) -> None:
        login(self)

    def test_order_id_not_exist(self):
        data = {
            'order_id': 456465456,
        }

        response = self.client.get('/buyer/order_info/', data=data, content_type='application/json')

        code, message = error.order_id_doesnt_exist(data['order_id'])

        self.assertEqual(response.status_code, code)

        expect = {
            'message': message,
        }
        self.assertJSONEqual(response.content, expected_data=expect)

    def test_success(self):
        data = {
            'order_id': self.order5.id,
        }

        response = self.client.get('/buyer/order_info/', data=data, content_type='application/json')

        self.assertEqual(response.status_code, 200)

        expect = {
            'message': 'ok',
            'order_id': json.loads(response.content).get('order_id'),
            'order_info': json.loads(response.content).get('order_info')
        }
        self.assertJSONEqual(response.content, expected_data=expect)
