# -*- coding=utf-8 -*-
import re
import requests
from urllib.parse import urlparse

from django.db.models import Q
from django.http import HttpResponse
from django.http import QueryDict

from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi
from rest_framework import status
from rest_framework.response import Response

from common.utils.views import BaseApiView
from console.contract.serialisers import ContractInfoSerializer
from console.contract.filters import ContractFilter
from common.utils.serializers import serializer_assembly
from common.utils.return_structure import general_message
from console.contract.repositories import contract_queryset, contract_info
from common.utils.return_structure import error_message
from console.contract.services import contract_service
from common.utils.service_code import SERVICE_ERROR


class ContractLView(BaseApiView):
    queryset = contract_queryset.get_all_contract_info
    serializer_class = ContractInfoSerializer
    filter_class = ContractFilter

    @swagger_auto_schema(operation_description="合同列表",
                         manual_parameters=[
                             openapi.Parameter("page",
                                               openapi.IN_QUERY,
                                               description="页码",
                                               type=openapi.TYPE_INTEGER,
                                               required=False),
                             openapi.Parameter("page_size",
                                               openapi.IN_QUERY,
                                               description="每页数量",
                                               type=openapi.TYPE_INTEGER,
                                               required=False),
                             openapi.Parameter("id",
                                               openapi.IN_QUERY,
                                               description="ID",
                                               required=False,
                                               type=openapi.TYPE_INTEGER),
                             openapi.Parameter("type",
                                               openapi.IN_QUERY,
                                               description="type",
                                               required=False,
                                               type=openapi.TYPE_INTEGER),
                         ],
                         tags=["Contract"],
                         responses={
                             status.HTTP_200_OK:
                                 serializer_assembly(ContractInfoSerializer,
                                                     many=True)
                         })
    def get(self, request, *args, **kwargs):
        id = request.GET.get('id')
        if id:
            self.queryset = self.queryset.filter(
                contract_party_id__in=self.enterprise_ids)
            defect = self.get_queryset().filter(id=id).first()
            data = self.get_serializer(defect).data
            return Response(data=general_message(msg_show="获取详细信息成功",
                                                 bean=data),
                            status=status.HTTP_200_OK)
        else:
            if self.is_customer:
                queryset = self.filter_queryset(self.get_queryset().filter(
                    customer_id=self.customer.id).order_by(
                    "-id", "-created_time"))
            else:
                self.queryset = self.queryset.filter(
                    Q(contract_party_id__in=self.enterprise_ids) |
                    Q(organization_id__in=self.enterprise_ids))
                queryset = self.filter_queryset(self.get_queryset().order_by(
                    "-id", "-created_time"))
            page = self.paginate_queryset(queryset)
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

    @swagger_auto_schema(operation_description="添加合同",
                         request_body=ContractInfoSerializer,
                         tags=['Contract'],
                         responses={
                             status.HTTP_200_OK:
                                 serializer_assembly(ContractInfoSerializer)
                         })
    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)

    @swagger_auto_schema(operation_description="删除合同",
                         request_body=ContractInfoSerializer,
                         tags=['Contract'],
                         responses={
                             status.HTTP_200_OK:
                                 serializer_assembly(ContractInfoSerializer)
                         })
    def delete(self, request, *args, **kwargs):
        contract_id = kwargs.get("id")
        try:
            contract_service.delete_contract(contract_id)
            data = general_message(msg='success', msg_show='删除成功')
            return Response(data, status=status.HTTP_200_OK)
        except Exception as e:
            data = general_message(msg='fail', msg_show=e)
            return Response(data, status=status.HTTP_400_BAD_REQUEST)

    @swagger_auto_schema(operation_description="修改合同详情",
                         request_body=ContractInfoSerializer,
                         tags=['Contract'],
                         responses={
                             status.HTTP_200_OK:
                                 serializer_assembly(ContractInfoSerializer)
                         })
    def put(self, request, *args, **kwargs):
        contract_id = kwargs.get('id')
        if not contract_id:
            data = error_message(code=SERVICE_ERROR,
                                 msg="缺少合同id",
                                 msg_show="服务端异常")
            return Response(data, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
        instance = contract_info.get_equipment_info(contract_id)
        serializer = self.get_serializer(instance, request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(data=general_message(msg_show="数据修改成功",
                                             bean=serializer.data),
                        status=status.HTTP_200_OK)


class PDFStreamView(BaseApiView):
    def dispatch(self, request, path, *args, **kwargs):
        self.args = args
        self.kwargs = kwargs
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
        self.headers = self.default_response_headers
        try:
            self.initial(request, *args, **kwargs)
            extra_requests_args = {
                "headers": {
                    "Referer": "http://oa.epkeeper.com/"
                },
            }
            remote_url = "http://oss-cm.epkeeper.com/{}".format(path)
            response = self.proxy_view(request, remote_url,
                                       extra_requests_args)
        except Exception as exc:
            response = self.handle_exception(exc)
        self.response = self.finalize_response(request, response, *args,
                                               **kwargs)
        return self.response

    def proxy_view(self, request, url, requests_args=None):
        params = request.GET.copy()

        if 'data' not in requests_args:
            requests_args['data'] = request.body
        if 'params' not in requests_args:
            requests_args['params'] = QueryDict('', mutable=True)

        params.update(requests_args['params'])

        requests_args['params'] = params
        response = requests.request(request.method, url, **requests_args)

        proxy_response = HttpResponse(response.content,
                                      status=response.status_code)

        excluded_headers = set(
            ['connection', 'keep-alive', 'content-encoding', 'content-length'])
        for key, value in response.headers.items():
            if key.lower() in excluded_headers:
                continue
            elif key.lower() == 'location':
                proxy_response[key] = self.make_absolute_location(
                    response.url, value)
            else:
                proxy_response[key] = value
        proxy_response["Content-Type"] = "application/pdf"

        return proxy_response

    def make_absolute_location(self, base_url, location):
        absolute_pattern = re.compile(r'^[a-zA-Z]+://.*$')
        if absolute_pattern.match(location):
            return location

        parsed_url = urlparse(base_url)

        if location.startswith('//'):
            return parsed_url.scheme + ':' + location

        elif location.startswith('/'):
            return parsed_url.scheme + '://' + parsed_url.netloc + location

        else:
            return parsed_url.scheme + '://' + parsed_url.netloc + \
                   parsed_url.path.rsplit('/', 1)[0] + '/' + location

    def get_headers(self, environ):
        headers = {}
        for key, value in environ.items():
            if key.startswith('HTTP_') and key != 'HTTP_HOST':
                headers[key[5:].replace('_', '-')] = value
            elif key in ('CONTENT_TYPE', 'CONTENT_LENGTH'):
                headers[key.replace('_', '-')] = value

        return headers
