from odoo.exceptions import AccessError, ValidationError
from odoo.tests.common import Form

from .common import TestTowerCommon


class TestTowerServerTemplate(TestTowerCommon):
    """
    Test the server template model
    """

    @classmethod
    def setUpClass(cls):
        super().setUpClass()

        # Create two "Manager" group users
        cls.manager1 = cls.Users.create(
            {
                "name": "Manager 1",
                "login": "manager1",
                "email": "manager1@example.com",
                "groups_id": [(6, 0, [cls.group_manager.id])],
            }
        )
        cls.manager2 = cls.Users.create(
            {
                "name": "Manager 2",
                "login": "manager2",
                "email": "manager2@example.com",
                "groups_id": [(6, 0, [cls.group_manager.id])],
            }
        )

    def test_create_server_from_template(self):
        """
        Create new server from template
        """
        self.assertFalse(
            self.Server.search(
                [("server_template_id", "=", self.server_template_sample.id)]
            ),
            "The servers shouldn't exist",
        )
        # add variable values to server template
        self.VariableValue.create(
            {
                "variable_id": self.variable_version.id,
                "server_template_id": self.server_template_sample.id,
                "value_char": "test",
            }
        )

        # add delete flight plan
        self.server_template_sample.plan_delete_id = self.plan_1.id

        # add server logs to template
        command_for_log = self.Command.create(
            {"name": "Get system info", "code": "uname -a"}
        )

        server_template_log = self.ServerLog.create(
            {
                "name": "Log from server template",
                "server_template_id": self.server_template_sample.id,
                "log_type": "command",
                "command_id": command_for_log.id,
            }
        )

        self.assertEqual(
            len(self.variable_version.value_ids),
            1,
            "The variable must have one value only",
        )

        server_log = self.ServerLog.search([("command_id", "=", command_for_log.id)])
        self.assertEqual(len(server_log), 1, "Server log must be one")

        # create new server from template
        new_server = self.ServerTemplate.create_server_from_template(
            self.server_template_sample.reference,
            "server_from_template",
            ipv4="0.0.0.0",
        )

        server = self.Server.search(
            [("server_template_id", "=", self.server_template_sample.id)]
        )
        self.assertEqual(new_server, server, "Servers must be the same")
        self.assertEqual(
            new_server.name,
            "server_from_template",
            "Server name must be server_from_template",
        )
        self.assertEqual(
            new_server.ip_v4_address, "0.0.0.0", "Server IP must be 0.0.0.0"
        )
        self.assertEqual(
            new_server.os_id, self.os_debian_10, "Server os must be Debian"
        )
        self.assertEqual(new_server.ssh_port, 22, "Server SSH Port must be 22")
        self.assertEqual(
            new_server.ssh_username, "admin", "Server SSH Username must be 'admin'"
        )
        self.assertEqual(
            new_server._get_secret_value("ssh_password"),
            "password",
            "Server SSH Password must be 'password'",
        )
        self.assertEqual(
            new_server.ssh_auth_mode, "p", "Server SSH Auth Mode must be 'p'"
        )
        self.assertEqual(
            len(self.variable_version.value_ids),
            2,
            "The variable must have two value only",
        )
        self.assertEqual(
            new_server.plan_delete_id,
            self.plan_1,
            "Server On Delete Plan must be 'Test plan 1'",
        )

        server_log = self.ServerLog.search([("command_id", "=", command_for_log.id)])
        self.assertEqual(len(server_log), 2, "Server log must be two")

        server_log = server_log.filtered(lambda rec: rec.server_id == new_server)
        self.assertNotEqual(server_log, server_template_log)

    def test_create_server_from_template_wizard(self):
        """
        Create new server from template from wizard
        """
        action = self.server_template_sample.action_create_server()
        wizard = (
            self.env["cx.tower.server.template.create.wizard"]  # pylint: disable=context-overridden we need a new clean context
            .with_context(action["context"])
            .new({})
        )
        self.assertEqual(
            self.server_template_sample,
            wizard.server_template_id,
            "Server Templates must be the same",
        )

        self.assertFalse(
            self.Server.search(
                [("server_template_id", "=", self.server_template_sample.id)]
            ),
            "The servers shouldn't exist",
        )

        wizard.update(
            {
                "name": "test",
                "ip_v4_address": "0.0.0.0",
                "use_sudo": "n",
                "partner_id": self.user_bob.partner_id.id,
                "os_id": self.os_debian_10.id,
                "tag_ids": [(4, self.tag_test_production.id)],
            }
        )
        action = wizard.action_confirm()

        server = self.Server.search(
            [("server_template_id", "=", self.server_template_sample.id)]
        )
        self.assertEqual(action["res_id"], server.id, "Server ids must be the same")
        self.assertEqual(
            server.partner_id, self.user_bob.partner_id, "Partner must be the same"
        )
        self.assertEqual(server.os_id, self.os_debian_10, "OS must be the same")
        self.assertEqual(
            server.tag_ids, self.tag_test_production, "Tag must be the same"
        )
        self.assertEqual(server.use_sudo, "n", "Use sudo must be the same")
        self.assertEqual(server.ip_v4_address, "0.0.0.0", "IP must be the same")
        self.assertEqual(server.name, "test", "Name must be the same")

    def test_create_server_from_template_action(self):
        """
        Create new server from action
        """
        name = "server from template"
        self.assertFalse(
            self.Server.search([("name", "=", name)]),
            "Server should not exist",
        )
        # add variable values to server template
        self.VariableValue.create(
            {
                "variable_id": self.variable_version.id,
                "server_template_id": self.server_template_sample.id,
                "value_char": "test template version",
            }
        )
        self.VariableValue.create(
            {
                "variable_id": self.variable_url.id,
                "server_template_id": self.server_template_sample.id,
                "value_char": "test template url",
            }
        )
        # add variable option
        variable_url_option = self.VariableOption.create(
            {
                "name": "localhost",
                "value_char": "localhost",
                "variable_id": self.variable_url.id,
            }
        )

        # create new server with new variable
        self.ServerTemplate.create_server_from_template(
            self.server_template_sample.reference,
            "server from template",
            ipv4="localhost",
            ssh_username="test",
            ssh_password="test",
            plan_delete_id=self.plan_1.id,
            configuration_variables={
                self.variable_version.reference: "test server version",
                "new_variable": "new_value",
            },
            configuration_variable_options={
                self.variable_url.reference: variable_url_option.reference,
            },
        )
        new_server = self.Server.search([("name", "=", name)])

        self.assertTrue(new_server, "Server must exist!")
        self.assertFalse(new_server.plan_delete_id, "On Delete Plan must be empty!")

        self.assertEqual(
            len(new_server.variable_value_ids), 3, "Should be 3 variable values!"
        )

        # check variable values
        var_version_value = new_server.variable_value_ids.filtered(
            lambda rec: rec.variable_id == self.variable_version
        )
        self.assertEqual(
            var_version_value.value_char,
            "test server version",
            "Version variable values should be with new values for "
            "server from template",
        )

        var_url_value = new_server.variable_value_ids.filtered(
            lambda rec: rec.variable_id == self.variable_url
        )
        self.assertEqual(
            var_url_value.value_char,
            variable_url_option.value_char,
            "Url variable values should be same as option value",
        )

        var_new_value = new_server.variable_value_ids.filtered(
            lambda rec: rec.variable_id.reference == "new_variable"
        )
        self.assertTrue(var_new_value, "New variable should exist on the server")
        self.assertEqual(
            var_new_value.value_char,
            "new_value",
            "New variable values should be 'new_values'",
        )

    def test_server_template_copy(self):
        """
        Test duplicating a Server Template with variable values and server logs
        """

        # A server template
        server_template = self.server_template_sample

        # Add variable values to the server template
        original_variable_value = self.VariableValue.create(
            {
                "variable_id": self.variable_version.id,
                "server_template_id": server_template.id,
                "value_char": "test",
            }
        )

        # Create a command for the server log
        command_for_log = self.Command.create(
            {
                "name": "Get system info",
                "code": "uname -a",
            }
        )

        # Add server logs to the template
        original_log = self.ServerLog.create(
            {
                "name": "Log from server template",
                "server_template_id": server_template.id,
                "log_type": "command",
                "command_id": command_for_log.id,
            }
        )

        # Duplicate the server template
        copied_template = server_template.copy()

        # Ensure the new server template was created with a new ID
        self.assertNotEqual(
            copied_template.id,
            server_template.id,
            "Copied server template should have a different ID from the original",
        )

        # Check that the copied template has the same number of variable values
        self.assertEqual(
            len(copied_template.variable_value_ids),
            len(server_template.variable_value_ids),
            (
                "Copied template should have the same "
                "number of variable values as the original"
            ),
        )

        # Ensure the variable itself was copied (check variable_id)
        copied_variable_value = copied_template.variable_value_ids
        self.assertEqual(
            copied_variable_value.variable_id.id,
            original_variable_value.variable_id.id,
            "Variable ID should be the same in the copied template",
        )
        self.assertEqual(
            copied_variable_value.value_char,
            original_variable_value.value_char,
            "Variable value should be the same in the copied template",
        )

        # Check that the copied template has the same number of server logs
        self.assertEqual(
            len(copied_template.server_log_ids),
            len(server_template.server_log_ids),
            (
                "Copied template should have the same "
                "number of server logs as the original"
            ),
        )

        # Ensure the first server log in the copied template matches the original
        copied_log = copied_template.server_log_ids
        self.assertEqual(
            copied_log.name,
            original_log.name,
            "Server log name should be the same in the copied template",
        )
        self.assertEqual(
            copied_log.command_id.id,
            original_log.command_id.id,
            "Command ID should be the same in the copied server log",
        )
        self.assertEqual(
            copied_log.command_id.code,
            original_log.command_id.code,
            "Command code should be the same in the copied server log",
        )

    def test_required_attribute_in_wizard_field(self):
        """
        Test that the 'required' attribute
        is correctly applied to the 'value_char' field
        in the wizard when the variable is marked as required.
        """
        # Create a required variable
        self.VariableValue.create(
            {
                "variable_id": self.variable_version.id,
                "server_template_id": self.server_template_sample.id,
                "value_char": "Test Value",
                "required": True,
            }
        )

        # Open the wizard
        wizard = self.env["cx.tower.server.template.create.wizard"].create(
            {
                "server_template_id": self.server_template_sample.id,
                "name": "Test Server",
                "ssh_username": "admin",
            }
        )

        # Checking that the 'required' flag is passed to the form context
        required_fields = [
            line.required
            for line in wizard.line_ids
            if line.variable_id == self.variable_version
        ]
        self.assertTrue(
            all(required_fields),
            "The 'required' attribute should be correctly "
            "applied to the 'value_char' field for required variables.",
        )

    def test_successful_server_creation_with_required_variables(self):
        """
        Test that a server is successfully created
        when all required variables are filled in the wizard.
        """
        # Add manager as user of template
        self.server_template_sample.user_ids = self.manager

        # Adding a required variable
        self.VariableValue.create(
            {
                "variable_id": self.variable_version.id,
                "server_template_id": self.server_template_sample.id,
                "value_char": "",
                "required": True,
            }
        )

        # Open the wizard and fill in the data as manager
        wizard = (
            self.env["cx.tower.server.template.create.wizard"]
            .with_user(self.manager)
            .create(
                {
                    "server_template_id": self.server_template_sample.id,
                    "name": "Test Server With Required Variables",
                    "ssh_username": "admin",
                    "line_ids": [
                        (
                            0,
                            0,
                            {
                                "variable_id": self.variable_version.id,
                                "required": True,
                            },
                        )
                    ],
                }
            )
        )

        # Fill in the value for the required variable
        with Form(wizard) as wizard_form:
            with wizard_form.line_ids.edit(0) as line:
                line.value_char = "Test Value"
            wizard_form.save()

        # Checking the successful creation of the server
        action = wizard.action_confirm()
        self.assertTrue(action, "Server should be created successfully.")

        # Checking that the server has been created
        server = self.Server.search(
            [
                ("name", "=", "Test Server With Required Variables"),
                ("server_template_id", "=", self.server_template_sample.id),
            ]
        )
        self.assertTrue(server, "Server should exist.")
        self.assertEqual(
            server.variable_value_ids.filtered(
                lambda v: v.variable_id == self.variable_version
            ).value_char,
            "Test Value",
            "The variable value should be saved correctly.",
        )

    def test_optional_variable_with_empty_value(self):
        """
        Test that an optional variable
        with an empty value is saved correctly
        in the wizard and does not block server creation.
        """
        # Adding an optional variable
        self.VariableValue.create(
            {
                "variable_id": self.variable_url.id,
                "server_template_id": self.server_template_sample.id,
                "value_char": "",
                "required": False,
            }
        )

        # Open the wizard
        wizard = self.env["cx.tower.server.template.create.wizard"].create(
            {
                "server_template_id": self.server_template_sample.id,
                "name": "Server With Optional Variable",
                "ssh_username": "admin",
                "line_ids": [
                    (
                        0,
                        0,
                        {
                            "variable_id": self.variable_url.id,
                            "value_char": "",
                            "required": False,
                        },
                    )
                ],
            }
        )

        # Checking that the wizard is saved without errors
        wizard.action_confirm()

        # Checking that the server has been created
        server = self.Server.search(
            [
                ("name", "=", "Server With Optional Variable"),
                ("server_template_id", "=", self.server_template_sample.id),
            ]
        )
        self.assertTrue(
            server, "Server should be created successfully with optional variables."
        )

        # Checking that an optional variable is saved with an empty value
        variable = server.variable_value_ids.filtered(
            lambda v: v.variable_id == self.variable_url
        )
        self.assertTrue(variable, "Optional variable should be attached to the server.")
        self.assertEqual(
            variable.value_char, "", "Optional variable should have an empty value."
        )

    def test_wizard_without_variables(self):
        """
        Test that the wizard does not display
        any variables if the server template has none.
        """
        # Removing all variables from the template
        self.VariableValue.search(
            [("server_template_id", "=", self.server_template_sample.id)]
        ).unlink()

        # Open the wizard
        wizard = self.env["cx.tower.server.template.create.wizard"].create(
            {
                "server_template_id": self.server_template_sample.id,
                "name": "Server Without Variables",
                "ssh_username": "admin",
            }
        )

        # Checking that the wizard does not contain variables
        self.assertFalse(wizard.line_ids, "Wizard should not display any variables.")

    def test_update_required_variable_value(self):
        """
        Test that the value of a required variable
        can be updated in the wizard and saved correctly.
        """
        # Adding a required variable
        self.VariableValue.create(
            {
                "variable_id": self.variable_version.id,
                "server_template_id": self.server_template_sample.id,
                "value_char": "Old Value",
                "required": True,
            }
        )

        # Open the wizard and update the variable value
        wizard = self.env["cx.tower.server.template.create.wizard"].create(
            {
                "server_template_id": self.server_template_sample.id,
                "name": "Server With Updated Variable",
                "ssh_username": "admin",
                "line_ids": [
                    (
                        0,
                        0,
                        {
                            "variable_id": self.variable_version.id,
                            "value_char": "New Value",
                            "required": True,
                        },
                    )
                ],
            }
        )
        wizard.action_confirm()

        # Checking that the variable value has been updated
        server = self.Server.search([("name", "=", "Server With Updated Variable")])
        variable = server.variable_value_ids.filtered(
            lambda v: v.variable_id == self.variable_version
        )
        self.assertEqual(
            variable.value_char,
            "New Value",
            "The variable value should be updated correctly.",
        )

    def test_optional_variable_handling(self):
        """
        Test that optional variables do not block server creation,
        even if their values are empty or missing.
        """
        # Adding an optional variable to the template
        self.VariableValue.create(
            {
                "variable_id": self.variable_url.id,
                "server_template_id": self.server_template_sample.id,
                "value_char": "",
                "required": False,
            }
        )

        # Specify an optional variable with an empty value
        values = self.server_template_sample._prepare_server_values(
            configuration_variables={self.variable_url.reference: ""}
        )

        # Checking that the optional variable is processed correctly
        variable_data = next(
            (
                v
                for v in values["variable_value_ids"]
                if v[2]["variable_id"] == self.variable_url.id
            ),
            None,
        )
        self.assertIsNotNone(
            variable_data,
            "The optional variable should be included "
            "in the server values even if empty.",
        )
        self.assertEqual(
            variable_data[2]["value_char"],
            "",
            "Optional variable should have an empty value.",
        )

    def test_server_creation_with_all_required_variables_removed(self):
        """
        Test that server creation fails if all required variables
        are removed in the wizard.

        Steps:
        1. Create a server template with required variables.
        2. Open the server creation wizard.
        3. Remove all required variables from the wizard.
        4. Attempt to create the server.

        Expected Result:
        - ValidationError is raised with a clear message listing missing variables.
        """
        # Create a server template with mandatory variables
        template = self.ServerTemplate.create(
            {
                "name": "Template with required variables",
                "ssh_port": 22,
                "ssh_username": "admin",
                "ssh_auth_mode": "p",
                "os_id": self.os_debian_10.id,
                "variable_value_ids": [
                    (
                        0,
                        0,
                        {
                            "variable_id": self.variable_path.id,
                            "value_char": "/var/log",
                            "required": True,
                        },
                    ),
                    (
                        0,
                        0,
                        {
                            "variable_id": self.variable_dir.id,
                            "value_char": "logs",
                            "required": True,
                        },
                    ),
                ],
            }
        )

        # Simulating the launch of a wizard with the removal of all variables
        configuration_variables = {}  # All variables removed

        # Checking that the server cannot be created
        with self.assertRaises(ValidationError) as cm:
            template._create_new_server(
                name="Server with missing variables",
                configuration_variables=configuration_variables,
            )

        # Checking that the error message contains all removed variables
        error_message = str(cm.exception)
        self.assertIn("Please resolve the following issues", error_message)
        self.assertIn("Missing variables: test_path_, test_dir", error_message)

    def test_partial_required_variables_provided(self):
        """
        Test that server creation fails if only some required variables
        are provided, and the error message includes both missing and empty variables.
        """
        # Create a template with mandatory variables
        template = self.ServerTemplate.create(
            {
                "name": "Template with partial variables",
                "variable_value_ids": [
                    (
                        0,
                        0,
                        {
                            "variable_id": self.variable_path.id,
                            "value_char": "/var/log",
                            "required": False,
                        },
                    ),
                    (
                        0,
                        0,
                        {
                            "variable_id": self.variable_dir.id,
                            "required": True,
                        },
                    ),
                ],
            }
        )

        # Launch the wizard and specify only some of the required variables
        configuration_variables = {"test_path_": "/var/log"}  # test_dir skipped

        # Checking that the server is not being created
        with self.assertRaises(ValidationError) as cm:
            template._create_new_server(
                name="Server with partial variables",
                configuration_variables=configuration_variables,
            )

        # Checking the error message
        error_message = str(cm.exception)
        self.assertIn("Missing variables: test_dir", error_message)
        self.assertNotIn("test_path_", error_message)  # test_path_ provided

    def test_empty_values_for_required_variables(self):
        """
        Test that server creation fails if required variables
        have empty values, and the error message includes these variables.
        """
        # Create a template with mandatory variables
        template = self.ServerTemplate.create(
            {
                "name": "Template with empty values",
                "variable_value_ids": [
                    (
                        0,
                        0,
                        {
                            "variable_id": self.variable_path.id,
                            "value_char": "",
                            "required": True,
                        },
                    ),
                    (
                        0,
                        0,
                        {
                            "variable_id": self.variable_dir.id,
                            "value_char": "",
                            "required": True,
                        },
                    ),
                ],
            }
        )

        # Run the wizard with empty values for all variables
        configuration_variables = {"test_path_": "", "test_dir": ""}

        # Checking that the server is not being created
        with self.assertRaises(ValidationError) as cm:
            template._create_new_server(
                name="Server with empty variables",
                configuration_variables=configuration_variables,
            )

        # Checking the error message
        error_message = str(cm.exception)
        self.assertIn("Empty values for variables: test_path_, test_dir", error_message)

    def test_with_partial_removed_variables_from_wizard(self):
        """
        Test that server creation only with specified
        variables from wizard and option
        """
        # create new variable option
        test_variable = self.Variable.create(
            {
                "name": "Test Variable",
                "variable_type": "s",
            }
        )
        option = self.VariableOption.create(
            {
                "name": "test",
                "value_char": "test",
                "variable_id": test_variable.id,
            }
        )

        # template with variables
        self.server_template_sample.write(
            {
                "variable_value_ids": [
                    (
                        0,
                        0,
                        {
                            "variable_id": self.variable_path.id,
                            "value_char": "/var/log",
                            "required": False,
                        },
                    ),
                    (
                        0,
                        0,
                        {
                            "variable_id": test_variable.id,
                            "option_id": option.id,
                            "required": False,
                        },
                    ),
                ],
            }
        )

        action = self.server_template_sample.action_create_server()

        # Open the wizard and fill in the data
        wizard = (
            self.env["cx.tower.server.template.create.wizard"]  # pylint: disable=context-overridden we new need a new clean context
            .with_context(action["context"])
            .create(
                {
                    "name": "Server from Template",
                    "ip_v4_address": "localhost",
                    "server_template_id": self.server_template_sample.id,
                }
            )
        )

        with Form(wizard) as wizard_form:
            wizard_form.line_ids.remove(0)
            wizard_form.save()

        wizard.action_confirm()

        server = self.server_template_sample.server_ids
        self.assertEqual(
            len(server.variable_value_ids), 1, "Server variable must be 1!"
        )
        self.assertEqual(
            server.variable_value_ids.value_char,
            option.value_char,
            "The variable value must be equal to the value from the option",
        )

    def test_manager_access_rights(self):
        """
        Test manager access rights for Server Template records:
        - Read: user is in user_ids or manager_ids
        - Write: user is in manager_ids
        """
        record = self.ServerTemplate.create(
            {
                "name": "Manager Access Test",
                "ssh_port": 22,
                "ssh_username": "admin",
                "ssh_auth_mode": "p",
                "os_id": self.os_debian_10.id,
                "user_ids": [(5, 0, 0)],
                "manager_ids": [(5, 0, 0)],
            }
        )

        # Case 1: No access rights
        records = self.ServerTemplate.with_user(self.manager1).search(
            [("id", "=", record.id)]
        )
        self.assertEqual(
            len(records),
            0,
            "Manager should not see the record if not added to user_ids or manager_ids",
        )

        # Case 2: Read access through user_ids
        record.write({"user_ids": [(4, self.manager1.id)]})
        records = self.ServerTemplate.with_user(self.manager1).search(
            [("id", "=", record.id)]
        )
        self.assertEqual(
            len(records),
            1,
            "Manager should see the record when added to user_ids",
        )

        # Write access should still be forbidden
        with self.assertRaises(AccessError):
            record.with_user(self.manager1).write({"name": "Updated Name"})

        # Case 3: Full access through manager_ids
        record.write(
            {
                "user_ids": [(5, 0, 0)],
                "manager_ids": [(4, self.manager1.id)],
            }
        )

        records = self.ServerTemplate.with_user(self.manager1).search(
            [("id", "=", record.id)]
        )
        self.assertEqual(
            len(records),
            1,
            "Manager should see the record when added to manager_ids",
        )

        # Write access should now work
        try:
            record.with_user(self.manager1).write({"name": "Updated Name"})
        except AccessError:
            self.fail("Manager should be able to update the record when in manager_ids")

    def test_manager_create_access(self):
        """
        Test that a manager can only create a Server Template record
        if they add themselves to manager_ids.
        """
        # Try to create without adding to manager_ids
        with self.assertRaises(AccessError):
            self.ServerTemplate.with_user(self.manager1).create(
                {
                    "name": "Create Access Test - Should Fail",
                    "ssh_port": 22,
                    "ssh_username": "admin",
                    "ssh_auth_mode": "p",
                    "os_id": self.os_debian_10.id,
                    "manager_ids": [(5, 0, 0)],
                }
            )

        # Create with manager_ids - should succeed
        record = self.ServerTemplate.with_user(self.manager1).create(
            {
                "name": "Create Access Test - Should Succeed",
                "ssh_port": 22,
                "ssh_username": "admin",
                "ssh_auth_mode": "p",
                "os_id": self.os_debian_10.id,
                "manager_ids": [(4, self.manager1.id)],
            }
        )
        self.assertEqual(
            len(self.ServerTemplate.search([("id", "=", record.id)])),
            1,
            "Manager should be able to create record when added to manager_ids",
        )

    def test_manager_delete_access(self):
        """
        Test that a manager can only delete a Server Template record if:
        - They are in manager_ids
        - They created the record
        """
        # Scenario 1: Manager1 creates and tries to delete their own record
        record = self.ServerTemplate.with_user(self.manager1).create(
            {
                "name": "Delete Access Test - Own Record",
                "ssh_port": 22,
                "ssh_username": "admin",
                "ssh_auth_mode": "p",
                "os_id": self.os_debian_10.id,
                "manager_ids": [(4, self.manager1.id)],
            }
        )

        try:
            record.with_user(self.manager1).unlink()
        except AccessError:
            self.fail(
                "Manager should be able to delete their own record if in manager_ids"
            )

        # Scenario 2: Manager2 creates record, Manager1 tries to delete
        record2 = self.ServerTemplate.with_user(self.manager2).create(
            {
                "name": "Delete Access Test - Other's Record",
                "ssh_port": 22,
                "ssh_username": "admin",
                "ssh_auth_mode": "p",
                "os_id": self.os_debian_10.id,
                "manager_ids": [(6, 0, [self.manager1.id, self.manager2.id])],
            }
        )

        # Manager1 should not be able to delete Manager2's record
        with self.assertRaises(AccessError):
            record2.with_user(self.manager1).unlink()

        # Remove Manager2 from manager_ids
        record2.write({"manager_ids": [(5, 0, 0)]})

        # Manager2 should not be able to delete their record now
        with self.assertRaises(AccessError):
            record2.with_user(self.manager2).unlink()

        # Scenario 3: Manager1 creates record but is later removed from manager_ids
        record3 = self.ServerTemplate.with_user(self.manager1).create(
            {
                "name": "Delete Access Test - Removed Manager",
                "ssh_port": 22,
                "ssh_username": "admin",
                "ssh_auth_mode": "p",
                "os_id": self.os_debian_10.id,
                "manager_ids": [(4, self.manager1.id)],
            }
        )

        # Remove Manager1 from manager_ids
        record3.write({"manager_ids": [(5, 0, 0)]})

        # Manager1 should not be able to delete their record after being removed
        with self.assertRaises(AccessError):
            record3.with_user(self.manager1).unlink()

    def test_server_template_reference_update(self):
        """Test server template reference update cascades to dependent models"""
        # 1. Add a variable value to server_template_sample
        variable_value = self.VariableValue.create(
            {
                "variable_id": self.variable_os.id,
                "value_char": "Ubuntu 20.04",
                "server_template_id": self.server_template_sample.id,
            }
        )

        # Store original references for comparison
        original_template_reference = self.server_template_sample.reference
        original_variable_value_reference = variable_value.reference

        # 2. Change the reference for server_template_sample to "super_template"
        self.server_template_sample.write({"reference": "super_template"})

        # 3. Verify that references are updated for dependent models
        # Invalidate models to refresh all references
        self.env["cx.tower.server.template"].invalidate_model(["reference"])
        self.env["cx.tower.variable.value"].invalidate_model(["reference"])

        # Check that server template reference was updated
        self.assertEqual(self.server_template_sample.reference, "super_template")
        self.assertNotEqual(
            self.server_template_sample.reference, original_template_reference
        )

        # Check that variable value reference was updated
        # to include the new template reference
        self.assertIn("super_template", variable_value.reference)
        self.assertNotEqual(variable_value.reference, original_variable_value_reference)

        # Verify the reference pattern for variable value follows the expected format:
        # <variable_reference>_<model_generic_reference>_<linked_model_generic_reference>_<linked_record_reference>  # noqa: E501
        expected_variable_pattern = (
            f"{self.variable_os.reference}_variable_value_server_template_"
            f"{self.server_template_sample.reference}"
        )
        self.assertEqual(variable_value.reference, expected_variable_pattern)
