from odoo import models, fields, _
from odoo.exceptions import UserError
import base64
import dateutil.parser
# import logging

# _logger = logging.getLogger(__name__)


class InvoiceImportWizard(models.TransientModel):
    _name = 'invoice.import.wizard'
    _description = 'Import Invoice'

    file = fields.Binary(string='File', required=True)
    file_name = fields.Char(string='File Name')

    def action_import_invoice(self):
        # _logger.info("Начало импорта файла выписки")

        if not self.file:
            # _logger.error("Файл не загружен")
            raise UserError(_("Please upload the file."))

        if not self.file_name.endswith('.txt'):
            # _logger.error("Неподдерживаемый формат файла: %s", self.file_name)
            raise UserError(_("Only TXT files are allowed."))

        file_content = base64.b64decode(self.file).decode('cp1251')
        journal = self.env['account.journal'].search([('type', '=', 'bank'), ('use_in_bank_statement', '=', True)],
                                                     limit=1)
        if not journal:
            raise UserError(_("Suitable journal not found."))

        try:
            sections = file_content.split('СекцияДокумент')
            invoice_sections = sections[0]
            transaction_sections = sections[1:]

            invoices = invoice_sections.split('СекцияРасчСчет')[1:]
            for invoice in invoices:
                statement_data = self.parse_statement_data(invoice)

                existing_statement = self.env['account.bank.statement'].search([
                    ('date_from', '=', dateutil.parser.parse(statement_data.get('ДатаНачала', '').strip(), dayfirst=True).date()),
                    ('name', '=', statement_data.get('РасчСчет', '').strip()),
                ], limit=1)

                if not existing_statement:
                    statement = self.create_statement(journal, statement_data)
                    # _logger.info("Выписка создана успешно: %s", statement.name)
            self.create_statement_lines(journal, transaction_sections)


        except Exception as e:
            # _logger.error("Ошибка при импорте файла: %s", e)
            raise UserError(_("Error Import: %s" % str(e)))

        message_title = _("Импорт завершен")
        message_content = _("Выписка успешно импортирована.")

        return {
            'type': 'ir.actions.client',
            'tag': 'display_notification',
            'params': {
                'title': message_title,
                'message': message_content,
            },
        }

    def parse_statement_data(self, section):
        lines = section.strip().split('\n')
        statement_data = {}
        for line in lines:
            if '=' in line:
                key, value = line.split('=', 1)
                statement_data[key] = value
        return statement_data

    def create_statement(self, journal, statement_data):
        statement_vals = {
            'journal_id': journal.id,
            'name': statement_data.get('РасчСчет', '').strip(),
            'balance_start': float(statement_data.get('НачальныйОстаток', '0.0').strip()),
            'balance_end_real': float(statement_data.get('КонечныйОстаток', '0.0').strip()),
            'date_from': dateutil.parser.parse(statement_data.get('ДатаНачала', '').strip(), dayfirst=True).date(),
        }

        return self.env['account.bank.statement'].sudo().create(statement_vals)

    def create_statement_lines(self, journal, sections):
        for section in sections:
            if section.strip():
                lines = section.strip().split('\n')
                transaction = self.parse_transaction_data(lines)
                if transaction:
                    # _logger.info("<==================================>")
                    # _logger.info("Создание строки выписки для транзакции №%s", transaction.get('Номер').strip())
                    self.create_line(journal, transaction)
                    # _logger.info("Строка выписки для транзакции №%s создана успешно", transaction.get('Номер').strip())

    def parse_transaction_data(self, lines):
        transaction = {}
        for line in lines:
            if '=' in line:
                key, value = line.split('=', 1)
                transaction[key] = value
        return transaction

    def create_line(self, journal, transaction):
        my_company_inn = journal.company_id.vat

        transaction_date = dateutil.parser.parse(transaction.get('Дата', '').strip(), dayfirst=True).date()
        statement = self.env['account.bank.statement'].search([
            ('date_from', '=', transaction_date),
        ], limit=1)

        if not statement:
            raise UserError(_("Statement not found for journal {} on date {}.").format(journal.name, transaction_date))

        amount = float(transaction.get('Сумма', '0.0').strip())

        if transaction.get('ПлательщикИНН').strip() == my_company_inn:
            amount = -amount
            partner_inn = transaction.get('ПолучательИНН').strip()
            partner_kpp = transaction.get('ПолучательКПП').strip()
            partner_name = transaction.get('Получатель').strip()
            partner_account = transaction.get('ПолучательСчет').strip()
            bank_bik = transaction.get('ПолучательБИК').strip()
            bank_account = transaction.get('ПолучательКорсчет').strip()
            bank_name = transaction.get('ПолучательБанк1').strip()
        elif transaction.get('ПолучательИНН').strip() == my_company_inn:
            # Если наша компания - получатель, значит это доход
            partner_inn = transaction.get('ПлательщикИНН').strip()
            partner_kpp = transaction.get('ПлательщикКПП').strip()
            partner_name = transaction.get('Плательщик').strip()
            partner_account = transaction.get('ПлательщикСчет').strip()
            bank_bik = transaction.get('ПлательщикБИК').strip()
            bank_account = transaction.get('ПлательщикКорсчет').strip()
            bank_name = transaction.get('ПлательщикБанк1').strip()
        else:
            error_message = "ИНН вашей компании не найден в транзакции. Запись не создана."
            error_message += "Журнал: {}, Дата транзакции: {}. ".format(journal.name, transaction_date)
            error_message += "Плательщик: {}, ИНН плательщика: {}. ".format(transaction.get('Плательщик1', 'не указан').strip(),
                                                                            transaction.get('ПлательщикИНН',
                                                                                            'не указан').strip())
            error_message += "Получатель: {}, ИНН получателя: {}. ".format(transaction.get('Получатель1', 'не указан').strip(),
                                                                           transaction.get('ПолучательИНН',
                                                                                           'не указан').strip())
            raise UserError(_(f"{error_message}"))

        existing_line = self.env['account.bank.statement.line'].search([
            ('date', '=', transaction_date),
            ('amount', '=', amount),
            ('narration', '=', transaction.get('НазначениеПлатежа', '').strip()),
            ('payment_ref', '=', transaction.get('Номер').strip()),
        ], limit=1)

        if existing_line:
            # _logger.info("Строка выписки уже существует: %s", existing_line.id)
            return None

        partner = self.env['res.partner'].search([('vat', '=', partner_inn), ('kpp', '=', partner_kpp)], limit=1)
        if not partner:
            # _logger.info("Создание нового партнера: ИНН %s, КПП %s", partner_inn, partner_kpp)
            partner = self.env['res.partner'].create({
                'name': partner_name,
                'vat': partner_inn,
                'kpp': partner_kpp,
                'company_type': 'company',
            })

        bank = self.env['res.bank'].search([('bic', '=', bank_bik), ('corr_acc', '=', bank_account)], limit=1)
        if not bank:
            # _logger.info("Создание нового банка: БИК %s", bank_bik)
            bank = self.env['res.bank'].create({
                'name': bank_name,
                'bic': bank_bik,
                'corr_acc': bank_account,
            })

        partner_bank_account = self.env['res.partner.bank'].search(
            [('acc_number', '=', partner_account), ('partner_id', '=', partner.id)], limit=1)
        if not partner_bank_account:
            # _logger.info("Создание нового банковского счета для партнера %s", partner.name)
            partner_bank_account = self.env['res.partner.bank'].create({
                'acc_number': partner_account,
                'bank_id': bank.id,
                'partner_id': partner.id,
            })

        line_vals = {
            'journal_id': journal.id,
            'partner_bank_id': partner_bank_account.id,
            'partner_id': partner.id,
            'statement_id': statement.id,
            'company_id': journal.company_id.id,
            'date': transaction_date,
            'amount': amount,
            'narration': transaction.get('НазначениеПлатежа', '').strip(),
            'payment_ref': transaction.get('Номер').strip(),
        }
        self.env['account.bank.statement.line'].sudo().create(line_vals)
