import datetime

from django.conf import settings

from .api import ContestAPI, ContestPrivateAPI, ContestTVMApi
from intranet.femida.src.contest.models import Contest, ContestProblem
from django.utils.dateparse import parse_datetime


def _fetch_problems_by_standings(contest_id, data):
    problems = []
    for item in data:
        url = '{}contest/{}/problems/{}/'.format(settings.CONTEST_URL, contest_id, item['title'])
        problems.append({
            'name': item['name'],
            'title': item['title'],
            'url': url,
        })
    return problems


def _fetch_participation_data(contest_id, row, participation, problems):
    data = {
        'contest': {
            'id': contest_id,
            'url': get_contest_url(contest_id),
        },
        'participation': {
            'id': row['participantInfo']['id'],
            'login': row['participantInfo']['login'],
            'name': row['participantInfo']['name'],
            'start_time': participation['participantStartTime'],
            'finish_time': participation['participantFinishTime'],
        },
        'results': {
            'score': row['score'],
            'problems': [],
        }
    }
    for i, problem in enumerate(problems):
        problem_info = dict(problem)
        problem_info['status'] = row['problemResults'][i]['status']
        data['results']['problems'].append(problem_info)
    return data


def get_contest_url(contest_id):
    return '{}contest/{}'.format(settings.CONTEST_URL, contest_id)


def get_contest_results_by_participants(contest_id, participant_ids=None):
    """
    :param contest_id: id контеста
    :param participant_ids: множество participant_id, для которых нужны результаты
    :return: Маппинг participant_id -> results для participants, которые завершили контест
    """
    data = ContestAPI.get_contest_standings(contest_id)
    problems = _fetch_problems_by_standings(contest_id, data['titles'])

    result = {}
    for row in data['rows']:
        participant_id = row['participantInfo']['id']
        if participant_ids is not None and participant_id not in participant_ids:
            continue

        participation = ContestAPI.get_participation(
            contest_id=contest_id,
            participant_id=participant_id,
        )

        # Если участие не завершено, то ничего не делаем
        if participation['contestState'] != 'FINISHED':
            continue

        participation_data = _fetch_participation_data(
            contest_id=contest_id,
            row=row,
            participation=participation,
            problems=problems,
        )
        result[participant_id] = participation_data
    return result


def register_to_contest(contest_id, login):
    return ContestAPI.create_participation(contest_id, login)


def register_to_contest_by_answer_id(contest_id, answer_id, passcode):
    ContestPrivateAPI.register_by_answer_id(contest_id, answer_id, passcode)


def get_participant_ids_by_answer_ids(answer_ids):
    return ContestPrivateAPI.get_participant_ids(answer_ids)


def sync_contests_meta_info():
    contest_list = Contest.objects.all()
    for contest in contest_list:
        sync_contest(contest)


def sync_contest(contest):
    contest_info = ContestTVMApi.get_contest_info(contest.contest_id)['result']
    update_contest(contest, contest_info['contest'])
    update_problems(contest, contest_info['problems'])


def update_contest(contest, contest_from_api):
    is_infinite = False
    finish_time = None
    start_time = parse_datetime(contest_from_api['startTime'])
    duration = int(contest_from_api['duration'])
    if duration == 0:
        is_infinite = True
    else:
        finish_time = start_time + datetime.timedelta(seconds=duration)

    contest.name = contest_from_api['name']
    contest.url = get_contest_url(contest.contest_id)
    contest.started_at = start_time
    contest.finishing_at = finish_time
    contest.is_infinite = is_infinite
    contest.save()


def update_problems(contest, problem_list_from_api):
    for problem_from_api in problem_list_from_api:
        femida_problem = ContestProblem.objects.filter(
            contest=contest,
            problem_origin_id=problem_from_api['id']
        ).first()
        statement = ContestTVMApi.get_problem_file(problem_id=problem_from_api['id'],
                                                   path=problem_from_api['pathToHtmlText'])
        if femida_problem is None:
            femida_problem = ContestProblem()

        femida_problem.contest = contest
        femida_problem.problem_origin_id = problem_from_api['id']
        femida_problem.name = problem_from_api['name']
        femida_problem.alias = problem_from_api['alias']
        femida_problem.max_score = problem_from_api['maxScore']
        femida_problem.type = problem_from_api['type']
        femida_problem.html_text = statement
        femida_problem.save()
