from django.http.response import JsonResponse
from django.db import transaction
from django.utils import timezone

from BookStore import error
from BookStore.function import check_login, check_method, \
    get_username_by_token, get_post_json
from order import state
from .auto_cancel import AutoCancel

from user.models import User
from order.models import Order, OrderBook
from store.models import Store, Book

from decimal import Decimal

ADD_VALUE_LIST = [Decimal('1'), Decimal('6'), Decimal('18'), Decimal('30'), Decimal('68'),
                  Decimal('118'), Decimal('198'), Decimal('348'), Decimal('648')]

# 启动自动取消
auto_cancel = AutoCancel()
auto_cancel.start()


# Create your views here.
@check_login
@check_method('GET')
def my_orders_view(request):
    username = get_username_by_token(request)

    def order_book_json(book):
        book_json = book.book.info_simple_json()
        book_json.update({'count': book.count})
        return book_json

    try:
        user = User.objects.get(username=username)
        orders = Order.objects.filter(user=user).order_by('-generateDate')
        return JsonResponse({
            'message': 'ok',
            'num': len(orders),
            'orders': [{
                'order_info': order.info_simple_json(),
                'books': [order_book_json(book) for book in OrderBook.objects.filter(order=order)]
            } for order in orders],
        })

    # 若username不存在则返回错误
    except User.DoesNotExist:
        code, message = error.user_id_doesnt_exist(username)
        return JsonResponse({
            'message': message,
        }, status=code)

    # 其他数据库错误
    except Exception as e:
        print(e)
        code, message = error.database_error()
        return JsonResponse({
            'message': message,
        }, status=code)


@check_login
@check_method('GET')
def order_info_view(request):
    order_id = request.GET.get('order_id')

    # 若字典中不存在order_id，则参数错误
    if order_id is None:
        code, message = error.invalid_parameter()
        return JsonResponse({
            'message': message,
        }, status=code)

    try:
        order = Order.objects.get(id=order_id)
        return JsonResponse({
            'message': 'ok',
            'order_id': str(order.id),
            'order_info': order.info_json(),
        })

    # 若订单ID不存在
    except Order.DoesNotExist:
        code, message = error.order_id_doesnt_exist(order_id)
        return JsonResponse({
            'message': message
        }, status=code)

    # 其他数据库错误
    except Exception as e:
        print(e)
        code, message = error.database_error()
        return JsonResponse({
            'message': message,
        }, status=code)


@check_login
@check_method('POST')
def add_funds_view(request):
    # 获取前端传来的json
    post = get_post_json(request)
    username = post.get('user_id')
    password = post.get('password')
    add_value = post.get('add_value')

    if type(add_value) is int:
        add_value = str(add_value)[:-2] + '.' + str(add_value)[-2:]

    if username is None or password is None or add_value is None \
            or type(username) != str or type(password) != str or type(add_value) != str:
        code, message = error.invalid_parameter()
        return JsonResponse({
            'message': message,
        }, status=code)

    # 判断充值金额是否正确
    try:
        add_value = Decimal(add_value)
    except Exception as e:
        print('add_value error!', e)
        add_value = 0

    if add_value not in ADD_VALUE_LIST:
        code, message = error.invalid_parameter()
        return JsonResponse({
            'message': message,
        }, status=code)

    try:
        user = User.objects.get(username=username)

        # 充值user对象存在判断对应密码是否正确
        if user.password != password:
            code, message = error.authorization_fail()
            return JsonResponse({
                'message': message,
            }, status=code)

        try:
            user.balance += add_value
            user.save()
            return JsonResponse({
                'message': 'ok',
            })

        except Exception as e:
            print(e)
            code, message = error.database_error()
            return JsonResponse({
                'message': message,
            }, status=code)

    # 若userID不存在
    except User.DoesNotExist:
        code, message = error.user_id_doesnt_exist(username)
        return JsonResponse({
            'message': message,
        }, status=code)

    except Exception as e:
        print(e)
        code, message = error.database_error()
        return JsonResponse({
            'message': message,
        }, status=code)


# @check_login
@check_method('POST')
def new_order_view(request):
    # 获取username
    # username = get_username_by_token(request)

    # 获取前端传来的json
    post = get_post_json(request)
    user_id = post.get('user_id')
    store_id = post.get('store_id')
    books = post.get('books')
    # 获取用户请求中的收货地址作为订单的收货地址
    receiving_address = post.get('address')

    if user_id is None or store_id is None or books is None or receiving_address is None or len(books) <= 0:
        code, message = error.invalid_parameter()
        return JsonResponse({
            'message': message,
        }, status=code)

    # # 判断token是否为当前用户
    # if username != user_id:
    #     code, message = error.authorization_fail()
    #     return JsonResponse({
    #         'message': message,
    #     }, status=code)
    username = user_id

    try:
        user = User.objects.get(username=username)
        store = Store.objects.get(storeName=store_id)

        # 用户不能购买自己店铺的书
        if store.owner == user:
            code, message = error.authorization_fail()
            return JsonResponse({
                'message': message,
            }, status=code)

        # 判断所有购买书籍是否存在,店家库存是否足够,同时获取购买所有书籍的总金额
        sum_price = Decimal('0.00')

        for book in books:
            book_id = book.get('id')
            count = int(book.get('count'))

            try:
                get_book = Book.objects.get(bookID=book_id, store=store)
                sum_price += Decimal(get_book.price * count)

            # 图书信息不存在
            except Book.DoesNotExist:
                code, message = error.book_id_doesnt_exist(book_id)
                return JsonResponse({
                    'message': message,
                }, status=code)

            except Exception as e:
                print(e)
                code, message = error.database_error()
                return JsonResponse({
                    'message': message,
                }, status=code)

        # 获取书店地址作为订单的发货地址
        shipping_address = store.address

        # 确定用户ID，书店ID，购买书籍信息后创建新订单
        try:
            # 使用事务处理API， 保证接下来的一系列操作的原子性
            with transaction.atomic():
                # 设置断电
                rollback_point = transaction.savepoint()
                order = Order.objects.create(store=store, user=user, sumPrice=sum_price,
                                             shippingAddress=shipping_address,
                                             receivingAddress=receiving_address, state=state.order_no_paid())
                # 生成OrderBook
                for book in books:
                    book_id = book.get('id')
                    count = int(book.get('count'))
                    order_book = Book.objects.get(bookID=book_id, store=store)

                    # 若库存不足则返回
                    if order_book.stock < count:
                        # 事务回滚到断点
                        transaction.rollback(rollback_point)
                        code, message = error.stock_level_is_insufficient(book_id)
                        return JsonResponse({
                            'message': message
                        }, status=code)

                    OrderBook.objects.create(order=order, book=order_book, title=order_book.title, count=count,
                                             booksPrice=order_book.price * count)
                    # 减少商家库存
                    order_book.stock -= count
                    order_book.save()

            # 将这个新的订单加入自动取消调度器
            auto_cancel.add_order_id(order_id=order.id)

            return JsonResponse({
                'message': 'ok',
                'order_id': str(order.id),
            })

        # 新建订单失败
        except Exception as new_order_error:
            print('New order error! ', new_order_error)
            code, message = error.stock_level_is_insufficient(book_id)
            return JsonResponse({
                'message': message
            }, status=code)

    # userID不存在
    except User.DoesNotExist:
        code, message = error.user_id_doesnt_exist(user_id)
        return JsonResponse({
            'message': message,
        }, status=code)

    # storeID不存在
    except Store.DoesNotExist:
        code, message = error.store_id_doesnt_exist(store_id)
        return JsonResponse({
            'message': message,
        }, status=code)

    except Exception as e:
        print(e)
        code, message = error.database_error()
        return JsonResponse({
            'message': message,
        }, status=code)


# @check_login
@check_method('POST')
def payment_view(request):
    # username = get_username_by_token(request)

    # 获取前端传来的json
    post = get_post_json(request)
    user_id = post.get('user_id')
    order_id = post.get('order_id')
    password = post.get('password')

    if user_id is None or order_id is None or password is None:
        code, message = error.invalid_parameter()
        return JsonResponse({
            'message': message,
        }, status=code)

    # # 用户名不匹配
    # if user_id != username:
    #     code, message = error.authorization_fail()
    #     return JsonResponse({
    #         'message': message
    #     }, status=code)
    username = user_id

    # 判断用户是否存在
    try:
        user = User.objects.get(username=user_id)

        # 若用户密码不存在
        if user.password != password:
            code, message = error.authorization_fail()
            return JsonResponse({
                'message': message,
            }, status=code)

        order = Order.objects.get(id=order_id)

        # 判断订单拥有者是否为该用户
        if order.user != user:
            code, message = error.authorization_fail()
            return JsonResponse({
                'message': message,
            }, status=code)

        print(order.valid)
        # 如果订单已失效
        if not order.valid:
            code, message = error.order_id_invalid(order_id)
            return JsonResponse({
                'message': message,
            }, status=code)

        # 判断订单是否已经付款
        if order.paid:
            code, message = error.authorization_fail()
            return JsonResponse({
                'message': message,
            }, status=code)

        # 确认订单与用户信息无误后获取该订单购买的书籍的总价格
        sum_price = order.sumPrice

        # 获取到总价格后，判断支付该订单的用户余额是否足够
        if user.balance < sum_price:
            code, message = error.balance_of_user_insufficient(user_id)
            return JsonResponse({
                'message': message
            }, status=code)

        # 完全确认后启动支付事务即修改订单信息、修改用户余额、修改商家余额
        try:
            # 使用事务处理API， 保证接下来的一系列操作的原子性
            with transaction.atomic():
                # 修改订单信息
                order.paid = True
                order.state = state.order_paid_no_shipped()
                order.paymentDate = timezone.now()
                order.save()

                # 减少用户余额
                user.balance -= sum_price
                user.save()

                # 增加商家余额
                seller = order.store.owner
                seller.balance += sum_price
                seller.save()

                # 增加订单内书本出售数量
                sum_sold = 0
                for order_book in OrderBook.objects.filter(order=order):
                    book = order_book.book
                    book.sold += order_book.count
                    book.save()
                    sum_sold += order_book.count

                # 增加店铺总出售量
                store = order.store
                store.sold += sum_sold
                store.save()

            # 将此订单从自动失效的调度器中拿出
            auto_cancel.remove_order_id(order_id)

            return JsonResponse({
                'message': 'ok',
            })

        except Exception as pay_error:
            print('Payment error! ', pay_error)
            code, message = error.database_error()
            return JsonResponse({
                'message': message,
            }, status=code)

    # userID不存在
    except User.DoesNotExist:
        code, message = error.user_id_doesnt_exist(user_id)
        return JsonResponse({
            'message': message,
        }, status=code)

    # 订单不存在
    except Order.DoesNotExist:
        code, message = error.order_id_doesnt_exist(order_id)
        return JsonResponse({
            'message': message,
        }, status=code)

    except Exception as e:
        print(e)
        code, message = error.database_error()
        return JsonResponse({
            'message': message,
        }, status=code)


@check_login
@check_method('POST')
def cancel_view(request):
    username = get_username_by_token(request)

    post = get_post_json(request)
    # user_id = post.get('user_id')
    order_id = post.get('order_id')

    # 参数不存在
    if order_id is None:
        code, message = error.invalid_parameter()
        return JsonResponse({
            'message': message
        }, status=code)

    # # 用户名不匹配
    # if user_id != username:
    #     code, message = error.authorization_fail()
    #     return JsonResponse({
    #         'message': message
    #     }, status=code)

    try:
        user = User.objects.get(username=username)
        order = Order.objects.get(id=order_id)

        # 如果订单不属于此人
        if order.user != user:
            code, message = error.authorization_fail()
            return JsonResponse({
                'message': message
            }, status=code)

        if order.valid is False:
            code, message = error.order_id_invalid(order_id)
            return JsonResponse({
                'message': message,
            }, status=code)

        if order.paid:
            code, message = error.authorization_fail()
            return JsonResponse({
                'message': message,
            })
        try:
            # 使用事务处理API， 保证接下来的一系列操作的原子性
            with transaction.atomic():
                # 取消订单，修改订单信息
                order.valid = False
                order.state = state.order_invalid()
                order.save()

                # 增加商家库存
                order_books = OrderBook.objects.filter(order=order)
                for order_book in order_books:
                    book = order_book.book
                    book.stock += order_book.count
                    book.save()

        except Exception as cancel_error:
            print('Cancel order error! ', cancel_error)
            code, message = error.database_error()
            return JsonResponse({
                'message': message,
            }, status=code)

        # 将此订单从自动取消调度器中取出
        auto_cancel.remove_order_id(order_id)

        return JsonResponse({
            'message': 'ok',
        })

    # 用户ID不存在
    except User.DoesNotExist:
        code, message = error.user_id_doesnt_exist(username)
        return JsonResponse({
            'message': message,
        }, status=code)

    # 订单ID不存在
    except Order.DoesNotExist:
        code, message = error.order_id_doesnt_exist(order_id)
        return JsonResponse({
            'message': message,
        }, status=code)

    # 其他数据库错误
    except Exception as e:
        print(e)
        code, message = error.database_error()
        return JsonResponse({
            'message': message,
        }, status=code)


def complete_order_view(request):
    username = get_username_by_token(request)

    post = get_post_json(request)
    order_id = post.get('order_id')

    if order_id is None:
        code, message = error.invalid_parameter()
        return JsonResponse({
            'message': message
        }, status=code)

    try:
        user = User.objects.get(username=username)
        order = Order.objects.get(id=order_id)

        if order.user != user:
            code, message = error.authorization_fail()
            return JsonResponse({
                'message': message
            }, status=code)

        if order.valid is False or order.paid is False or order.state == state.order_paid_no_shipped():
            code, message = error.authorization_fail()
            return JsonResponse({
                'message': message,
            }, status=code)

        # 完成订单，修改订单信息
        order.state = state.order_received()
        order.complete = True
        order.completeDate = timezone.now()
        order.save()

        return JsonResponse({
            'message': 'ok',
        })

    # 若订单ID不存在
    except Order.DoesNotExist:
        code, message = error.order_id_doesnt_exist(order_id)
        return JsonResponse({
            'message': message
        }, status=code)

    except Exception as e:
        print(e)
        code, message = error.database_error()
        return JsonResponse({
            'message': message,
        }, status=code)
