from __future__ import annotations

import os

from vibelexity.circular_deps.resolvers.base import PathResolver
from vibelexity.circular_deps.resolvers.shared import check_under_root


class GoPathResolver(PathResolver):
    _STDLIB_PACKAGES = {
        "fmt",
        "os",
        "io",
        "net",
        "http",
        "strings",
        "bytes",
        "strconv",
        "math",
        "time",
        "encoding/json",
        "encoding/xml",
        "context",
        "sync",
        "log",
        "path/filepath",
        "path",
    }

    def resolve(self, module, current_file, root_dir):
        if self._is_stdlib(module):
            return None

        return self._resolve_local(module, current_file, root_dir)

    def _is_stdlib(self, module):
        for pkg in self._STDLIB_PACKAGES:
            if module == pkg or module.startswith(pkg + "/"):
                return True
        return False

    def _resolve_local(self, module, current_file, root_dir):
        module_path = module.replace("/", os.sep)
        current_dir = os.path.dirname(current_file)

        target_path = os.path.join(root_dir, module_path)
        resolved = self._find_go_file(target_path, root_dir)
        if resolved:
            return resolved

        parent_dir = os.path.dirname(current_dir)
        while parent_dir.startswith(root_dir):
            target_path = os.path.join(parent_dir, module_path)
            resolved = self._find_go_file(target_path, root_dir)
            if resolved:
                return resolved
            parent_dir = os.path.dirname(parent_dir)

        return None

    def _find_go_file(self, target_path, root_dir):
        if not os.path.exists(target_path):
            return None

        if os.path.isfile(target_path) and target_path.endswith(".go"):
            return check_under_root(target_path, root_dir)

        if os.path.isdir(target_path):
            go_files = [f for f in os.listdir(target_path) if f.endswith(".go")]
            if go_files:
                for go_file in go_files:
                    file_path = os.path.join(target_path, go_file)
                    if os.path.isfile(file_path):
                        return check_under_root(file_path, root_dir)

        go_file = target_path + ".go"
        if os.path.isfile(go_file):
            return check_under_root(go_file, root_dir)

        return None
