# -*- coding: utf-8 -*-
"""
Created on Jan 19, 2018

@author: noob
"""

from .forms import UploadAPKForm, UploadTestsForm
from common.util.clients import MDSClient
from common.views import get_common
from common.models import Job
from mobilepage.models import MobileJob
from copy import deepcopy
from datetime import datetime
from django.http import HttpResponse
from django.shortcuts import render_to_response
from django.template import RequestContext
from django_yauth.decorators import yalogin_required
import yaml
import uuid
import logging
import json
import re
import requests
from .models import APK, APKTests
from django.views.decorators.csrf import csrf_exempt

config = {
    'android': {
        'volta_options': {
            'phone': {
                'test_apps': ['', ''],
                'cleanup_apps': ['', ''],
                'test_class': '',
                'test_package': '',
                'test_runner': 'android.support.test.runner.AndroidJUnitRunner'
            },
            'uploader': {
                'enabled': True,
                'task': '',
                'name': '',
                'dsc': '',
                'component': ''
            }
        },
    },
    'uploader': {
            'enabled': True,
            'package': 'yandextank.plugins.DataUploader',
            'task': '',
            'job_name': '',
            'job_dsc': '',
            'component': '',
            'meta': {
                'use_tank': '',
            }
    },
    'telegraf': {
            'enabled': True,
            'package': 'yandextank.plugins.Telegraf',
            'config': 'https://github.yandex-team.ru/raw/load/pogoda-performance/master/monitoring-htc.xml'
    }
}

config_ios = {
    'config': {
        'artifacts_url': 'hhhh',
        'volta_config': {
            'phone': {
                'enabled': True,
                'source': '0x6382910F98C26',
                'type': 'iphone'
            },
            'uploader': {
                'dsc': 'apple garden dsc',
                'enabled': True,
                'name': 'apple garden test',
                'task': 'jjjjjj'
            },
            'volta': {
                'enabled': True,
                'source': '/dev/cu.usbmodem1411',
                'type': 'stm32'
            }
        }
    },
    'demands': {
        'executor_type': 'fastlane,',
        'host_name': 'mac04k.volta.yandex.net'
    }
}


@yalogin_required
def mobilefirestarter(request):
    error = request.POST.get('error', '')

    if request.POST.get('api_handle'):
        return [{'success': not bool(error), 'error': error}]

    user = request.yauser
    common_data = get_common(request)

    apk_upload_form = UploadAPKForm()
    tests_upload_form = UploadTestsForm()

    return render_to_response('mobilefirestarter.html',
                              {
                                  'common': common_data,
                                  'config': yaml.dump(config),
                                  'error': error,
                                  'apk_files': list(APK.objects.filter(author=user.login)),
                                  'tests_files': list(APKTests.objects.filter(author=user.login)),
                                  'apk_upload_form': apk_upload_form,
                                  'tests_upload_form': tests_upload_form,
                                  'recent_user_tasks': get_user_recent_tasks(user.login),
                                  'recent_user_tanks': get_user_recent_tanks(user.login),
                                  'pagename': 'mobilefirestarter',
                              },
                              context_instance=RequestContext(request))


def get_user_recent_tasks(login, limit=2):
    """
    :param login: user login
    :param limit: how many tasks to return
    """
    try:
        tasks = [j.task for j in MobileJob.objects.filter(person=login).order_by('-n')[:100]]
        distinct_tasks = []
        for task in tasks:
            if task not in distinct_tasks:
                distinct_tasks.append(task)
    except:
        logging.exception('Could not get tasks for user {} due to:'.format(login))
        distinct_tasks = []
    return distinct_tasks[:limit]


def get_user_recent_tanks(login, limit=2):
    """
    :param login: user login
    :param limit: how many tasks to return
    """
    try:
        jobs = Job.objects.filter(person=login).order_by('-n')[:100]
        tanks = [
            j.config.get('uploader', {}).get('meta', {}).get('use_tank', '')
            or j.config.get('meta', {}).get('use_tank', '')
            for j in jobs
        ]
        distinct_tanks = []
        for tank in tanks:
            if tank and tank not in distinct_tanks:
                distinct_tanks.append(tank)
    except:
        logging.exception('Could not get tasks for user {} due to:'.format(login))
        distinct_tanks = []
    return distinct_tanks[:limit]


@yalogin_required
def upload_apk(request):
    form = UploadAPKForm(request.POST, request.FILES)
    path = ''
    dsc = ''
    if form.is_valid():
        try:
            user = request.yauser
            now = datetime.now()
            dsc = request.POST.get('title') or request.FILES['file']._name
            uniq = uuid.uuid4().hex
            size = request.FILES['file']._size
            client = MDSClient(namespace='load-artefact')
            resp = client.post(
                uniq,
                request.FILES['file'].file,
                size,
            )
            logging.error(resp)
            error = resp['error']
            assert resp['success']
            APK.objects.create(
                path=resp['url'],
                author=user.login,
                created_at=now,
                dsc=dsc,
                size=int(size),
            )
            path = resp['url']
        except AssertionError:
            logging.exception('Could not upload apk_file due to:')
            error = 'Не удалось залить апк {}'.format(resp['error'])
        except:
            logging.exception('Could not upload apk_file due to:')
            error = 'Не удалось залить апк :('
    else:
        error = 'Файл-то не выбран'

    return HttpResponse(json.dumps({'success': bool(not error),
                                    'error': error,
                                    'dsc': dsc,
                                    'path': path
                                    }), content_type='application/json')


@yalogin_required
def upload_tests(request):
    form = UploadTestsForm(request.POST, request.FILES)
    path = ''
    dsc = ''
    if form.is_valid():
        try:
            user = request.yauser
            now = datetime.now()
            dsc = request.POST.get('title') or request.FILES['file']._name
            uniq = uuid.uuid4().hex
            size = request.FILES['file']._size
            client = MDSClient(namespace='load-artefact')
            resp = client.post(
                uniq,
                request.FILES['file'].file,
                size,
            )
            error = resp['error']
            assert resp['success']
            APKTests.objects.create(
                path=resp['url'],
                author=user.login,
                created_at=now,
                dsc=dsc,
                size=int(size),
            )
            path = resp['url']
        except AssertionError:
            logging.exception('Could not upload tests_file due to:')
            error = 'Не удалось залить тестовую апк ' + resp['error']
        except:
            logging.exception('Could not upload tests_file due to:')
            error = 'Не удалось залить тестовую апк :('
    else:
        error = 'Файл-то не выбран'

    return HttpResponse(json.dumps({'success': bool(not error),
                                    'error': error,
                                    'dsc': dsc,
                                    'path': path
                                    }), content_type='application/json')


@yalogin_required
@csrf_exempt
def start(request):
    error = ''

    logging.error(request.POST)

    try:
        package = request.POST.get('package_input')
        assert package, 'package field is mandatory'

        test_classes = request.POST.get('test_classes_input')
        assert test_classes, 'test_classes field is mandatory'

        test_package = request.POST.get('test_package_input')
        assert test_package, 'test_package field is mandatory'

        test_runner = request.POST.get('test_runner_input')
        assert test_runner, 'test_runner field is mandatory'

        apk = request.POST.get('apk_select')
        assert apk, 'apk field is mandatory'

        apk_test = request.POST.get('tests_select')
        assert apk_test, 'apk_test field is mandatory'

        task = request.POST.get('task_input')
        assert package, 'task field is mandatory'

        tank = request.POST.get('tank_input')
        assert test_classes, 'tank field is mandatory'

        job_dsc = request.POST.get('job_dsc', '')

    except AssertionError as ae:
        logging.error('Start problems', exc_info=True)
        return HttpResponse(json.dumps({
            'success': False,
            'error': ae,
        }), content_type='application/json')

    jobs_data = ''

    api_url = 'https://lunapark.yandex-team.ru/api/v2/jobs/'

    for test_class in test_classes.split(','):
        test_class = test_class.strip()
        new_config = deepcopy(config)
        new_config['android']['volta_options']['phone']['test_apps'] = [apk, apk_test]
        new_config['android']['volta_options']['phone']['cleanup_apps'] = [package, test_package]
        new_config['android']['volta_options']['phone']['test_class'] = test_class
        new_config['android']['volta_options']['phone']['test_package'] = test_package
        new_config['android']['volta_options']['phone']['test_runner'] = test_runner
        new_config['android']['volta_options']['uploader']['task'] = task
        new_config['android']['volta_options']['uploader']['name'] = test_class
        new_config['android']['volta_options']['uploader']['dsc'] = job_dsc
        new_config['android']['volta_options']['uploader']['component'] = test_class
        new_config['uploader']['task'] = task
        new_config['uploader']['job_name'] = test_class
        new_config['uploader']['job_dsc'] = job_dsc
        new_config['uploader']['component'] = test_class
        new_config['uploader']['meta']['use_tank'] = tank

        resp = requests.post(
            api_url,
            data=json.dumps({'config': yaml.dump(new_config)}),
            verify=False,
            headers={'Content-Type': 'application/json'}
        )

        jobs_data += resp.content

    job_ids = re.findall('\"resource_uri\": \"/api/v2/jobs/(\d+)/\"', jobs_data)

    return HttpResponse(json.dumps({
        'success': bool(not error),
        'error': error,
        'jobs': ', '.join(job_ids),
        'tank': tank,
    }), content_type='application/json')


@yalogin_required
def mobilefirestarter_ios(request):
    error = request.POST.get('error', '')

    if request.POST.get('api_handle'):
        return [{'success': not bool(error), 'error': error}]

    user = request.yauser
    common_data = get_common(request)

    return render_to_response('mobilefirestarter_ios.html',
                              {
                                  'common': common_data,
                                  'config': yaml.dump(config),
                                  'error': error,
                                  'recent_user_tasks': get_user_recent_tasks(user.login),
                                  'pagename': 'mobilefirestarter',
                              },
                              context_instance=RequestContext(request))


@yalogin_required
@csrf_exempt
def start_ios(request):
    error = ''

    logging.error(request.POST)

    try:
        url = request.POST.get('url_input')
        assert url, 'url field is mandatory'
        task = request.POST.get('task_input', 'LOAD-272')

    except AssertionError as ae:
        logging.error('Problems with start_ios', exc_info=True)
        return HttpResponse(json.dumps({
            'success': False,
            'error': ae,
        }), content_type='application/json')

    # FIXME: проковырять работающие дырки до lpq.yandex-team.ru
    api_url = 'http://sas1-941f7545b715.qloud-c.yandex.net:80/enqueue.json'

    new_config_ios = deepcopy(config_ios)
    new_config_ios['config']['artifacts_url'] = url
    new_config_ios['config']['volta_config']['uploader']['task'] = task

    try:
        resp = requests.post(
            api_url,
            data=json.dumps(new_config_ios),
            verify=False,
            headers={'Content-Type': 'application/json'}
        )
        logging.error(resp.content)
        resp.raise_for_status()
    except (requests.exceptions.ConnectionError, requests.exceptions.Timeout) as exc:
        error = repr(exc)
    except Exception as exc:
        error = repr(exc)

    return HttpResponse(json.dumps({
        'success': bool(not error),
        'error': error,
    }), content_type='application/json')
