from django.core.files.base import ContentFile
from django.db import transaction
from django.http.response import JsonResponse
from django.utils import timezone
from django.core.paginator import Paginator

from BookStore import error
from BookStore.function import check_login, check_method, \
    get_username_by_token, get_post_json

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

import base64
from decimal import Decimal

MAX_STORE_NUM = 9
MAX_PER_PAGE = 6


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

    try:
        user = User.objects.get(username=username)
        stores = [store.info_json() for store in Store.objects.filter(owner=user)]

        return JsonResponse({
            'message': 'ok',
            'num': len(stores),
            'stores': stores,
        })

    # 若用户名不存在则返回错误
    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 store_info_view(request):
    store_name = request.GET.get('store_id')
    off_books_page = int(request.GET.get('page', 1))

    # 判断参数是否存在
    if store_name is None:
        code, message = error.invalid_parameter()
        return JsonResponse({
            'message': message,
        }, status=code)

    try:
        store = Store.objects.get(storeName=store_name)
        off_books = Book.objects.filter(store=store, off=True).order_by('-createDate')

        off_books_paginator = Paginator(off_books, MAX_PER_PAGE)
        off_books_page = 1 if off_books_page < 1 else off_books_page
        off_books_page = off_books_paginator.num_pages if off_books_page > off_books_paginator.num_pages \
            else off_books_page

        return JsonResponse({
            'message': 'ok',
            'store': store.info_json(),
            'off_books_page': off_books_page,
            'off_books_page_num': off_books_paginator.num_pages,
            'off_book_num': len(off_books),
            'off_books': [book.info_simple_json() for book in off_books_paginator.page(off_books_page)],
        })

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

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


@check_method('GET')
def book_info_view(request):
    store_name = request.GET.get('store_id')
    book_id = request.GET.get('book_id')

    # 判断参数是否存在
    if store_name is None or book_id is None:
        code, message = error.invalid_parameter()
        return JsonResponse({
            'message': message,
        }, status=code)

    try:
        store = Store.objects.get(storeName=store_name)
        book = Book.objects.get(bookID=book_id, store=store)
        return JsonResponse({
            'message': 'ok',
            'store_id': store.storeName,
            'book_info': book.info_json(),
        })

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

    # 若book_id不存在
    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)


@check_login
@check_method('POST')
def create_store_view(request):
    # 通过token获取username
    username = get_username_by_token(request)

    # 接收前端传来的json
    post = get_post_json(request)
    user_id = post.get('user_id')
    store_name = post.get('store_id')

    # 判断必须参数是否存在
    if user_id is None or store_name is None:
        code, message = error.invalid_parameter()
        return JsonResponse({
            'message': message,
        }, status=code)

    # 选填的属性
    address = post.get('address', '')
    info = post.get('info', '')

    # 用token判断用户权限
    if username != user_id:
        code, message = error.authorization_fail()
        return JsonResponse({
            'message': message,
        }, status=code)

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

        # 若商铺名字已存在
        try:
            Store.objects.get(storeName=store_name)
            code, message = error.store_id_already_exist(store_name)
            return JsonResponse({
                'message': message,
            }, status=code)

        # 商铺名字不存在则创建新商铺
        except Store.DoesNotExist:
            try:
                stores = Store.objects.filter(owner=user)
                if len(stores) >= MAX_STORE_NUM:
                    code, message = error.too_many_stores(MAX_STORE_NUM)
                    return JsonResponse({
                        'message': message,
                    }, status=code)
                Store.objects.create(owner=user, storeName=store_name, address=address, info=info)
                return JsonResponse({
                    'message': 'ok',
                })

            # 创建失败
            except Exception as inner_e:
                print('Create(Insert) error! ', inner_e)
                code, message = error.database_error()
                return JsonResponse({
                    'message': message,
                }, status=code)

    # 若用户ID不存在则返回错误
    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 add_book_view(request):
    # 通过token获取username
    username = get_username_by_token(request)

    # 接收前端传来的json
    post = get_post_json(request)
    user_id = post.get('user_id')
    store_name = post.get('store_id')
    stock_level = int(post.get('stock_level', 0))

    # 获得的书籍信息
    book_info = post.get('book_info', {})
    book_id = book_info.get('id')
    title = book_info.get('title')
    cover = book_info.get('cover')

    if cover:
        cover = base64.b64decode(cover)
        cover = ContentFile(cover, 'book_cover.png')

    author = book_info.get('author')
    publisher = book_info.get('publisher')
    original_title = book_info.get('original_title')
    translator = book_info.get('translator')
    pub_year = book_info.get('pub_year')
    pages = book_info.get('pages', 0)

    # price这边为了迎合接口和前端，需判断price类型
    price = book_info.get('price')
    if type(price) is int:
        price = Decimal(str(price)[:-2] + '.' + str(price)[-2:])
    elif type(price) is str:
        pass
    else:
        price = 0

    binding = book_info.get('binding')
    isbn = book_info.get('isbn')
    author_intro = book_info.get('author_intro')
    book_intro = book_info.get('book_intro')
    content = book_info.get('content')
    tags = book_info.get('tags')
    pictures = book_info.get('pictures')

    # 用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_name, owner=user)

        # 若图书ID已存在
        try:
            Book.objects.get(bookID=book_id, store=store)
            code, message = error.book_id_already_exist(book_id)
            return JsonResponse({
                'message': message
            }, status=code)

        # 未存在则添加书籍
        except Book.DoesNotExist:
            try:
                with transaction.atomic():
                    book = Book.objects.create(bookID=book_id, store=store, stock=stock_level, price=price, isbn=isbn,
                                               title=title, author=author, publisher=publisher,
                                               originalTitle=original_title, cover=cover,
                                               translator=translator, pubYear=pub_year, pages=pages, binding=binding,
                                               authorIntro=author_intro, bookIntro=book_intro, content=content)

                    if tags:
                        for tag in tags:
                            Tag.objects.create(book=book, tag=tag)

                    if pictures:
                        for picture in pictures:
                            picture = base64.b64decode(picture)
                            picture = ContentFile(picture, 'book_picture.png')
                            Picture.objects.create(book=book, picture=picture)

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

            # 若插入错误
            except Exception as e2:
                print('Create(Insert) error! ', e2)
                code, message = error.database_error()
                return JsonResponse({
                    'message': message,
                }, status=code)

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

    # 若store_id不存在
    except Store.DoesNotExist:
        code, message = error.store_id_doesnt_exist(store_name)
        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_stock_level_view(request):
    # 通过token获取username
    username = get_username_by_token(request)

    # 接收前端传来的json
    post = get_post_json(request)
    user_id = post.get('user_id')
    store_name = post.get('store_id')
    book_id = post.get('book_id')

    try:
        add_stock_level = int(post.get('add_stock_level'))
    except Exception as e:
        print('str to int error! ', e)
        add_stock_level = 0

    # 若参数错误
    if user_id is None or store_name is None or book_id is None or add_stock_level is None or add_stock_level <= 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)

    # 判断商铺ID是否存在
    try:
        user = User.objects.get(username=username)
        store = Store.objects.get(storeName=store_name, owner=user)
        book = Book.objects.get(bookID=book_id, store=store)
        book.stock += add_stock_level
        book.save()

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

    except User.DoesNotExist:
        code, message = error.user_id_doesnt_exist(username)
        return JsonResponse({
            'message': message,
        }, status=code)

    # 若店铺ID不存在
    except Store.DoesNotExist:
        code, message = error.store_id_doesnt_exist(store_name)
        return JsonResponse({
            'message': message
        }, status=code)

    # 若book_id不存在
    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)


@check_login
@check_method('POST')
def modify_view(request):
    # 通过token获取username
    username = get_username_by_token(request)

    post = get_post_json(request)
    store_name = post.get('store_id')

    address = post.get('address')
    info = post.get('info')

    if store_name is None or (address is None and info is None):
        code, message = error.invalid_parameter()
        return JsonResponse({
            'message': message,
        }, status=code)

    try:
        store = Store.objects.get(storeName=store_name)
        owner = store.owner

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

        if address:
            store.address = address
        if info:
            store.info = info

        store.save()

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

    except Store.DoesNotExist:
        code, message = error.store_id_doesnt_exist(store_name)
        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 store_orders_view(request):
    # 通过token获取username
    username = get_username_by_token(request)

    store_name = request.GET.get('store_id')

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

    try:
        store = Store.objects.get(storeName=store_name)

        if username != store.owner.username:
            code, message = error.authorization_fail()
            return JsonResponse({
                'message': message,
            }, status=code)

    except Store.DoesNotExist:
        code, message = error.store_id_doesnt_exist(store_name)
        return JsonResponse({
            'message': message,
        }, status=code)

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

    try:
        orders = Order.objects.filter(store=store, valid=True, paid=True).order_by('-generateDate')

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

        return JsonResponse({
            'message': 'ok',
            'orders': [{
                'order_info': order.info_simple_json(),
                'books': [order_book_json(book) for book in OrderBook.objects.filter(order=order)]
            } for order in orders],
        })

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


@check_login
@check_method('POST')
def deliver_view(request):
    # 通过token获取username
    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:
        order = Order.objects.get(id=order_id)

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

        if order.state == state.order_shipped() or order.state == state.order_received():
            code, message = error.authorization_fail()
            return JsonResponse({
                'message': message,
            }, status=code)

        order.state = state.order_shipped()
        order.shippingDate = timezone.now()
        order.save()

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

    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 delete_store_view(request):
    # 通过token获取username
    username = get_username_by_token(request)

    post = get_post_json(request)

    store_id = post.get('store_id')

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

        if store.owner.username != username:
            code, message = error.authorization_fail()
            return JsonResponse({
                'message': message,
            }, status=code)

        store.delete()

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

    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 off_book_view(request):
    # 通过token获取username
    username = get_username_by_token(request)

    post = get_post_json(request)

    store_id = post.get('store_id')
    book_id = post.get('book_id')

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

    return modify_book(username, store_id, book_id)


@check_login
@check_method('POST')
def modify_price_view(request):
    # 通过token获取username
    username = get_username_by_token(request)

    post = get_post_json(request)

    store_id = post.get('store_id')
    book_id = post.get('book_id')
    price = post.get('price')

    if store_id is None or book_id is None or price is None:
        code, message = error.invalid_parameter()
        return JsonResponse({
            'message': message,
        }, status=code)

    return modify_book(username, store_id, book_id, price)


def modify_book(username, store_id, book_id, price=None):
    try:
        store = Store.objects.get(storeName=store_id)

        if store.owner.username != username:
            code, message = error.authorization_fail()
            return JsonResponse({
                'message': message,
            }, status=code)

        book = Book.objects.get(store=store, bookID=book_id)

        if price:
            if int(price) <= 0 :
                code, message = error.invalid_parameter()
                return JsonResponse({
                    'message': message,
                }, status=code)
            book.price = price
        else:
            if book.off:
                book.off = False
            else:
                book.off = True

        book.save()

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

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

    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)
