# Copyright 2022 Moduon
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).

from datetime import date

from odoo import _, api, exceptions, fields, models


class AccountMoveRenumberWizard(models.TransientModel):
    _name = "account.move.renumber.wizard"
    _description = "Account move entry renumbering wizard"

    starting_date = fields.Date(
        required=True,
        default=lambda self: self._default_starting_date(),
        help="Renumber account moves starting this day.",
    )
    starting_number = fields.Integer(
        default=1, help="Reset sequence to this number before starting."
    )
    available_sequence_ids = fields.Many2many(
        comodel_name="ir.sequence",
        string="Available sequences",
        default=lambda self: self._default_available_sequence_ids(),
    )
    sequence_id = fields.Many2one(
        comodel_name="ir.sequence",
        string="Sequence",
        required=True,
        default=lambda self: self._default_entry_number_sequence(),
        domain="[('id', 'in', available_sequence_ids)]",
        help="Sequence to use for renumbering. "
        "Affects all journals that use this sequence.",
    )

    @api.model
    def _default_starting_date(self):
        """Start by default on day 1 of current year."""
        return date(date.today().year, 1, 1)

    @api.model
    def _default_entry_number_sequence(self):
        """Get default sequence if it exists."""
        return self.env["ir.sequence"].search(
            [
                "&",
                ("code", "=", "account_journal_general_sequence.default"),
                ("company_id", "in", self.env.companies.ids),
            ]
        )

    @api.model
    def _default_available_sequence_ids(self):
        """Let view display only journal-related sequences."""
        return (
            self.env["account.journal"]
            .search([("company_id", "in", self.env.companies.ids)])
            .mapped("entry_number_sequence_id")
        )

    def action_renumber(self):
        """Renumber moves.

        Makes sure moves exist. Sorts them. Resets sequences. Renumbers them.
        """
        # Find posted moves that match wizard criteria
        moves = self.env["account.move"].search(
            [
                ("state", "=", "posted"),
                ("date", ">=", self.starting_date),
                ("journal_id.entry_number_sequence_id", "=", self.sequence_id.id),
            ],
            order="date, id",
        )
        if not moves:
            raise exceptions.UserError(_("No account moves found."))
        # Reset sequence
        future_ranges = self.env["ir.sequence.date_range"].search(
            [
                ("date_from", ">", self.starting_date),
                ("sequence_id", "=", self.sequence_id.id),
            ]
        )
        # Safe `sudo` calls; wizard only available for accounting managers
        future_ranges.sudo().unlink()
        current_range = self.sequence_id._get_current_sequence(self.starting_date)
        current_range.sudo().number_next = self.starting_number
        self.sequence_id.sudo().number_next = self.starting_number
        # Renumber the moves
        moves = moves.with_context(skip_invoice_sync=True)
        moves.entry_number = False
        moves.flush_recordset(["entry_number"])
        moves._compute_entry_number()
