import logging

from django.db import transaction
from django.db.models import Q, F
from rest_framework import status
from rest_framework.response import Response
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema

from common.utils.views import BaseApiView, AllowAnyApiView
from common.utils.exceptions import ValidationError
from common.utils.serializers import serializer_assembly
from common.utils.return_structure import general_message, error_message
from common.utils.service_code import VERIFICATION_ERROR, MYSQL_OPERATE_ERROR
from common.utils.pagination import CustomPageNumberPagination

from console.learningcenter.serializers import (KnowledgePointSerializer,
                                                KnowledgeListSerializer,
                                                KnowledgeRepositorySerializer,
                                                MiniKnowledgeListSerializer,
                                                MiniNewsListSerializer)
from console.learningcenter.models import KnowledgePoint, KnowledgeRepository

logger = logging.getLogger('')


# Create your views here.
class KnowledgeLDView(BaseApiView):
    """
    web新闻与知识点删除与列表展示
    """
    queryset = KnowledgePoint.objects.all()
    serializer_class = KnowledgeListSerializer
    pagination_class = CustomPageNumberPagination

    @swagger_auto_schema(operation_description="知识点列表",
                         tags=["knowledge"],
                         manual_parameters=[
                             openapi.Parameter(name="title",
                                               in_=openapi.IN_QUERY,
                                               type=openapi.TYPE_STRING,
                                               description="标题",
                                               required=False),
                             openapi.Parameter("page",
                                               openapi.IN_QUERY,
                                               description="页码",
                                               required=False,
                                               type=openapi.TYPE_INTEGER),
                             openapi.Parameter("page_size",
                                               openapi.IN_QUERY,
                                               description="每页数量",
                                               required=False,
                                               type=openapi.TYPE_INTEGER)
                         ],
                         responses={
                             status.HTTP_200_OK:
                             serializer_assembly(KnowledgeListSerializer,
                                                 many=True)
                         })
    def get(self, request, *args, **kwargs):
        title = request.GET.get('title')
        if title:
            self.queryset = self.queryset.filter(
                Q(title__contains=title)
                | (Q(text__contains=title))).order_by('-updated_time')
        page = self.paginate_queryset(queryset=self.queryset)
        if page:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = KnowledgePointSerializer(self.queryset.all(), many=True)
        return Response(data=general_message(msg_show="数据请求成功",
                                             list=serializer.data),
                        status=status.HTTP_200_OK)

    @swagger_auto_schema(operation_description="知识点删除",
                         tags=["knowledge"],
                         manual_parameters=[
                             openapi.Parameter(name="id",
                                               in_=openapi.IN_QUERY,
                                               type=openapi.TYPE_INTEGER,
                                               description="id",
                                               required=True)
                         ],
                         responses={status.HTTP_200_OK: {}})
    @transaction.atomic
    def delete(self, request, *args, **kwargs):
        k_id = kwargs.get('id')
        if not k_id:
            raise ValidationError("参数错误")
        else:
            instance = KnowledgePoint.objects.filter(id=k_id).first()
            if instance:
                sid = transaction.savepoint()
                try:
                    KnowledgePoint.objects.filter(id=k_id).delete()
                    transaction.savepoint_commit(sid)
                    # 删除知识点信息
                    return Response(data=general_message('删除成功'))
                except Exception as e:
                    logger.info('知识点删除失败：', e)
                    transaction.rollback(sid)
                    return Response(data=error_message(
                        code=MYSQL_OPERATE_ERROR, msg='fail', msg_show='删除失败'))
            else:
                raise ValidationError("参数错误")


class KnowledgeCreateView(BaseApiView):
    """
    知识点详情编辑与保存
    """
    queryset = KnowledgePoint.objects.all()
    serializer_class = KnowledgePointSerializer

    @swagger_auto_schema(operation_description="知识点详情获取",
                         tags=["knowledge"],
                         manual_parameters=[
                             openapi.Parameter(name="id",
                                               in_=openapi.IN_QUERY,
                                               type=openapi.TYPE_INTEGER,
                                               description="id",
                                               required=True)
                         ],
                         responses={
                             status.HTTP_200_OK:
                             serializer_assembly(KnowledgePointSerializer)
                         })
    def get(self, request, *args, **kwargs):

        k_id = request.GET.get('id')
        self.queryset = self.queryset.filter(id=k_id).first()
        if self.queryset:
            data = KnowledgePointSerializer(self.queryset).data
            return Response(data=general_message(msg_show="数据请求成功", bean=data),
                            status=status.HTTP_200_OK)
        else:
            return Response(data=general_message(msg_show="数据为空"),
                            status=status.HTTP_200_OK)

    @swagger_auto_schema(operation_description="知识点创建保存",
                         tags=["knowledge"],
                         request_body=KnowledgePointSerializer,
                         responses={status.HTTP_200_OK: {}})
    def post(self, request, *args, **kwargs):
        data = request.data
        data['operator'] = request.user.username
        serializer = self.get_serializer(data=data)
        if serializer.is_valid():
            serializer.save()
            return Response(data=general_message(msg_show="提交成功"))
        return Response(data=error_message(
            code=VERIFICATION_ERROR, msg_show="提交失败", msg='create fail'))

    @swagger_auto_schema(operation_description="知识点更新",
                         tags=["knowledge"],
                         request_body=KnowledgePointSerializer,
                         responses={status.HTTP_200_OK: {}})
    def put(self, request, *args, **kwargs):
        data = request.data
        data['operator'] = request.user.username
        knowledge_instance = KnowledgePoint.objects.filter(
            id=request.data.get('id')).first()
        serializer = KnowledgePointSerializer(instance=knowledge_instance,
                                              data=data)
        if serializer.is_valid():
            serializer.save()
            return Response(data=general_message(msg_show="提交成功"))
        return Response(data=error_message(
            code=VERIFICATION_ERROR, msg_show="提交失败", msg='update fail'))


class KnowledgeRepositoryLDView(BaseApiView):
    """
    知识库列表获取与删除、更新
    """
    queryset = KnowledgeRepository.objects.all()
    serializer_class = KnowledgeRepositorySerializer
    pagination_class = CustomPageNumberPagination

    @swagger_auto_schema(operation_description="知识库列表展示",
                         tags=["warehouse"],
                         manual_parameters=[
                             openapi.Parameter(name="name",
                                               in_=openapi.IN_QUERY,
                                               type=openapi.TYPE_STRING,
                                               description="知识库名",
                                               required=False),
                             openapi.Parameter("page",
                                               openapi.IN_QUERY,
                                               description="页码",
                                               required=False,
                                               type=openapi.TYPE_INTEGER),
                             openapi.Parameter("page_size",
                                               openapi.IN_QUERY,
                                               description="每页数量",
                                               required=False,
                                               type=openapi.TYPE_INTEGER)
                         ],
                         responses={
                             status.HTTP_200_OK:
                             serializer_assembly(KnowledgeRepositorySerializer,
                                                 many=True)
                         })
    def get(self, request, *args, **kwargs):
        name = request.GET.get('name')
        k_id = kwargs.get('id')
        if k_id:
            instance = self.queryset.filter(id=k_id).first()
            if instance:
                serializer = KnowledgeRepositorySerializer(instance)
                return Response(data=general_message(msg_show="数据请求成功",
                                                     bean=serializer.data),
                                status=status.HTTP_200_OK)
        if name:
            self.queryset = self.queryset.filter(name__contains=name)
        # queryset = self.filter_queryset(self.get_queryset())  # 有什么用？
        page = self.paginate_queryset(queryset=self.queryset)
        if page:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = KnowledgeRepositorySerializer(self.queryset.all(),
                                                   many=True)
        return Response(data=general_message(msg_show="数据请求成功",
                                             list=serializer.data),
                        status=status.HTTP_200_OK)

    @swagger_auto_schema(operation_description="知识库删除",
                         tags=["warehouse"],
                         manual_parameters=[
                             openapi.Parameter(name="id",
                                               in_=openapi.IN_QUERY,
                                               type=openapi.TYPE_INTEGER,
                                               description="知识库id",
                                               required=False)
                         ],
                         responses={status.HTTP_200_OK: {}})
    @transaction.atomic
    def delete(self, request, *args, **kwargs):
        k_id = kwargs.get('id')
        if not k_id:
            raise ValidationError("参数错误")
        else:
            instance = KnowledgeRepository.objects.filter(id=k_id).first()
            if instance:
                sid = transaction.savepoint()
                try:
                    KnowledgeRepository.objects.filter(id=k_id).delete()
                    transaction.savepoint_commit(sid)
                    # 删除知识点信息
                    return Response(data=general_message('删除成功'))
                except Exception as e:
                    logger.info('知识点删除失败：', e)
                    transaction.rollback(sid)
                    return Response(data=error_message(
                        code=MYSQL_OPERATE_ERROR, msg='fail', msg_show='删除失败'))
            else:
                raise ValidationError("参数错误")

    @swagger_auto_schema(operation_description="知识库保存与更新",
                         tags=["warehouse"],
                         request_body=KnowledgeRepositorySerializer,
                         responses={status.HTTP_200_OK: {}})
    def post(self, request, *args, **kwargs):
        data = request.data
        data['operator'] = request.user.username
        if request.data.get('id'):
            repository_instance = KnowledgeRepository.objects.filter(
                id=request.data.get('id')).first()
        else:
            repository_instance = KnowledgeRepository.objects.filter(
                name=request.data.get('name')).first()
        if repository_instance:
            # 更新
            serializer = KnowledgeRepositorySerializer(
                instance=repository_instance, data=data)
        else:
            # 新建
            serializer = self.get_serializer(data=data)
        if serializer.is_valid():
            serializer.save()
            return Response(data=general_message(msg_show="提交成功"))
        return Response(data=error_message(
            code=VERIFICATION_ERROR, msg_show="提交失败", msg='create error'))


# 小程序获取知识库列表
class MiniKnowledgeRepositoryLView(AllowAnyApiView):
    queryset = KnowledgeRepository.objects.all().order_by(
        '-is_hot', '-updated_time')
    serializer_class = KnowledgeRepositorySerializer
    pagination_class = CustomPageNumberPagination

    @swagger_auto_schema(operation_description="小程序知识库列表展示",
                         tags=["mini"],
                         manual_parameters=[
                             openapi.Parameter(name="is_hot",
                                               in_=openapi.IN_QUERY,
                                               type=openapi.TYPE_BOOLEAN,
                                               description="是否推荐到首页",
                                               required=False),
                             openapi.Parameter("page",
                                               openapi.IN_QUERY,
                                               description="页码",
                                               required=False,
                                               type=openapi.TYPE_INTEGER),
                             openapi.Parameter("page_size",
                                               openapi.IN_QUERY,
                                               description="每页数量",
                                               required=False,
                                               type=openapi.TYPE_INTEGER)
                         ],
                         responses={
                             status.HTTP_200_OK:
                             serializer_assembly(KnowledgeRepositorySerializer,
                                                 many=True)
                         })
    def get(self, request, *args, **kwargs):
        page = self.paginate_queryset(queryset=self.queryset)
        if page:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = KnowledgeRepositorySerializer(self.queryset.all(),
                                                   many=True)
        return Response(data=general_message(msg_show="数据请求成功",
                                             list=serializer.data),
                        status=status.HTTP_200_OK)


# 小程序知识点列表
class MiniKnowledgeLView(AllowAnyApiView):
    queryset = KnowledgePoint.objects.all()
    serializer_class = MiniKnowledgeListSerializer
    pagination_class = CustomPageNumberPagination

    @swagger_auto_schema(operation_description="小程序知识点列表展示",
                         tags=["mini"],
                         manual_parameters=[
                             openapi.Parameter(name="s_key_knowledge",
                                               in_=openapi.IN_QUERY,
                                               type=openapi.TYPE_BOOLEAN,
                                               description="首页热门知识点=1",
                                               required=False),
                             openapi.Parameter(name="title",
                                               in_=openapi.IN_QUERY,
                                               type=openapi.TYPE_STRING,
                                               description="搜索框模糊查询：标题内容",
                                               required=False),
                             openapi.Parameter(name="warehouse_id",
                                               in_=openapi.IN_QUERY,
                                               type=openapi.TYPE_INTEGER,
                                               description="知识库id：知识库点击传入",
                                               required=False),
                             openapi.Parameter("page",
                                               openapi.IN_QUERY,
                                               description="页码",
                                               required=False,
                                               type=openapi.TYPE_INTEGER),
                             openapi.Parameter("page_size",
                                               openapi.IN_QUERY,
                                               description="每页数量",
                                               required=False,
                                               type=openapi.TYPE_INTEGER)
                         ],
                         responses={
                             status.HTTP_200_OK:
                             serializer_assembly(MiniKnowledgeListSerializer,
                                                 many=True)
                         })
    def get(self, request, *args, **kwargs):
        title = request.GET.get('title')  # 知识点的查询条件
        warehouse_id = request.GET.get('warehouse_id')  # 查询条件属于哪个知识库
        is_key_knowledge = request.GET.get('is_key_knowledge')  # 是否热门知识点
        if is_key_knowledge:  # 小程序首页获取热门知识点
            self.queryset = self.queryset.filter(
                is_key_knowledge=is_key_knowledge)
        elif title and warehouse_id:  # 其他查询条件
            self.queryset = self.queryset.filter(
                (Q(title__contains=title) | (Q(text__contains=title)))
                & (Q(knowledge_warehouse_type=warehouse_id)))\
                .order_by('-updated_time')
        elif warehouse_id:
            self.queryset = self.queryset.filter(
                knowledge_warehouse_type=warehouse_id).order_by(
                    '-updated_time')
        elif title:
            self.queryset = self.queryset.filter(Q(title__contains=title)
                                                 | (Q(text__contains=title)))\
                .order_by('-updated_time')
        else:
            self.queryset = self.queryset.order_by('-updated_time')
        page = self.paginate_queryset(queryset=self.queryset)
        if page:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = KnowledgePointSerializer(self.queryset.all(), many=True)
        return Response(data=general_message(msg_show="数据请求成功",
                                             list=serializer.data),
                        status=status.HTTP_200_OK)


# 小程序新闻列表
class MiniNewsLView(AllowAnyApiView):
    queryset = KnowledgePoint.objects.all()
    serializer_class = MiniNewsListSerializer
    pagination_class = CustomPageNumberPagination

    @swagger_auto_schema(operation_description="小程序新闻列表展示",
                         tags=["mini"],
                         manual_parameters=[
                             openapi.Parameter("page",
                                               openapi.IN_QUERY,
                                               description="页码",
                                               required=False,
                                               type=openapi.TYPE_INTEGER),
                             openapi.Parameter("page_size",
                                               openapi.IN_QUERY,
                                               description="每页数量",
                                               required=False,
                                               type=openapi.TYPE_INTEGER)
                         ],
                         responses={
                             status.HTTP_200_OK:
                             serializer_assembly(MiniNewsListSerializer,
                                                 many=True)
                         })
    def get(self, request, *args, **kwargs):
        self.queryset = self.queryset.filter(knowledge_type=1).\
            order_by('-updated_time')
        page = self.paginate_queryset(queryset=self.queryset)
        if page:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = KnowledgePointSerializer(self.queryset.all(), many=True)
        return Response(data=general_message(msg_show="数据请求成功",
                                             list=serializer.data),
                        status=status.HTTP_200_OK)


# 小程序新闻与知识点详情
class MiniKnowledgeView(AllowAnyApiView):
    queryset = KnowledgePoint.objects.all()
    serializer_class = KnowledgePointSerializer

    @swagger_auto_schema(operation_description="小程序新闻或知识点详情展示",
                         tags=["mini"],
                         manual_parameters=[
                             openapi.Parameter("id",
                                               openapi.IN_QUERY,
                                               description="id",
                                               required=True,
                                               type=openapi.TYPE_INTEGER),
                             openapi.Parameter("page",
                                               openapi.IN_QUERY,
                                               description="页码",
                                               required=False,
                                               type=openapi.TYPE_INTEGER),
                             openapi.Parameter("page_size",
                                               openapi.IN_QUERY,
                                               description="每页数量",
                                               required=False,
                                               type=openapi.TYPE_INTEGER)
                         ],
                         responses={
                             status.HTTP_200_OK:
                             serializer_assembly(KnowledgePointSerializer)
                         })
    def get(self, request, *args, **kwargs):
        k_id = request.GET.get('id')
        self.queryset = self.queryset.filter(id=k_id).first()
        data = KnowledgePointSerializer(self.queryset).data
        if self.queryset:
            with transaction.atomic():
                self.queryset.visit_nums = F('visit_nums') + 1  # 阅读人数更新
                self.queryset.save()  # 更新

        return Response(data=general_message(msg_show="数据请求成功", bean=data),
                        status=status.HTTP_200_OK)
