# -*- coding: utf-8 -*-
from lazy_object_proxy import Proxy as LazyProxy
from typing import List

from events.surveyme.models import Survey
from events.surveyme_integration.models import SurveyHook
from events.v3.errors import ObjectNotFound
from events.v3.perms import check_perm
from events.v3.schemas import HookIn, HookOut
from events.v3.types import SurveyId
from events.v3.utils import set_master_db, get_from_db, get_from_master, get_survey
from events.v3.views.conditions import get_conditions_out
from events.v3.views.subscriptions import get_subscriptions_out


def get_hook_out(hook, conditions, subscriptions) -> HookOut:
    return HookOut(
        id=hook.pk,
        name=hook.name,
        active=hook.is_active,
        conditions=conditions.get(hook.pk),
        subscriptions=subscriptions.get(hook.pk),
    )


def get_hooks_out(survey: Survey) -> List[HookOut]:
    fields = ('pk', 'is_active', 'name')
    params = {
        'conditions': LazyProxy(lambda: get_conditions_out(survey)),
        'subscriptions': LazyProxy(lambda: get_subscriptions_out(survey)),
    }
    qs = (
        get_from_db(SurveyHook).filter(survey=survey)
        .values_list(*fields, named=True)
    )
    out = [
        get_hook_out(it, **params)
        for it in qs
    ]
    return out or None


def get_one_hook_out(survey: Survey, hook_id: int) -> HookOut:
    fields = ('pk', 'is_active', 'name')
    params = {
        'conditions': LazyProxy(lambda: get_conditions_out(survey, hook_id)),
        'subscriptions': LazyProxy(lambda: get_subscriptions_out(survey, hook_id)),
    }
    qs = (
        get_from_db(SurveyHook).filter(survey=survey, pk=hook_id)
        .values_list(*fields, named=True)
    )
    for it in qs:
        return get_hook_out(it, **params)
    raise ObjectNotFound


def create_hook(survey: Survey, data: HookIn) -> int:
    params = {}
    if data.name is not None:
        params['name'] = data.name
    if data.active is not None:
        params['is_active'] = data.active
    hook = SurveyHook.objects.create(survey=survey, **params)
    return hook.pk


def modify_hook(survey: Survey, hook_id: int, data: HookIn) -> int:
    qs = get_from_master(SurveyHook).filter(survey=survey, pk=hook_id)
    params = {}
    if data.name is not None:
        params['name'] = data.name
    if data.active is not None:
        params['is_active'] = data.active
    if params:
        qs.update(**params)
    return hook_id


def delete_hook(survey: Survey, hook_id: int) -> None:
    hook = get_from_db(SurveyHook).get(survey=survey, pk=hook_id)
    hook.delete()


def get_hooks_view(
    request,
    survey_id: SurveyId,
) -> List[HookOut]:
    survey = get_survey(survey_id, user=request.user, orgs=request.orgs, only=['pk'])
    check_perm(request.user, survey)
    return get_hooks_out(survey) or []


def get_hook_view(
    request,
    survey_id: SurveyId, hook_id: int,
) -> HookOut:
    survey = get_survey(survey_id, user=request.user, orgs=request.orgs, only=['pk'])
    check_perm(request.user, survey)
    return get_one_hook_out(survey, hook_id)


def post_hook_view(
    request,
    survey_id: SurveyId,
    data: HookIn,
) -> HookOut:
    survey = get_survey(survey_id, user=request.user, orgs=request.orgs, only=['pk'])
    check_perm(request.user, survey)
    with set_master_db():
        return get_one_hook_out(survey, create_hook(survey, data))


def patch_hook_view(
    request,
    survey_id: SurveyId, hook_id: int,
    data: HookIn,
) -> HookOut:
    survey = get_survey(survey_id, user=request.user, orgs=request.orgs, only=['pk'])
    check_perm(request.user, survey)
    with set_master_db():
        return get_one_hook_out(survey, modify_hook(survey, hook_id, data))


def delete_hook_view(
    request,
    survey_id: SurveyId, hook_id: int,
) -> None:
    survey = get_survey(survey_id, user=request.user, orgs=request.orgs, only=['pk'])
    check_perm(request.user, survey)
    delete_hook(survey, hook_id)
