# coding: utf-8


import attr

from idm.nodes.queue import (
    ExternalIDQueue,
    ExternalIDAdditionItem,
    ExternalIDMovementItem,
    ModificationItem,
    ExternalIDRemovalItem,
    RestoringItem,
)
from idm.users import signals


class GroupAdditionItem(ExternalIDAdditionItem):
    def apply(self, **kwargs):
        from idm.users.models import Group

        group = Group.from_canonical(self.child_data)
        group.parent = self.get_parent_node()
        group.save()
        self.new_node = group
        signals.group_added.send(sender=self.node, group=group)
        # Обновление состава департаментых групп происходит в таске по синхронизации пользователей
        group.add_members(list(self.child_data.members.values()))
        group.add_responsibles(list(self.child_data.responsibles.values()))
        group.actions.create(action='group_created')


class GroupModificationItem(ModificationItem):
    def apply(self, **kwargs):
        diff = self.get_diff()

        data_has_changed = bool(diff.flat)

        for item in diff.flat:
            setattr(self.node, item.name, item.new)

        # Обновление состава департаментых групп происходит в таске по синхронизации пользователей
        self.node.add_members([addition.new for addition in diff.nested['members'].additions])
        self.node.remove_members([removal.old for removal in diff.nested['members'].removals])

        self.node.add_responsibles([addition.new for addition in diff.nested['responsibles'].additions])
        self.node.remove_responsibles([removal.old for removal in diff.nested['responsibles'].removals])

        self.node.hash = self.new_data.hash
        self.node.save()
        if data_has_changed:
            self.node.actions.create(
                group=self.node,
                action='group_changed',
                data={
                    'diff': {item.name: [item.old, item.new] for item in diff.flat}
                }
            )
        return self.node


class GroupMovementItem(ExternalIDMovementItem):
    source_snapshot = attr.ib(default=None)

    def __init__(self, *args, **kwargs):
        super(GroupMovementItem, self).__init__(*args, **kwargs)
        self.source_snapshot = self.node.as_snapshot()

    def apply(self, **kwargs):
        new_parent = self.get_parent_node()

        action_data = {
            'moved_from': {
                'id': self.node.pk,
                'path': self.node.path,
            }
        }
        self.node.parent = new_parent
        self.node.save(recalc_fields=True)
        target = self.node.as_snapshot()

        action_data['moved_to'] = self.node.path
        self.node.actions.create(action='group_moved', data=action_data)

        if self.node.type == 'department':
            self.node.transfers.create(
                type='group',
                state='created',
                source=self.node,
                target=self.node,
                source_name=self.source_snapshot,
                target_name=target,
            )


class GroupRemovalItem(ExternalIDRemovalItem):
    def apply(self, **kwargs):
        self.node.mark_depriving()


class GroupRestoreItem(RestoringItem):
    def apply(self, **kwargs):
        self.node.state = 'active'
        self.node.expire_at = None
        self.node.save(update_fields=('state', 'expire_at'))
        signals.group_restored.send(sender=self.node, group=self.node)


class GroupQueue(ExternalIDQueue):
    addition = GroupAdditionItem
    modification = GroupModificationItem
    removal = GroupRemovalItem
    restore = GroupRestoreItem
    movement = GroupMovementItem

    def get_item_class(self):
        from idm.users.models import Group
        return Group
