from odoo import api, fields, models
from odoo.exceptions import UserError
import logging

_logger = logging.getLogger(__name__)


class AccountMove(models.Model):
    _inherit = ['account.move', 'account.move.template.mixin']

    move_ids = fields.Many2many(
        comodel_name='account.move',
        relation='account_move_template_invoice_move_rel',
        column1='document_id',
        column2='move_id',
        string='Проводки по шаблону',
    )

    journal_template_id = fields.Many2one(
        comodel_name='account.move.template',
        string='Шаблон типовой операции',
        default=lambda self: self._default_journal_template(),
    )

    def _default_journal_template(self):
        use = self.env['ir.config_parameter'].sudo().get_param(
            'account_move_templates_invoice.use_journal_templates_for_invoices'
        )
        if use:
            return self.env['account.move.template'].search([], limit=1, order='id asc')
        return False

    def get_move_line_amounts(self):
        """Return invoice total as the base amount for the wizard."""
        self.ensure_one()
        return [{'name': self.name or '/', 'amount': self.amount_total}]

    def _replace_lines_from_template(self, move):
        """
        Replace ALL lines (product + payment_term) with template lines
        plus one explicit payment_term line with date_maturity.

        We pass 'balance' explicitly in vals so _get_protected_vals protects
        it from being overwritten by _sync_invoice.
        """
        _logger.info("TEMPLATE DEBUG: _replace_lines_from_template START for move %s", move.id)
        template = move.journal_template_id
        _logger.info("TEMPLATE DEBUG: template = %s", template)
        base_amount = move.amount_untaxed or move.amount_total
        _logger.info("TEMPLATE DEBUG: base_amount = %s", base_amount)

        # Determine receivable/payable account
        partner = move.commercial_partner_id.with_company(move.company_id)
        if move.is_sale_document(include_receipts=True):
            term_account = partner.property_account_receivable_id
        else:
            term_account = partner.property_account_payable_id
        _logger.info("TEMPLATE DEBUG: term_account = %s", term_account)

        # due date: use invoice_date_due, invoice_date, or today
        due_date = (
            move.invoice_date_due
            or move.invoice_date
            or fields.Date.context_today(move)
        )
        _logger.info("TEMPLATE DEBUG: due_date = %s", due_date)

        # Remove only payment_term lines, keep product lines from invoice_line_ids
        _logger.info("TEMPLATE DEBUG: Removing existing payment_term lines")
        lines_to_remove = move.line_ids.filtered(lambda l: l.display_type == 'payment_term')
        _logger.info("TEMPLATE DEBUG: Lines to remove: %s", [(l.id, l.account_id.code, l.display_type) for l in lines_to_remove])
        lines_to_remove.with_context(
            dynamic_unlink=True,
            check_move_validity=False,
            skip_invoice_sync=True,
        ).unlink()
        _logger.info("TEMPLATE DEBUG: payment_term lines removed")

        AML = self.env['account.move.line']
        ctx = dict(check_move_validity=False, skip_invoice_sync=True)

        # 1. Process template lines based on line_type
        _logger.info("TEMPLATE DEBUG: Processing template lines")
        
        # Get existing product lines from invoice_line_ids
        product_lines = move.line_ids.filtered(lambda l: l.display_type == 'product')
        _logger.info("TEMPLATE DEBUG: Found %d product lines", len(product_lines))
        
        # Separate template lines by type
        template_product_lines = template.line_ids.filtered(lambda l: l.line_type == 'product')
        template_payment_lines = template.line_ids.filtered(lambda l: l.line_type == 'payment')
        
        _logger.info("TEMPLATE DEBUG: Template has %d product lines and %d payment lines", 
                    len(template_product_lines), len(template_payment_lines))
        
        # Update existing product lines with accounts from template (line_type='product')
        for idx, product_line in enumerate(product_lines):
            if idx < len(template_product_lines):
                tpl_line = template_product_lines[idx]
                _logger.info("TEMPLATE DEBUG: Updating product line %d: old account=%s, new account=%s", 
                           product_line.id, product_line.account_id.code, tpl_line.account_id.code)
                product_line.with_context(**ctx).write({'account_id': tpl_line.account_id.id})
        
        # Create payment lines from template (line_type='payment')
        _logger.info("TEMPLATE DEBUG: Creating payment lines from template")
        for tpl_line in template_payment_lines:
            line_amount = base_amount * tpl_line.percent / 100.0
            balance = line_amount if tpl_line.move_type == 'debit' else -line_amount
            _logger.info("TEMPLATE DEBUG: Creating payment line: account=%s, balance=%s", 
                        tpl_line.account_id.id, balance)
            
            vals = {
                'move_id': move.id,
                'account_id': tpl_line.account_id.id,
                'name': template.name,
                'balance': balance,
                'amount_currency': balance,
                'date_maturity': due_date,
                'display_type': 'payment_term',
            }
            
            AML.with_context(**ctx).create(vals)
        _logger.info("TEMPLATE DEBUG: Template lines processed")
        
        _logger.info("TEMPLATE DEBUG: _replace_lines_from_template END")

    def action_post(self):
        _logger.info("TEMPLATE DEBUG: action_post called for moves: %s", self.ids)
        use_templates = self.env['ir.config_parameter'].sudo().get_param(
            'account_move_templates_invoice.use_journal_templates_for_invoices'
        )
        _logger.info("TEMPLATE DEBUG: use_templates = %s", use_templates)
        
        if use_templates:
            for move in self.filtered(
                lambda m: m.move_type in ('out_invoice', 'in_invoice')
            ):
                _logger.info("TEMPLATE DEBUG: Processing move %s, template: %s", move.id, move.journal_template_id)
                if not move.journal_template_id:
                    raise UserError(
                        'Выберите шаблон типовой операции перед проведением.'
                    )
                try:
                    _logger.info("TEMPLATE DEBUG: Calling _replace_lines_from_template")
                    self._replace_lines_from_template(move)
                    _logger.info("TEMPLATE DEBUG: _replace_lines_from_template completed")
                except Exception as e:
                    _logger.error("TEMPLATE DEBUG: Error in _replace_lines_from_template: %s", e, exc_info=True)
                    raise

        return super().action_post()
