from hql import hql
from ppms import ppms
from ppms.migration import SQLPacket, ChangeDTPPacket, PacketCategory, \
    MinVersionDependency, MaxVersionDependency, VersionType, PacketDependency, PacketState


DI_FOR_ADJUSTING = {("029316",): dict(hdi_ajust_source=['028831', '023173']),
                    ("029263",): dict(hdi_ajust_source=['023173', '028831'])
                    }


class CorrectExistentReports(ChangeDTPPacket, SQLPacket):
    """
    fixes existing reports: switches values for DI029316 and DI029263

    CAUTION: run this package only once, otherwise you will get wrong data in reports
    """
    
    version = 1
    done_after_success = True
    run_on_startup = True
    category = PacketCategory.CATEGORY_MANDATORY
    wi_number = 13803

    def get_dependencies(self):
        return (MinVersionDependency(version='39.4'),
                MaxVersionDependency(version='39.4'),
                PacketDependency(
                    packet_path=r'migration.hotfix.S_39_5_15.wi13803_fix_reports_in_voe.CorrectDIForAdjustment',
                    expected_state=PacketState.INSTALLED),
                PacketDependency(
                    packet_path=r'migration.server.S_39_5_13.wi12349_add_entity.Entity',
                    expected_state=PacketState.INSTALLED),
                PacketDependency(
                    packet_path=r'migration.server.S_39_5_14.wi13837_add_entity2.Entity2',
                    expected_state=PacketState.INSTALLED))
    
    def hql_modify(self, query, log_rows=True):
        self.log('Executing query "%s"' % query)
        try:
            rows = hql.modify(query)
        except ppms.DatabaseError as e:
            self.log('Statement failed: DatabaseError occured: {exception}'.format(exception=e))
            rows = -1

        if log_rows:
            self.log('Affected %i row(s)' % rows)

        return rows

    def fix(self, runner):
        modifying_user = 'MIGRATION'
        budget_co_ben_p_year_report = hql.search_record("from BudgetCoBenPYearReport report")
        
        failed = 0
        
        for record in budget_co_ben_p_year_report:
            if record.modified_by.get_value() != modifying_user:
                pr_id = record.pr_id.get_value()
                report_id = record.report_id.get_value()
                year = record.year_id.get_value()
                
                planned_benefit_total_rec = record.planned_benefit
                achieved_benefit_total_rec = record.achieved_benefit
                
                planned_benefit = planned_benefit_total_rec.get_value()
                achieved_benefit = achieved_benefit_total_rec.get_value()
                
                self.change_value(record, 'planned_benefit', planned_benefit, achieved_benefit)
                self.change_value(record, 'achieved_benefit', achieved_benefit, planned_benefit)

                self.log("Trying to set objectprotectionfield 'modified-by'")

                statement = "update BudgetCoBenPYearReport bcbpyr " \
                            "set bcbpyr.modified_by = '{modifying_user}' " \
                            "where bcbpyr.pr_id = '{pr_id}' " \
                            "and bcbpyr.report_id = '{report_id}' " \
                            "and bcbpyr.year_id = {year}"

                if self.hql_modify(statement.format(modifying_user=modifying_user,
                                                    pr_id=pr_id,
                                                    report_id=report_id,
                                                    year=year)) < 1:
                    failed += 1
            else:
                self.log("Was already modified by %s" % modifying_user)
        if failed:
            return self.fail("Failed on %s statements" % str(failed))
        return self.success()


class CorrectDIForAdjustment(ChangeDTPPacket):
    """
    fixes dataitem for adjustmentsource
    
    changes for DI029316 from 028831 to 023173
    changes for DI029263 from 023173 to 028831

    CAUTION: run this package only once, otherwise you will get wrong data in reports
    """
    
    version = 1
    done_after_success = True
    run_on_startup = True
    category = PacketCategory.CATEGORY_MANDATORY
    wi_number = 13803
    
    def get_dependencies(self):
        return (MinVersionDependency(version='39.4', version_type=VersionType.CUSTOMIZING),
                MaxVersionDependency(version='39.4.4', version_type=VersionType.CUSTOMIZING))
    
    def change_record(self, datatable, primary_key, change_dictionary):
        old_value = 0
        new_value = 1
        record = self.get_record(datatable, list(primary_key), list(change_dictionary.keys()))
        if not record: 
            return
        for field in change_dictionary.keys():
            old_new_values = change_dictionary.get(field)
            self.change_value(record, field, old_new_values[old_value], old_new_values[new_value])
            
    def fix(self, runner):
        for dataitem, value in DI_FOR_ADJUSTING.items():
            self.change_record(412, dataitem, value)
        return self.success()