# Copyright 2022 ACSONE SA/NV
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html)

from contextlib import contextmanager

import odoo
from odoo import api
from odoo.tests import common

from extendable import context, main


def _get_addon_name(full_name: str) -> str:
    # The (Odoo) module name can be in the ``odoo.addons`` namespace
    # or not. For instance, module ``sale`` can be imported as
    # ``odoo.addons.sale`` (the right way) or ``sale`` (for backward
    # compatibility).
    module_parts = full_name.split(".")
    if len(module_parts) > 2 and module_parts[:2] == ["odoo", "addons"]:
        addon_name = full_name.split(".")[2]
    else:
        addon_name = full_name.split(".")[0]
    return addon_name


@contextmanager
def new_rollbacked_env():
    registry = odoo.registry(common.get_db_name())
    uid = odoo.SUPERUSER_ID
    cr = registry.cursor()
    try:
        yield api.Environment(cr, uid, {})
    finally:
        cr.rollback()  # we shouldn't have to commit anything
        cr.close()


class ExtendableMixin(object):
    @classmethod
    def init_extendable_registry(cls):
        with new_rollbacked_env() as env:
            builder = env["extendable.registry.loader"]
            # build the extendable classes of every installed addons
            extendable_registry = builder._init_global_registry()
            cls._extendable_registry = extendable_registry
            # ensure that we load only the extendable classes of the 'installed'
            # modules, not 'to install', which means we load only the
            # dependencies of the tested addons, not the siblings or
            # children addons
            builder.build_registry(extendable_registry, states=("installed",))
            # build the extendable classes of the current tested addon
            current_addon = _get_addon_name(cls.__module__)
            extendable_registry.init_registry([f"odoo.addons.{current_addon}.*"])
            cls.token = context.extendable_registry.set(cls._extendable_registry)

    @classmethod
    def backup_extendable_registry(cls):
        # Store the current extendable classes
        cls._initial_extendable_class_defs_by_module = (
            main._extendable_class_defs_by_module
        )
        # Use a copy of the current extendable classes
        main._extendable_class_defs_by_module = dict(
            cls._initial_extendable_class_defs_by_module
        )

    @classmethod
    def restore_extendable_registry(cls):
        # Restore the initial extendable classes
        main._extendable_class_defs_by_module = (
            cls._initial_extendable_class_defs_by_module
        )

    @classmethod
    def reset_extendable_registry(cls):
        context.extendable_registry.reset(cls.token)
