import attr
from decimal import Decimal
from typing import List, Any, Dict


@attr.s(auto_attribs=True)
class DepartmentAction:
    @attr.s(auto_attribs=True)
    class NameChange:
        name: str or None = None
        name_en: str or None = None
        hr_type: str or None = None
        is_correction: str or None = None

    @attr.s(auto_attribs=True)
    class AdministrationChange:
        chief: int or None = None
        deputies: List[int] or None = None

    @attr.s(auto_attribs=True)
    class HierarchyChange:
        parent: int or None = None
        fake_parent: str or None = None
        changing_duties: bool or None = None

    @attr.s(auto_attribs=True)
    class TechnicalChange:
        position: int or None = None
        kind: int or None = None
        category: str or None = None
        code: str or None = None
        allowed_overdraft_percents: Decimal or None = None

    delete: bool = False
    fake_id: str or None = None
    id: int or None = None
    name: NameChange or None = None
    administration: AdministrationChange or None = None
    hierarchy: HierarchyChange or None = None
    technical: TechnicalChange or None = None

    @property
    def creates_new_department(self) -> bool:
        return bool(self.fake_id)

    @classmethod
    def from_dict(cls, department_action: Dict[str, Any]) -> 'DepartmentAction':
        simple_fields = ('delete', 'fake_id', 'id')
        return cls(
            name=DepartmentAction.NameChange(**department_action.get('name', {})),
            administration=DepartmentAction.AdministrationChange(**department_action.get('administration', {})),
            hierarchy=DepartmentAction.HierarchyChange(**department_action.get('hierarchy', {})),
            technical=DepartmentAction.TechnicalChange(**department_action.get('technical', {})),
            **{f: department_action.get(f) for f in simple_fields},
        )

    def as_dict(self):
        result = attr.asdict(self)

        for field in ('name', 'administration', 'technical', 'hierarchy'):
            if result[field] is None:
                result.pop(field)

        return result
