import hashlib
import time

from django.conf import settings
from gm_types.ascle import ERROR
from helios.rpc.exceptions import RPCFaultException

from utils.base import APIView
from utils.channel_package_tools import ChannelPackage
from utils.logger import error_logger
from .tasks import version_release_task, channel_build, channel_build_one


def get_md5_value(src):
    md5 = hashlib.md5()
    md5.update(src)
    md5_digest = md5.hexdigest()
    return md5_digest


class Vendor(APIView):
    def get(self, request):
        """
        获取渠道商列表
        :param request:
        :return:
        """
        query = request.GET.get('q', '')
        page = int(request.GET.get('page', 1))
        offset = int(request.GET.get('offset', 30))

        data = request.rpc.origin['endpoint'](
            query=query, start=(page - 1) * offset, offset=offset
        ).unwrap()
        return data


class ChannelList(APIView):
    def get(self, request):
        """
        渠道列表
        :param request:
        :return:
        """
        page = int(request.GET.get('page', 1))
        limit = int(request.GET.get('limit', 10))
        filters = self.handle_filter(request.GET.get('filter', ""))
        try:
            channel_list = self.rpc['venus/sun/channel_build/channel/list'](
                offset=(page-1)*limit, limit=limit, filters=filters
            ).unwrap()
        except Exception as e:
            error_logger.error(u'获取渠道列表失败：%s', e)
            raise e
        data = {'total': channel_list.get('total', 0)}
        url = settings.APK_DOMAIN + settings.APK_BUILD_DIR + '/' + settings.APK_RELEASE_DIR + \
              "/{name}/gm_alpha_{name}.apk?t={timestamp}"
        channels = [
            {
                'id': data.get('id'),
                'name': data.get('name'),
                'url_name': data.get('url_name'),
                'pack': data.get('pack'),
                'released_version': data.get('released_version'),
                'download_url': url.format(name=data.get('url_name'), timestamp=time.time()),
            }
            for data in channel_list.get('data', [])]
        data.update({'channel': channels})
        return self.write_success(message='获取渠道列表成功', data=data)


class ChannelVersionList(APIView):
    def get(self, request):
        """
        :param request:
        :return:
        """
        channel_id = request.GET.get('channel_id')
        page = int(request.GET.get('page', 1))
        limit = int(request.GET.get('limit', 10))
        try:
            channel_list = self.rpc['venus/sun/channel_build/channel_version/list'](
                offset=(page-1)*limit, limit=limit, channel_id=channel_id
            ).unwrap()
        except Exception as e:
            error_logger.error(u'获取渠道列表失败：%s', e)
            raise e
        data = {'total': channel_list.get('total', 0)}
        url = settings.APK_DOMAIN + settings.APK_BUILD_DIR + "/{version}/{name}/gm_alpha_{name}.apk?t={timestamp}"
        channels = [
            {
                'version_id': data.get('version_id'),
                'channel_id': data.get('channel_id'),
                'version': data.get('version'),
                'name': data.get('name'),
                'url_name': data.get('url_name'),
                'packed_time': data.get('packed_time'),
                'packed': data.get('packed'),
                'release_time': data.get('release_time'),
                'is_released': data.get('is_released'),
                'download_url': url.format(
                    version=data.get('version'), name=data.get('url_name'), timestamp=time.time()),
            }
            for data in channel_list.get('data', [])]
        data.update({'channel': channels})
        return self.write_success(message='获取渠道列表成功', data=data)


class Channel(APIView):
    def get(self, request):
        """
        渠道详情
        :param request:
        :return:
        """
        channel_id = request.GET.get('channel_id')
        if not channel_id:
            error_logger.error(u'参数不完整')
            return self.write_fail(code=ERROR.ARG_MISS, message='参数不完整')
        try:
            channel_data = self.rpc['venus/sun/channel_build/channel/get'](
                id=channel_id
            ).unwrap()
        except Exception as e:
            error_logger.error(u'获取渠道详情失败：%s', e)
            raise e
        channel = {
            'id': channel_data.get('id'),
            'name': channel_data.get('name'),
            'url_name': channel_data.get('url_name'),
            'pack': channel_data.get('pack'),
            'type': channel_data.get('type'),
            'released_version': channel_data.get('released_version'),
        }
        return self.write_success(message='获取渠道详情成功', data=channel)

    def post(self, request):
        """
        渠道创建 / 编辑
        :param request:
        :return:
        """
        channel_id = request.POST.get('id', None)
        channel_name = request.POST.get('name', '')
        url_name = request.POST.get('url_name', '')
        auto_pack = request.POST.get('pack', True)
        channel_type = request.POST.get('type', 2)
        if not all([channel_name, url_name, auto_pack, channel_type]):
            error_logger.error(u'参数不完整')
            return self.write_fail(code=ERROR.ARG_MISS, message='参数不完整')
        if channel_id:
            channel = self.rpc['venus/sun/channel_build/channel/get'](
                id=channel_id
            ).unwrap()
        else:
            channel = {}
        data = dict()
        if channel_name:
            data.update({'name': channel_name})
        if url_name:
            data.update({'url_name': url_name})
        if auto_pack:
            data.update({'pack': auto_pack})
        if channel_type:
            data.update({'type': channel_type})
        try:
            resp = self.rpc['venus/sun/channel_build/channel/edit'](
                id=channel_id, data=data
            ).unwrap()
        except Exception as e:
            error_logger.error('操作失败%s', e)
            return self.write_fail(message='路径名不能重复', code=-1)
        version = resp.get('version', '')
        if version and channel.get('url_name') != url_name:
            channel_build_one.delay(version, url_name)
        return self.write_success(message='操作成功', data={})


class ChannelPacked(APIView):
    def post(self, request):
        """
        当前版本的渠道包发布
        :param request:
        :return:
        """
        version_id = request.POST.get('version_id')
        channel_id = request.POST.get('channel_id')
        if not all([channel_id, version_id]):
            error_logger.error(u'参数不完整')
            return self.write_fail(code=ERROR.ARG_MISS, message='参数不完整')

        channel = self.rpc['venus/sun/channel_build/channel/get'](
            id=channel_id
        ).unwrap()
        version = self.rpc['venus/sun/channel_build/version/get'](
            id=version_id
        ).unwrap()
        ChannelPackage.publish_apk(channel.get('url_name'), version.get('version'))
        try:
            self.rpc['venus/sun/channel_build/version/release'](
                version_id=version_id, channel_ids=[channel_id]
            ).unwrap()  #发布
        except RPCFaultException as e:
            error_logger.error(u'发布失败：%s', e)
            return self.write_fail(code=-1, message='发布失败！')
        return self.write_success(data={}, message='发布成功！')


class VersionList(APIView):
    def get(self, request):
        """
        所有版本列表
        :param request:
        :return:
        """
        page = int(request.GET.get('page', 1))
        offset = int(request.GET.get('limit', 10))
        try:
            version_list = self.rpc['venus/sun/channel_build/version/list'](
                offset=(page-1)*offset, limit=offset
            ).unwrap()
        except Exception as e:
            error_logger.error(u'获取版本列表失败：%s', e)
            raise e
        data = {'total': version_list.get('total', 0)}
        versions = [
            {
                'version_id': item.get('id'),
                'version': item.get('version'),
                'md5': item.get('md5'),
                'release_time': item.get('release_time'),
            } for item in version_list.get('data', [])
        ]
        data.update({'data': versions})
        return self.write_success(data=data)


class VersionChannelList(APIView):
    def get(self, request):
        page = int(request.GET.get('page', 1))
        offset = int(request.GET.get('limit', 10))
        version_id = request.GET.get('version_id', 10)
        try:
            version_list = self.rpc['venus/sun/channel_build/version_channel/list'](
                offset=(page-1)*offset, limit=offset, version_id=version_id
            ).unwrap()
        except Exception as e:
            error_logger.error(u'获取版本列表失败：%s', e)
            raise e
        data = {'total': version_list.get('total', 0)}
        url = settings.APK_DOMAIN + settings.APK_BUILD_DIR + "/{version}/{name}/gm_alpha_{name}.apk?t={timestamp}"
        sup_url = ChannelPackage.apk_url(channel='', version=version_list.get('version')) + '?t={timestamp}'
        versions = {
            'version': [{
                'channel_id': item.get('channel_id'),
                'version_id': item.get('version_id'),
                'version': item.get('version'),
                'name': item.get('name'),
                'packed_time': item.get('packed_time'),
                'packed': item.get('packed'),
                'download_url': url.format(
                    version=item.get('version'), name=item.get('url_name'), timestamp=time.time()),
                'release_time': item.get('release_time'),
                'is_released': item.get('is_released'),
            } for item in version_list.get('data', [])],
            'base_apk_url': sup_url.format(timestamp=time.time()),
        }
        data.update({'data': versions})
        return self.write_success(data=data)


class VersionDetailUpdate(APIView):
    def get(self, request):
        """
        版本详情
        :param request:
        :return:
        """
        version_id = request.GET.get('version_id')
        if not version_id:
            error_logger.error(u'参数不完整')
            return self.write_fail(code=ERROR.ARG_MISS, message='参数不完整')
        version_info = self.rpc['venus/sun/channel_build/version/get'](
            id=version_id
        ).unwrap()
        data = {
            'id': version_info.get('id'),
            'version': version_info.get('version'),
            'release_time': version_info.get('release_time'),
            'md5': version_info.get('md5'),
            'description': version_info.get('description'),
        }
        return self.write_success(data=data, message='操作成功')

    def post(self, request):
        """
        版本信息编辑 只允许修改描述
        :param request:
        :return:
        """
        version_id = request.POST.get('id')
        version = request.POST.get('version')
        md5 = request.POST.get('md5')
        release_time = request.POST.get('release_time')
        desc = request.POST.get('description')
        if not version_id:
            error_logger.error(u'参数不完整')
            return self.write_fail(code=ERROR.ARG_MISS, message='参数不完整')
        data = dict()
        if version:
            data.update({'version': version})
        if release_time:
            data.update({'release_time': release_time})
        if desc:
            data.update({'description': desc})
        if md5:
            data.update({'md5': md5})
        try:
            self.rpc['venus/sun/channel_build/version/edit'](
                id=version_id, data=data
            ).unwrap()
        except Exception as e:
            error_logger.error(e)
            return self.write_fail(code=-1, message='操作失败')
        return self.write_success(data={}, message='操作成功')


class BatchPublishVersion(APIView):
    def post(self, request):
        """
        批量发布 并邮件通知
        :param request:
        :return:
        """
        version_id = request.POST.get('version_id')
        if not version_id:
            error_logger.error(u'参数不完整')
            return self.write_fail(code=ERROR.ARG_MISS, message='参数不完整')
        try:
            # 获取当前版本所有已打包渠道
            channel_info = self.rpc['venus/sun/channel_build/version/get_channel_info'](
                version_id=version_id
            ).unwrap()
        except RPCFaultException as e:
            error_logger.error(u'获取渠道失败%s', e)
            return self.write_fail(code=-1, message='获取渠道失败！')
        packed_channels = list()
        for item in channel_info.get('data', []):
            if item.get('pack', False):
                packed_channels.append(item)
        version_release_task.delay(
            packed_channels, version_id=version_id, version=channel_info.get('version')
        )
        return self.write_success(data={}, message='操作成功')


class VersionCreate(APIView):
    def post(self, request):
        """
        版本创建  供脚本使用
        :param request:
        :return:
        """
        apk = request.FILES.get('file').read()
        file_md5 = get_md5_value(apk)
        version = request.POST.get('version')
        md5 = request.POST.get('md5')
        if md5 != file_md5:
            raise Exception('md5校验失败, 文件md5{}'.format(file_md5))
        data = dict()
        if version:
            data.update({'version': version})
        if md5:
            data.update({'md5': md5})
        try:
            version_id = self.rpc['venus/sun/channel_build/version/edit'](
                data=data
            ).unwrap()
        except RPCFaultException as e:
            error_logger.error('创建版本失败：%s', e)
            raise Exception('创建版本失败！')
        channel_info = self.rpc['venus/sun/channel_build/version/get_channel_info'](
            version_id=version_id
        ).unwrap()  # 所有渠道的url_name: list()
        url_names = []
        for item in channel_info.get('data', []):
            if item.get('pack', False):
                url_names.append(item.get('url_name'))
        channel_build.delay(version, url_names, apk)
        return {'success': True}
