import datetime

from decimal import Decimal, ROUND_HALF_DOWN


class BaseSection:
    _fields = []
    _mandatory_fields = []

    def __str__(self):
        s = ""
        for name in self._fields:
            s += "\t{}: {}\n".format(name, str(self.__dict__[name]))
        return s

    @property
    def document(self):
        s = ""
        for name in self._mandatory_fields:
            value = self.__dict__[name]
            if value is None:
                value = ''
            value = self.__format_value(value)
            s += "{}={}\n".format(name, value)
        for name in self._fields:
            if name in self._mandatory_fields or self.__dict__[name] is None:
                continue
            value = self.__dict__[name]
            value = self.__format_value(value)
            s += "{}={}\n".format(name, value)
        return s

    @staticmethod
    def __format_value(value):
        if isinstance(value, datetime.date):
            value = value.strftime('%d.%m.%Y')
        if isinstance(value, datetime.time):
            value = value.strftime('%H:%M:%S')
        if isinstance(value, Decimal):
            value = str(value.quantize(Decimal('.01'), rounding=ROUND_HALF_DOWN))
        return value


class GeneralSection(BaseSection):
    _fields = ['ВерсияФормата', 'Кодировка', 'Отправитель', 'Получатель', 'ДатаСоздания', 'ВремяСоздания']
    _mandatory_fields = ['ВерсияФормата', 'Кодировка', 'Отправитель']

    def __init__(self, encoding='windows-1251'):
        BaseSection.__init__(self)

        for name in self._fields:
            self.__dict__[name] = None

        self.__dict__['ВерсияФормата'] = '1.02'
        if encoding == 'windows-1251':
            self.__dict__['Кодировка'] = 'Windows'
        elif encoding == 'utf-8':
            self.__dict__['Кодировка'] = 'UTF-8'
        elif encoding == 'cp-866':
            self.__dict__['Кодировка'] = 'DOS'
        self.__dict__['Отправитель'] = 'modulbank_python'
        self.__dict__['ДатаСоздания'] = datetime.date.today()
        self.__dict__['ВремяСоздания'] = datetime.datetime.now().time()


class FilterSection(BaseSection):
    _fields = ['ДатаНачала', 'ДатаКонца', 'РасчСчет', 'Документ']
    _mandatory_fields = ['ДатаНачала', 'ДатаКонца', 'РасчСчет']

    def __init__(self):
        BaseSection.__init__(self)

        for name in self._fields:
            self.__dict__[name] = None

        self.__dict__['ДатаНачала'] = datetime.date.today()
        self.__dict__['ДатаКонца'] = datetime.date.today()


class BalancesSection(BaseSection):
    _fields = ['ДатаНачала', 'ДатаКонца', 'РасчСчет', 'НачальныйОстаток', 'ВсегоПоступило', 'ВсегоСписано',
               'КонечныйОстаток']
    _mandatory_fields = []

    def __init__(self):
        BaseSection.__init__(self)

        for name in self._fields:
            self.__dict__[name] = None


class DocumentSection(BaseSection):
    _fields = ['Номер', 'Дата', 'Сумма', 'КвитанцияДата', 'КвитанцияВремя', 'КвитанцияСодержание', 'ПлательщикСчет',
               'ДатаСписано', 'Плательщик', 'ПлательщикИНН', 'Плательщик1', 'Плательщик2', 'Плательщик3',
               'Плательщик4', 'ПлательщикРасчСчет', 'ПлательщикБанк1', 'ПлательщикБанк2', 'ПлательщикБИК',
               'ПлательщикКорсчет', 'ПолучательСчет', 'ДатаПоступило', 'Получатель', 'ПолучательИНН', 'Получатель1',
               'Получатель2', 'Получатель3', 'Получатель4', 'ПолучательРасчСчет', 'ПолучательБанк1', 'ПолучательБанк2',
               'ПолучательБИК', 'ПолучательКорсчет', 'ВидПлатежа', 'ВидОплаты', 'Код', 'НазначениеПлатежа',
               'НазначениеПлатежа 1', 'НазначениеПлатежа 2', 'НазначениеПлатежа 3', 'НазначениеПлатежа 4',
               'НазначениеПлатежа 5', 'НазначениеПлатежа 6', 'СтатусСоставителя', 'ПлательщикКПП', 'ПолучательКПП',
               'ПоказательКБК', 'ОКАТО', 'ПоказательОснования', 'ПоказательПериода', 'ПоказательНомера',
               'ПоказательДаты', 'ПоказательТипа', 'Очередность', 'СрокАкцепта', 'ВидАккредитива', 'СрокПлатежа',
               'УсловиеОплаты1', 'УсловиеОплаты2', 'УсловиеОплаты3', 'ПлатежПоПредст', 'ДополнУсловия',
               'НомерСчетаПоставщика', 'ДатаОтсылкиДок']
    _mandatory_fields = ['Номер', 'Дата', 'Сумма', 'ПлательщикСчет', 'Плательщик', 'ПлательщикИНН', 'Плательщик1',
                         'ПлательщикРасчСчет', 'ПлательщикБанк1', 'ПлательщикБанк2', 'ПлательщикБИК',
                         'ПлательщикКорсчет', 'ПолучательСчет', 'Получатель', 'ПолучательИНН', 'Получатель1',
                         'ПолучательРасчСчет', 'ПолучательБанк1', 'ПолучательБанк2', 'ПолучательБИК',
                         'ПолучательКорсчет', 'ВидОплаты', 'СтатусСоставителя', 'ПлательщикКПП', 'ПолучательКПП',
                         'ПоказательКБК', 'ОКАТО', 'ПоказательОснования', 'ПоказательПериода', 'ПоказательНомера',
                         'ПоказательДаты']

    def __init__(self):
        BaseSection.__init__(self)

        for name in self._fields:
            self.__dict__[name] = None


class ClientBankExchange:
    """
    Файл обмена данными 1С
    """

    def __init__(self):
        self.__dict__['ОбщиеСведения'] = GeneralSection()
        self.__dict__['УсловияОтбора'] = FilterSection()
        self.__dict__['СекцияОстатков'] = BalancesSection()
        self.__dict__['СекцияПлатежногоДокумента'] = DocumentSection()

    def __str__(self):
        s = ""
        for item in ['ОбщиеСведения', 'УсловияОтбора', 'СекцияОстатков', 'СекцияПлатежногоДокумента']:
            s += "\n{}: \n{}".format(item, str(self.__dict__[item]))
        return s

    @property
    def document(self):
        s = "1CClientBankExchange\n{body}КонецФайла"
        body = self.__dict__['ОбщиеСведения'].document
        body += self.__dict__['УсловияОтбора'].document
        body += self.__dict__['СекцияОстатков'].document
        body += 'СекцияДокумент=Платежное поручение\n'
        body += self.__dict__['СекцияПлатежногоДокумента'].document
        body += 'КонецДокумента\n'
        return s.format(body=body)
