from __future__ import annotations

import importlib
from pathlib import Path
from typing import Any


def _jl() -> Any:
    juliacall = importlib.import_module("juliacall")
    return getattr(juliacall, "Main")


def install_macroenergy_jl(
    *,
    project_path: str | Path | None = None,
    url: str | None = None,
    rev: str | None = None,
) -> None:
    """Install MacroEnergy.jl into the active Julia environment.

    Args:
        project_path: Optional Julia project to activate before installation.
        url: Optional git URL for installing from a specific repository.
        rev: Optional git revision/branch/tag when `url` is provided.
    """
    jl = _jl()
    _activate_project(project_path)
    jl.seval("using Pkg")

    if url:
        jl.macroenergy_url = url
        jl.macroenergy_rev = rev
        jl.seval(
            """
            if isnothing(macroenergy_rev)
                Pkg.add(Pkg.PackageSpec(url=macroenergy_url))
            else
                Pkg.add(Pkg.PackageSpec(url=macroenergy_url, rev=macroenergy_rev))
            end
            """
        )
    else:
        jl.seval('Pkg.add("MacroEnergy")')


def compile_macroenergy_jl(*, project_path: str | Path | None = None) -> None:
    """Compile and load MacroEnergy.jl in the active Julia environment.

    Args:
        project_path: Optional Julia project to activate before compilation.
    """
    jl = _jl()
    _activate_project(project_path)
    jl.seval("using Pkg")
    jl.seval("using MacroEnergy")


def setup_macroenergy_jl(
    *,
    project_path: str | Path | None = None,
    url: str | None = None,
    rev: str | None = None,
) -> None:
    """Install and compile MacroEnergy.jl in one call.

    Args:
        project_path: Optional Julia project to activate before setup.
        url: Optional git URL for installing from a specific repository.
        rev: Optional git revision/branch/tag when `url` is provided.
    """
    install_macroenergy_jl(project_path=project_path, url=url, rev=rev)
    compile_macroenergy_jl(project_path=project_path)


def _activate_project(project_path: str | Path | None) -> None:
    if project_path is None:
        return

    jl = _jl()
    resolved_path = str(Path(project_path).resolve())
    jl.project_path = resolved_path
    jl.seval('using Pkg; Pkg.activate(project_path)')
