import json
import copy

from django.http import JsonResponse
from django.db.models import Q
from rest_framework import viewsets, permissions, status, filters
from rest_framework.filters import OrderingFilter

from update.models import Cinema
from update.serializers import *
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework_extensions.cache.mixins import CacheResponseMixin
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page
from django.views.decorators.csrf import csrf_exempt
from django_filters.rest_framework import DjangoFilterBackend
from django.core.cache import cache
from update.utils.get_version import GetVersion
from rest_framework.decorators import action
from update.utils.git_util import GitUtil, GitDbUtil
from update.utils.cmd_extcute import UpdateCommandUtil, UpdateConfigUtil
from update.utils.db_compare import DbCompare
from update.utils.client_util import ClientUtil
# from consumers import UpdateConsumer


# CacheResponseMixin 一定要放第一位
class CinemaViewSet(CacheResponseMixin, viewsets.ModelViewSet):
    # 接口文档的中文注释
    """
    create: 添加测试影院
    list: 获取测试影院列表
    retrieve: 获取某个影院的信息
    update: 更新某个影院的信息
    delete: 删除指定影院
    """
    queryset = Cinema.objects.all()
    serializer_class = CinemaSerializer
    # permission_classes = (permissions.IsAuthenticated,)
    filter_backends = (filters.SearchFilter, DjangoFilterBackend, OrderingFilter)
    ordering_fields = ('ip',)
    search_fields = ('sys_ver',)
    # filter_fields = ('ip',)
    filterset_fields = ('ip',)
    GetVersion().main_process()

    @action(methods=['get'], detail=False)
    @method_decorator(cache_page(60 * 1))
    def refresh(self, request, *args, **kwargs):
        GetVersion().main_process()
        queryset = Cinema.objects.all().order_by('ip')
        serializer = self.get_serializer(instance=queryset, many=True)
        return Response(serializer.data)


class CinemaUserViewSet(CacheResponseMixin, viewsets.ModelViewSet):
    queryset = CinemaUser.objects.order_by('pinyin').all()
    serializer_class = CinemaUserSerializer


class UpdateAlterViewSet(CacheResponseMixin, viewsets.ModelViewSet):
    queryset = UpdateAlter.objects.all()
    serializer_class = UpdateAlterSerializer

# class CinemaSearchAPIView(APIView, CacheResponseMixin):
#     @method_decorator(cache_page(60 * 5))
#     def get(self, request, *args, **kwargs):
#         query_params = request.query_params.dict()
#         print(query_params)
#         query_data = Cinema.objects.filter(
#             Q(ip__contains=query_params.get('ip')) & Q(sys_ver__icontains=query_params.get('version')))
#         serializer = CinemaSerializer(instance=query_data, many=True)
#         return Response(serializer.data, status=status.HTTP_200_OK)

@csrf_exempt
def update_user(request, *args, **kwargs):
    cinema_id = request.GET.dict().get('id')
    user = json.loads(request.body).get('user', '暂无')
    result = Cinema.objects.filter(id=cinema_id).update(user=user)
    return JsonResponse({'result': 'success'} if result == 1 else {'result': 'fail'})


def get_operation_cmd(request):
    update_cmd = UpdateCommandUtil()
    no_sys_cmd = update_cmd.get_no_sys_cmd()
    serializer = UpdateCommandSerializer(instance=no_sys_cmd, many=True)
    return JsonResponse(serializer.data, safe=False)


def get_git_version(request):
    git_db_util = GitDbUtil()
    git_db_util.set_release_to_db()
    git_ver = git_db_util.get_short_version()
    serializer = ReleaseSerializer(instance=git_ver, many=True)
    return JsonResponse(serializer.data, safe=False)


cinema_update_status = dict()


def update_cine(request):
    req = request.GET.dict()
    cinema_ip = req.get('ip')
    # 处理命令格式
    cmd_dict = {}
    cmd_obj = UpdateCommand.objects.filter(is_sys=0).values('id', 'process')
    for cmd in cmd_obj:
        if cmd['process'] in cmd_dict.keys():
            cmd_dict[cmd['process']].append(cmd['id'])
        else:
            cmd_dict[cmd['process']] = [cmd['id']]
    print(cmd_dict)

    # 增加状态
    update_status = {
        'git': {'result': '', 'msg': ''},
        'setup': {'result': '', 'msg': ''},
        'sql': {'result': '', 'msg': ''},
        'teardown': {'result': '', 'msg': ''},
        'config': {'result': '', 'msg': ''},
        'client': {'result': '', 'msg': ''},
    }

    cinema_update_status[cinema_ip] = copy.deepcopy(update_status)

    short_release = req.get('version')
    cmd_list = json.loads(req.get('cmd'))
    print(cinema_ip, short_release, cmd_list)

    # cinema_ip = '172.16.3.88'
    # short_release = '2.0.33.0338_Release'
    # cmd_list = [10, 11, 12, 13, 14, 15, 16, 17, 19, 20]

    # 获取并写入cine.sql
    print('获取并写入cine.sql')
    try:
        cinema_update_status[cinema_ip]['git']['result'] = 'running'
        git_util = GitUtil(short_release)
        git_output = git_util.handle_create_cine()
        cinema_update_status[cinema_ip]['git']['result'] = 'success'
        cinema_update_status[cinema_ip]['git']['msg'] = git_output
    except Exception as e:
        print('git', e)
        cinema_update_status[cinema_ip]['git']['result'] = 'fail'
        cinema_update_status[cinema_ip]['git']['msg'] = str(e)
        return JsonResponse({'result': 'fail', 'ip': cinema_ip, 'msg': str(e)})

    # 执行setup
    print('执行setup')
    try:
        cinema_update_status[cinema_ip]['setup']['result'] = 'running'
        setup_list = list(set(cmd_list) & set(cmd_dict['setup']))
        update_cmd = UpdateCommandUtil()
        result, setup_output = update_cmd.exec_cmd_by_type(cinema_ip, 'setup', setup_list, short_release)
        if result is False:
            raise Exception(setup_output)
        cinema_update_status[cinema_ip]['setup']['result'] = 'success'
        cinema_update_status[cinema_ip]['setup']['msg'] = setup_output
    except Exception as e:
        print('setup', e)
        cinema_update_status[cinema_ip]['setup']['result'] = 'fail'
        cinema_update_status[cinema_ip]['setup']['msg'] = str(e)
        return JsonResponse({'result': 'fail', 'ip': cinema_ip, 'msg': str(e)})

    # 数据库对比
    sql_list = list(set(cmd_list) & set(cmd_dict['sql']))
    if len(sql_list) > 0:
        print('数据库对比')
        try:
            cinema_update_status[cinema_ip]['sql']['result'] = 'running'
            db_compare = DbCompare(cinema_ip, short_release)
            sql_output = db_compare.exec_diff_sql()
            cinema_update_status[cinema_ip]['sql']['result'] = 'success'
            cinema_update_status[cinema_ip]['sql']['msg'] = sql_output
        except Exception as e:
            print('sql', e)
            cinema_update_status[cinema_ip]['sql']['result'] = 'fail'
            cinema_update_status[cinema_ip]['sql']['msg'] = str(e)
            return JsonResponse({'result': 'fail', 'ip': cinema_ip, 'msg': str(e)})

    # 修改设置
    print('执行config(teardown前)')
    try:
        cinema_update_status[cinema_ip]['config']['result'] = 'running'
        config_list = list(set(cmd_list) & set(cmd_dict['config']))
        update_config = UpdateConfigUtil(cinema_ip, config_list, True)
        config_before_output = update_config.exec_config()
        cinema_update_status[cinema_ip]['config']['result'] = 'success'
        cinema_update_status[cinema_ip]['config']['msg'] = config_before_output
    except Exception as e:
        print('config', e)
        cinema_update_status[cinema_ip]['config']['result'] = 'fail'
        cinema_update_status[cinema_ip]['config']['msg'] = str(e)
        return JsonResponse({'result': 'fail', 'ip': cinema_ip, 'msg': str(e)})

    # 执行teardown
    teardown_list = list(set(cmd_list) & set(cmd_dict['teardown']))
    if len(teardown_list) > 0:
        print('执行teardown')
        try:
            cinema_update_status[cinema_ip]['teardown']['result'] = 'running'
            update_cmd = UpdateCommandUtil()
            result, teardown_output = update_cmd.exec_cmd_by_type(cinema_ip, 'teardown', teardown_list, short_release)
            if result is False:
                raise Exception(teardown_output)
            cinema_update_status[cinema_ip]['teardown']['result'] = 'success'
            cinema_update_status[cinema_ip]['teardown']['msg'] = '执行升级脚本:执行成功'
        except Exception as e:
            print('teardown', e)
            cinema_update_status[cinema_ip]['teardown']['result'] = 'fail'
            cinema_update_status[cinema_ip]['teardown']['msg'] = str(e)
            return JsonResponse({'result': 'fail', 'ip': cinema_ip, 'msg': str(e)})

    # 修改设置
    print('执行config(teardown后)')
    try:
        cinema_update_status[cinema_ip]['config']['result'] = 'running'
        config_list = list(set(cmd_list) & set(cmd_dict['config']))
        update_config = UpdateConfigUtil(cinema_ip, config_list, False)
        config_after_output = update_config.exec_config()
        cinema_update_status[cinema_ip]['config']['result'] = 'success'
        cinema_update_status[cinema_ip]['config']['msg'] = config_before_output + '<br/>' + config_after_output
    except Exception as e:
        print('config', e)
        cinema_update_status[cinema_ip]['config']['result'] = 'fail'
        cinema_update_status[cinema_ip]['config']['msg'] = config_before_output + '<br/>' + str(e)
        return JsonResponse({'result': 'fail', 'ip': cinema_ip, 'msg': str(e)})

    # 传输客户端
    client_list = list(set(cmd_list) & set(cmd_dict['client']))
    if len(client_list) > 0:
        print('传输客户端1')
        try:
            client_release = ClientUtil()
            client_release.client_process(cinema_ip, short_release)
            cinema_update_status[cinema_ip]['client']['result'] = 'success'
            cinema_update_status[cinema_ip]['client']['msg'] = '客户端上传成功'
        except Exception as e:
            print('client', e)
            cinema_update_status[cinema_ip]['client']['result'] = 'fail'
            cinema_update_status[cinema_ip]['client']['msg'] = str(e)
            return JsonResponse({'result': 'fail', 'ip': cinema_ip, 'msg': str(e)})

    print(cinema_update_status[cinema_ip])
    return JsonResponse({'result': 'success', 'ip': cinema_ip, 'msg': ''})


# # 测试用接口
def write_git_version_to_db(request):
    git_util = GitDbUtil()
    git_util.set_release_to_db()
    return JsonResponse({'result': 'success'})
#
#
# def write_cine_sql(request):
#     git_util = GitUtil('2.0.33.0338_Release')
#     git_util.handle_create_cine()
#     return JsonResponse({'result': 'success'})
#
#
# def compare_db_structor(request):
#     db_compare = DbCompare('172.16.3.88', '2.0.33.0338_Release')
#     db_compare.exec_diff_sql()
#     return JsonResponse({'result': 'success'})
#
#
# def get_cmd(request):
#     update_cmd = UpdateCommandUtil()
#     update_cmd.connect('172.16.3.112')
#     update_cmd.disconnect()
#     # cmd = update_cmd.get_all_cmd()
#     # cmd_ser = UpdateCommandSerializer(instance=cmd, many=True)
#     # return JsonResponse(data=cmd_ser.data, safe=False)
#     cmd_list = [10, 12, 13, 14, 15, 17, 19, 20]
#     r = update_cmd.get_checked_cmd(cmd_list)
#     print(r)
#     return JsonResponse({'result': 'success'})
#
#
# def setup_cmd(request):
#     update_cmd = UpdateCommandUtil()
#     cmd_list = [10, 11, 12, 13, 14, 15, 16, 17, 19, 20]
#     # exec_cmd_data = update_cmd.get_checked_cmd(cmd_list)
#     update_cmd.exec_cmd_by_type('172.16.3.88', 'setup', cmd_list, '2.0.33.0338_Release')
#     return JsonResponse({'result': 'success'})
#
#
# def teardown_cmd(request):
#     update_cmd = UpdateCommandUtil()
#     cmd_list = [10, 11, 12, 13, 14, 15, 16, 17, 19, 20]
#     # exec_cmd_data = update_cmd.get_checked_cmd(cmd_list)
#     update_cmd.exec_cmd_by_type('172.16.3.88', 'teardown', cmd_list, '2.0.33.0338_Release')
#     return JsonResponse({'result': 'success'})
#
#
# def get_client(request):
#     client_release = ClientUtil()
#     client_release.client_process('172.16.3.88', '2.0.33.0338_Release')
#     return JsonResponse({'result': 'success'})