from typing import Any, Dict, List

from staff.lib.utils.qs_values import extract_related
from staff.umbrellas.models import UmbrellaAssignment

from staff.person_profile.controllers.blocks.abstract_block import AbstractBlock


def get_person_umbrellas(logins: List[str]) -> Dict[str, List[Dict[str, Any]]]:
    assignment_fields = {
        'person__login',
        'umbrella__id',
        'umbrella__name',
        'umbrella__issue_key',
        'umbrella__goal_id',
        'engagement',
        'engaged_from',
        'engaged_to',
    }

    assignments_qs = (
        UmbrellaAssignment.all_assignments
        .active()
        .filter(person__login__in=logins)
        .order_by('-engagement')
        .values(*assignment_fields)
    )

    person_umbrellas = {}

    for assignment in assignments_qs:
        assignment['umbrella'] = extract_related(assignment, 'umbrella', pop=True)

        if assignment['umbrella']['id'] is None:
            assignment['umbrella'] = None

        person_umbrellas.setdefault(assignment.pop('person__login'), []).append(assignment)

    missing_logins = logins - person_umbrellas.keys()
    person_umbrellas.update(
        {login: [] for login in missing_logins},
    )

    return person_umbrellas


class UmbrellasBlock(AbstractBlock):
    fields = {
        'id',
        'login',
    }

    def get_data(self):
        return {'umbrellas': self._get_umbrellas()}

    def _get_umbrellas(self) -> List[Dict[str, Any]]:
        login = self.data['login']
        if login not in self.cache.get('person_umbrellas', {}):
            self.cache.setdefault('person_umbrellas', {}).update(get_person_umbrellas([login]))

        return self.cache['person_umbrellas'][login]
