from __future__ import annotations

import os

from vibelexity.circular_deps.resolvers.base import PathResolver


class PythonPathResolver(PathResolver):
    def resolve(self, module: str, current_file: str, root_dir: str) -> str | None:
        if module.startswith("."):
            return self._resolve_relative(module, current_file, root_dir)
        else:
            return self._resolve_absolute(module, current_file, root_dir)

    def _resolve_relative(
        self, module: str, current_file: str, root_dir: str
    ) -> str | None:
        current_dir = os.path.dirname(current_file)

        if module.startswith(".."):
            parts = []
            i = 0
            while i < len(module) and module[i] == ".":
                parts.append("..")
                i += 1
            if parts:
                module_suffix = module[len(parts) :].strip(".")
                target_dir = os.path.abspath(os.path.join(current_dir, *parts))
                if module_suffix:
                    target_path = os.path.join(
                        target_dir, module_suffix.replace(".", os.sep)
                    )
                else:
                    target_path = target_dir
            else:
                target_path = os.path.abspath(
                    os.path.join(current_dir, module.lstrip("."))
                )
        else:
            module_name = module.lstrip(".").strip(".")
            if module_name:
                target_path = os.path.abspath(
                    os.path.join(current_dir, module_name.replace(".", os.sep))
                )
            else:
                return None

        return self._find_py_file(target_path, root_dir)

    def _resolve_absolute(
        self, module: str, current_file: str, root_dir: str
    ) -> str | None:
        module_path = module.replace(".", os.sep)
        current_dir = os.path.dirname(current_file)

        for search_path in [current_dir, root_dir]:
            target_path = os.path.join(search_path, module_path)
            resolved = self._find_py_file(target_path, root_dir)
            if resolved:
                return resolved

        return None

    def _find_py_file(self, target_path: str, root_dir: str) -> str | None:
        if os.path.isfile(target_path) and target_path.endswith(".py"):
            return self._check_under_root(target_path, root_dir)

        if os.path.isdir(target_path):
            init_py = os.path.join(target_path, "__init__.py")
            if os.path.isfile(init_py):
                return self._check_under_root(init_py, root_dir)

        py_file = target_path + ".py"
        if os.path.isfile(py_file):
            return self._check_under_root(py_file, root_dir)

        return None

    def _check_under_root(self, path: str, root_dir: str) -> str | None:
        abs_path = os.path.abspath(path)
        abs_root = os.path.abspath(root_dir)
        if abs_path.startswith(abs_root):
            return abs_path
        return None
        abs_path = os.path.abspath(path)
        abs_root = os.path.abspath(root_dir)
        if abs_path.startswith(abs_root):
            return abs_path
        return None
