import json
from datetime import datetime
import logging

from staff.departments.models import Bonus
from staff.lib.sync_tools.data_mapper import DataMapper
from staff.lib.sync_tools.rollupper import Rollupper
from staff.oebs import models as oebs_models

logger = logging.getLogger(__name__)


def get_non_review_bonus(scheme_data: str or None) -> float or None:
    def _is_non_review_bonus_row(row):
        return row['value_type'] == 'Процент от оклада' and row['value_source'] == 'Значением'

    bonuses = [(row['value'] or .0) for row in json.loads(scheme_data) if _is_non_review_bonus_row(row)]

    if len(bonuses) == 0:
        return None

    return round(sum(bonuses) * 12, 13)


class BonusDataMapper(DataMapper):
    mapping = (
        ('scheme_id',),
        ('schemes_line_id',),
        ('name',),
        ('description',),
        ('start_date',),
        ('end_date',),
        ('scheme_data',),
        ('scheme_data', 'non_review_bonus', get_non_review_bonus),
        ('scheme_id', 'intranet_status', lambda _: 1),
    )


class BonusRollupper(Rollupper):
    model = oebs_models.Bonus
    data_mapper_class = BonusDataMapper
    link_field_name = 'dis_bonus'
    key_field_name = 'scheme_id'
    create_absent = True

    def create_dis_instance(self, oebs_instance: oebs_models.Bonus) -> Bonus:
        now = datetime.now()
        return Bonus(
            scheme_id=oebs_instance.scheme_id,
            schemes_line_id=oebs_instance.schemes_line_id,
            name=oebs_instance.name,
            description=oebs_instance.description,
            start_date=oebs_instance.start_date,
            end_date=oebs_instance.end_date,
            scheme_data=oebs_instance.scheme_data,
            non_review_bonus=get_non_review_bonus(oebs_instance.scheme_data),
            created_at=now,
            modified_at=now,
        )

    def run_rollup(self, object_id=None, dry_run=False):
        super().run_rollup(object_id, dry_run)

        if not dry_run:
            Bonus.objects.filter(oebs_bonus__isnull=True).update(intranet_status=0)
