from __future__ import annotations

import inspect
import os
import sys
from typing import Sequence

from astroid import modutils
from astroid.interpreter._import import spec
from pylint.lint import utils

def register(linter):
    # very old pylint (/ astroid) versions not compatible with this plugin but
    # not really needing it either as they don't try importing stuff nearly as
    # hard
    if 'type' not in inspect.signature(spec.ModuleSpec).parameters:
        return

    # prevent pylint from messing with sys.path
    utils._augment_sys_path = lambda _: sys.path
    modutils.modpath_from_file = modpath_from_file
    spec._SPEC_FINDERS = (AddonsPackageFinder,) + spec._SPEC_FINDERS

    addons_path = os.environ.get('ADDONS_PATH')
    if addons_path:
        import odoo.addons
        for p in addons_path.split(os.pathsep):
            normp = os.path.normcase(os.path.abspath(p.strip()))
            odoo.addons.__path__.append(normp)

def modpath_from_file(filename, path):
    if filename == "./addons":
        return ['odoo', 'addons']
    return modutils.modpath_from_file_with_callback(
        filename,
        path,
        modutils.check_modpath_has_init,
    )

class AddonsPackageFinder(spec.Finder):
    """Finder which special cases odoo and odoo.addons, such that they're
    forcefully discovered as namespace packages since otherwise they get
    discovered as directory packages.
    """
    def find_module(
        self,
        modname: str,
        module_parts: Sequence[str],
        processed: list[str],
        submodule_path: Sequence[str] | None,
    ) -> spec.ModuleSpec | None:
        modname = '.'.join([*processed, modname])
        if modname in ('odoo', 'odoo.addons'):
            return spec.ModuleSpec(
                name=modname,
                location="",
                origin="namespace",
                type=spec.ModuleType.PY_NAMESPACE,
                submodule_search_locations=sys.modules[modname].__path__,
            )
        else:
            return None

    def contribute_to_path(self, spec: spec.ModuleSpec, processed: list[str]) -> Sequence[str] | None:
        return spec.submodule_search_locations

