# Copyright 2023 Moduon Team S.L.
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0)


from odoo import api, fields, models


class ProjectProject(models.Model):
    _inherit = "project.project"
    _sql_constraints = [
        # Ensure compatibility with other modules that always expect a value in name
        ("name_required", "CHECK(name IS NOT NULL)", "Project name is required"),
        (
            "sequence_code_unique",
            "UNIQUE(sequence_code)",
            "Sequence code must be unique",
        ),
    ]

    sequence_code = fields.Char(
        copy=False,
        readonly=True,
    )
    name = fields.Char(
        # We actually require it with the SQL constraint, but it is disabled
        # here to let users create/write projects without name, and let this module
        # add a default name if needed
        required=False,
    )

    def _sync_analytic_account_name(self):
        """Set analytic account name equal to project's display name."""
        for rec in self:
            if not rec.analytic_account_id:
                continue
            rec.analytic_account_id.name = rec.display_name

    def name_get(self):
        """Prefix name with sequence code if they are different."""
        old_result = super().name_get()
        result = []
        sequence_pattern = (
            self.env["ir.config_parameter"]
            .sudo()
            .get_param(
                "project_sequence.display_name_pattern",
                default="%(sequence_code)s - %(name)s",
            )
        )
        for id_, name in old_result:
            project = self.browse(id_)
            if project.sequence_code and project.sequence_code != name:
                name = sequence_pattern % {
                    "name": name,
                    "sequence_code": project.sequence_code,
                }
            result.append((id_, name))
        return result

    @api.model
    def name_search(self, name="", args=None, operator="ilike", limit=100):
        """Allow searching by sequence code by default."""
        # Do not add any domain when user just clicked on search widget
        if not (name == "" and operator == "ilike"):
            # The dangling | is needed to combine with the domain added by super()
            args = (args or []) + ["|", ("sequence_code", operator, name)]
        return super().name_search(name, args, operator, limit)

    @api.model_create_multi
    def create(self, vals_list):
        """Apply sequence code and a default name if not set."""
        # It is important to set sequence_code before calling super() because
        # other modules such as hr_timesheet expect the name to always have a value
        for vals in vals_list:
            if not vals.get("sequence_code", False):
                vals["sequence_code"] = self.env["ir.sequence"].next_by_code(
                    "project.sequence"
                )
            if not vals.get("name"):
                vals["name"] = vals["sequence_code"]
        res = super().create(vals_list)
        # The analytic account is created with just the project name, but
        # it is more useful to let it contain the project sequence too
        res._sync_analytic_account_name()
        return res

    def write(self, vals):
        """Sync name and analytic account name when name is changed."""
        # If name isn't changing, nothing special to do
        if "name" not in vals and "sequence_name" not in vals:
            return super().write(vals)
        # When changing name, we need to update the analytic account name too
        for one in self:
            sequence_code = vals.get("sequence_code", one.sequence_code)
            name = vals.get("name") or sequence_code
            super().write(dict(vals, name=name))
        self._sync_analytic_account_name()
        return True
