from odoo import api, fields, models
from odoo.exceptions import ValidationError


class AccountMoveTemplateTag(models.Model):
    _name = 'account.move.template.tag'
    _description = 'Признак шаблона'

    name = fields.Char(string='Название', required=True, translate=True)
    color = fields.Integer(string='Цвет')


class AccountMoveTemplate(models.Model):
    _name = 'account.move.template'
    _description = 'Шаблон типовой операции'

    name = fields.Char(string='Название', required=True)
    description = fields.Text(string='Описание')
    tag_ids = fields.Many2many(
        comodel_name='account.move.template.tag',
        string='Признаки',
    )
    line_ids = fields.One2many(
        comodel_name='account.move.template.line',
        inverse_name='template_id',
        string='Строки шаблона',
    )

    @api.constrains('line_ids')
    def _check_balance(self):
        for template in self:
            if not template.line_ids:
                raise ValidationError(
                    'Шаблон должен содержать хотя бы одну строку.'
                )
            debit_sum = sum(
                line.percent for line in template.line_ids if line.move_type == 'debit'
            )
            credit_sum = sum(
                line.percent for line in template.line_ids if line.move_type == 'credit'
            )
            if round(debit_sum, 2) != round(credit_sum, 2):
                diff = round(abs(debit_sum - credit_sum), 2)
                raise ValidationError(
                    f'Сумма дебета ({debit_sum:.2f}%) не равна сумме кредита '
                    f'({credit_sum:.2f}%), разница: {diff:.2f}%'
                )


class AccountMoveTemplateLine(models.Model):
    _name = 'account.move.template.line'
    _description = 'Строка шаблона типовой операции'

    template_id = fields.Many2one(
        comodel_name='account.move.template',
        string='Шаблон',
        required=True,
        ondelete='cascade',
    )
    account_id = fields.Many2one(
        comodel_name='account.account',
        string='Счёт',
        required=True,
        ondelete='restrict',
    )
    move_type = fields.Selection(
        selection=[('debit', 'Дебет'), ('credit', 'Кредит')],
        string='Сторона',
        required=True,
    )
    percent = fields.Float(
        string='Процент',
        required=True,
        digits=(5, 2),
    )
    line_type = fields.Selection(
        selection=[
            ('product', 'Продуктовая строка (заменяет счёт)'),
            ('payment', 'Строка оплаты (receivable/payable)')
        ],
        string='Тип строки',
        required=True,
        default='product',
        help='Продуктовая строка заменяет счёт в существующих product-строках инвойса. '
             'Строка оплаты создаёт новую payment_term строку.'
    )

    @api.constrains('percent')
    def _check_percent(self):
        for line in self:
            if line.percent < 0.01 or line.percent > 100.0:
                raise ValidationError(
                    'Процент должен быть от 0.01 до 100.00.'
                )
