"""
Unit test file.
"""

import os
import shutil
import subprocess
import sys
from dataclasses import dataclass
from pathlib import Path


@dataclass
class Requirements:
    content: str
    python_version: str | None = None

    def __post_init__(self):
        self.content = self.content.strip()

    def __repr__(self):
        return self.content


@dataclass
class PyProjectToml:
    content: str

    def __post_init__(self):
        self.content = self.content.strip()

    def __repr__(self):
        return self.content


@dataclass
class IsoEnvArgs:
    venv_path: Path
    build_info: Requirements | PyProjectToml


def _to_requirements(build_info: Requirements) -> PyProjectToml:
    req_lines = build_info.content.split("\n")
    req_lines = [line.strip() for line in req_lines if line.strip()]
    headers = ["# This file is generated by iso_env.", "# Do not edit this file."]
    headers.append("[project]")
    headers.append('name = "project"')
    if build_info.python_version:
        headers.append(f'requires-python = "{build_info.python_version}"')
    headers.append('version = "0.1.0"')
    if req_lines:
        headers.append("dependencies = [")
        for line in build_info.content.split("\n"):
            headers.append(f'  "{line}",')
        headers.append("]")
    return PyProjectToml("\n".join(headers))


def _to_pyproject_toml(build_info: Requirements | PyProjectToml) -> PyProjectToml:
    if isinstance(build_info, Requirements):
        return _to_requirements(build_info)
    return build_info


# def install(path: Path, requirements_text: str) -> None:
def install(args: IsoEnvArgs) -> None:
    """Uses isolated_environment to install aider."""
    # env: dict = dict(os.environ)
    try:
        path = args.venv_path
        if installed(args):
            return
        py_project_toml = _to_pyproject_toml(args.build_info)
        # Print installing message
        # Install aider using isolated_environment
        path.mkdir(exist_ok=True)
        subprocess.run(
            ["uv", "venv"],
            cwd=str(path),
            check=True,
            capture_output=True,
            text=True,
            shell=True,
        )
        py_project_toml_path = path / "pyproject.toml"
        py_project_toml_path.write_text(str(py_project_toml), encoding="utf-8")
        (path / "installed").touch()
    except KeyboardInterrupt:
        pass


def purge(venv_path: Path) -> int:
    print("Purging...")
    if not venv_path.exists():
        print("venv_path does not exist.")
        return 0
    try:
        shutil.rmtree(venv_path)
        print("purged successfully.")
        return 0
    except Exception as e:
        print(f"Error purging aider: {e}")
        return 1


def _santize(context: str) -> str:
    new_lines: list[str] = []
    for line in context.split("\n"):
        line = line.strip()
        if line:
            new_lines.append(line)
    return "\n".join(new_lines)


# def installed(venv_path: Path, requirements_text: str) -> bool:
def installed(args: IsoEnvArgs) -> bool:
    venv_path = args.venv_path
    if not venv_path.exists():
        return False
    pyproject_toml_path = venv_path / "pyproject.toml"
    if not pyproject_toml_path.exists():
        return False
    pyproject_toml = _to_pyproject_toml(args.build_info)
    if _santize(pyproject_toml_path.read_text()) != _santize(str(pyproject_toml)):
        return False
    return (venv_path / "installed").exists()


def run(
    args: IsoEnvArgs, cmd_list: list[str] | str, **process_args
) -> subprocess.CompletedProcess:
    """Runs the command using the isolated environment."""
    if not installed(args):
        purge(args.venv_path)
        install(args)

    python_exe = sys.executable
    if isinstance(cmd_list, list):
        full_cmd = [
            python_exe,
            "-m",
            "uv",
            "run",
            "--isolated",
            "--project",
            str(args.venv_path),
        ] + cmd_list
        full_cmd_str = subprocess.list2cmdline(full_cmd)
    else:
        full_cmd_str = f"{python_exe} -m uv run {cmd_list}"
    env = dict(os.environ)
    cp = subprocess.run(full_cmd_str, env=env, shell=True, **process_args)
    return cp


class IsoEnv:
    def __init__(self, args: IsoEnvArgs) -> None:
        self.args = args

    def run(
        self, cmd_list: list[str] | str, **process_args
    ) -> subprocess.CompletedProcess:
        return run(self.args, cmd_list, **process_args)
