# -*- coding: utf-8 -*-
"""Russian tax and registration code validation constants and functions."""
KPP_CODE = {
    '01': ('Постановка на учет в налоговом органе российской организации '
           'в качестве налогоплательщика по месту ее нахождения'),
    '02': ('Постановка на учет налогоплательщика - российской организации '
           'по месту нахождения ее обособленного подразделения в зависимости '
           'от вида подразделения'),
    '03': ('Постановка на учет налогоплательщика – российской организации '
           'по месту нахождения ее филиала, не исполняющего обязанности '
           'организации по уплате налогов и сборов'),
    '04': ('Постановка на учет налогоплательщика - российской организации '
           'по месту нахождения ее обособленного подразделения в зависимости '
           'от вида подразделения'),
    '05': ('Постановка на учет налогоплательщика - российской организации '
           'по месту нахождения ее обособленного подразделения в зависимости '
           'от вида подразделения'),
    '06': ('Постановка на учет налогоплательщика - российской организации '
           'по месту нахождения принадлежащего ей недвижимого имущества '
           '(за исключением транспортных средств) - в зависимости от вида '
           'имущества'),
    '07': ('Постановка на учет налогоплательщика - российской организации '
           'по месту нахождения принадлежащего ей недвижимого имущества '
           '(за исключением транспортных средств) - в зависимости от вида '
           'имущества'),
    '08': ('Постановка на учет налогоплательщика - российской организации '
           'по месту нахождения принадлежащего ей недвижимого имущества '
           '(за исключением транспортных средств) - в зависимости от вида '
           'имущества'),
    '30': ('Российская организация - налоговый агент, не учтенная в качестве '
           'налогоплательщика'),
    '31': ('Постановка на учет налогоплательщика - российской организации '
           'по месту нахождения обособленного подразделения, в отношении '
           'которого не проведена процедура оформления в соответствии с '
           'пунктом 3 статьи 55 Гражданского кодекса Российской Федерации, '
           'исполняющего обязанности организации по уплате налогов и сборов'),
    '32': ('Постановка на учет налогоплательщика - российской организации '
           'по месту нахождения обособленного подразделения, в отношении '
           'которого не проведена процедура оформления в соответствии с '
           'пунктом 3 статьи 55 Гражданского кодекса Российской Федерации, '
           'не исполняющего обязанности организации по уплате налогов и '
           'сборов'),
    '51': 'Постановка на учет отделений иностранных организаций',
    '52': ('Постановка на учет отделений иностранных организаций в '
           'Российской Федерации, созданных филиалом этой иностранной '
           'организации в иностранном государстве'),
    '53': 'резервный код',
    '54': 'резервный код',
    '55': 'резервный код',
    '56': 'резервный код',
    '57': 'резервный код',
    '58': 'резервный код',
    '59': 'резервный код',
    '60': 'Постановка на учет посольств иностранных государств',
    '61': 'Постановка на учет консульств иностранных государств',
    '62': ('Постановка на учет представительств, приравненных к '
           'дипломатическим'),
    '63': 'Постановка на учет международных организаций',
    '64': 'резервный код',
    '65': 'резервный код',
    '66': 'резервный код',
    '67': 'резервный код',
    '68': 'резервный код',
    '69': 'резервный код',
    '70': ('Постановка на учет иностранных и международных организаций, '
           'имеющих недвижимое имущество в Российской Федерации, за '
           'исключением транспортных средств, относящихся к недвижимому '
           'имуществу'),
    '71': ('Постановка на учет иностранных и международных организаций, '
           'имеющих транспортные средства в Российской Федерации, не '
           'относящиеся к недвижимому имуществу'),
    '72': ('Постановка на учет иностранных и международных организаций, '
           'имеющих морские транспортные средства в Российской Федерации'),
    '73': ('Постановка на учет иностранных и международных организаций, '
           'имеющих речные транспортные средства в Российской Федерации'),
    '74': ('Постановка на учет иностранных и международных организаций, '
           'имеющих воздушные транспортные средства в Российской Федерации'),
    '75': ('Постановка на учет иностранных и международных организаций, '
           'имеющих космические объекты в Российской Федерации'),
    '76': 'резервный код',
    '77': 'резервный код',
    '78': 'резервный код',
    '79': 'резервный код',
    '80': ('Учет иностранных и международных организаций в связи с '
           'открытием в банках рублевых счетов типа "Т" (текущие)'),
    '81': ('Учет иностранных и международных организаций в связи с '
           'открытием счетов в банках типа "И" (инвестиционные)'),
    '82': ('учет иностранных и международных организаций в связи с '
           'открытием счетов в банках типа "С" (специальные)'),
    '83': ('Учет иностранных и международных организаций в связи с '
           'открытием в банках счетов типа "Т" (текущие) в иностранной '
           'валюте'),
    '84': ('Учет иностранных и международных организаций в связи с '
           'открытием корреспондентских счетов в банка'),
}


OGRN_CODES = {
    '1': 'юридическое лицо',
    '5': 'юридическое лицо',
    '3': 'индивидуальный предприниматель',
}


SOUN_SCHEMA = {'1': {'name': 'kod', 'type': 'string'},
               '2': {'name': 'vid', 'type': 'string'},
               '3': {'name': 'kodp', 'type': 'string'},
               '4': {'name': 'kodv', 'type': 'string'},
               '5': {'name': 'naimk', 'type': 'string'},
               '6': {'name': 'naim', 'type': 'string'},
               '7': {'name': 'psono', 'type': 'int'},
               '8': {'name': 'puch', 'type': 'int'},
               '9': {'name': 'potchdok', 'type': 'int'},
               '10': {'name': 'potch', 'type': 'int'},
               '11': {'name': 'spro_u', 'type': 'string'},
               '12': {'name': 'spro_f', 'type': 'string'},
               '13': {'name': 'inn', 'type': 'string'},
               '14': {'name': 'kpp', 'type': 'string'},
               '15': {'name': 'adres', 'type': 'string'},
               '16': {'name': 'tel', 'type': 'string'},
               '17': {'name': 'email', 'type': 'string'},
               '18': {'name': 'cite', 'type': 'string'},
               '19': {'name': 'dokum', 'type': 'string'},
               '20': {'name': 'nomdok', 'type': 'string'},
               '21': {'name': 'datadok', 'type': 'date'},
               '22': {'name': 'datan', 'type': 'date'},
               '23': {'name': 'datak', 'type': 'date'},
               '24': {'name': 'coment', 'type': 'string'},
               }

SSRF_SCHEMA = {'1': {'name': 'code', 'type': 'string'},
               '2': {'name': 'name', 'type': 'string'},
               }

OKV_SCHEMA = {'1': {'name': 'id', 'type': 'int'},
              '2': {'name': 'ncode', 'type': 'string'},
              '3': {'name': 'ccode', 'type': 'string'},
              '4': {'name': 'name', 'type': 'string'},
              '5': {'name': 'countries', 'type': 'string'},
              }

PLANSCHET_SCHEMA = {'1': {'name': 'id', 'type': 'int'},
                    '2': {'name': 'code', 'type': 'string'},
                    '3': {'name': 'name', 'type': 'string'},
                    '4': {'name': 'stype', 'type': 'int'},
                    '5': {'name': 'parent_id', 'type': 'int'},
                    '6': {'name': 'level', 'type': 'int'},
                    }


RUS_INN_FACTOR = (2, 4, 10, 3, 5, 9, 4, 6, 8)

RUS_ACCOUNT_MASK = [7, 1, 3, 7, 1, 3, 7, 1, 3, 7, 1, 3, 7, 1, 3, 7, 1, 3,
                    7, 1, 3, 7, 1]


def calc_personal_check_digits(number):
    """Calculate the check digits for the 12-digit personal ИНН."""
    weights = (7, 2, 4, 10, 3, 5, 9, 4, 6, 8)
    d1 = str(sum(w * int(n) for w, n in zip(weights, number)) % 11 % 10)
    weights = (3, 7, 2, 4, 10, 3, 5, 9, 4, 6, 8)
    d2 = str(sum(w * int(n) for w, n in zip(weights, number[:10] + d1)) %
             11 % 10)
    return d1 + d2


def _check_inn(code):
    """Validates INN code."""
    if code is not None and code.isdigit():
        if len(code) == 10:
            asum = 0
            for i in range(0, 9):
                asum += int(code[i]) * RUS_INN_FACTOR[i]
            asum = (asum % 11) % 10
            return int(code[9]) == asum
        if len(code) == 12:
            weights = (7, 2, 4, 10, 3, 5, 9, 4, 6, 8)
            d1 = str(sum(w * int(n) for w, n in zip(weights, code)) % 11 %
                     10)
            weights = (3, 7, 2, 4, 10, 3, 5, 9, 4, 6, 8)
            d2 = str(sum(w * int(n) for w, n in zip(weights,
                                                     code[:10] + d1)) % 11 %
                     10)
            chsum = d1 + d2
            return chsum == code[-2:]
    return False


def _check_ogrn(ogrn):
    """Validates OGRN code."""
    if not ogrn:
        return False
    if len(ogrn) == 13:
        delimeter = 11
    elif len(ogrn) == 15:
        delimeter = 13
    else:
        return False
    main_part = int(ogrn[:-1]) % delimeter % 10
    checksum = int(ogrn[-1])

    return main_part == checksum
