"""Command module for models."""

from __future__ import annotations

import logging
import platform
import subprocess
from enum import Enum
from pathlib import Path
from typing import ClassVar

logger = logging.getLogger(__name__)
CWD = Path.cwd()
EXT = ".exe" if platform.system() == "Windows" else ""


class CommandRegisterError(Exception):
    """命令注册错误."""


class BaseCommand:
    """命令执行器."""

    OPTIONS: ClassVar[list[str]] = []

    def execute(self) -> bool:
        """执行命令."""
        build_command = self.get_build_command()
        logger.info(f"正在使用 {build_command} 进行构建, 执行选项: {self.OPTIONS}")
        subprocess.run([build_command, *self.OPTIONS], check=True)

    @classmethod
    def get_build_command(cls, project_dir: Path = CWD) -> str:
        """获取构建命令.

        Returns
        -------
            str: 构建命令

        Raises
        ------
            CommandRegisterError: 如果无法读取 pyproject.toml
        """
        pyproject_file = project_dir / "pyproject.toml"
        if pyproject_file.is_file():
            try:
                from pytola.dev.pypack.models.project import Project

                project = Project.from_toml_file(pyproject_file)
            except Exception as e:
                msg = f"无法读取 pyproject.toml: {e}"
                raise CommandRegisterError(msg) from e
            else:
                backend = project.build_backend
                if backend.startswith("poetry"):
                    build_tool = BuildTool.POETRY
                elif backend.startswith("hatch"):
                    build_tool = BuildTool.HATCH
                else:
                    build_tool = BuildTool.UV

                return build_tool.value

        return BuildTool.UV.value + EXT


class CommandRegister:
    """命令注册器."""

    _commands: ClassVar[dict[str, BaseCommand]] = {}
    _instance: CommandRegister | None = None
    _lock: bool = False

    @classmethod
    def register(cls, name: str) -> None:
        """注册命令."""

        def decorator(command_class: type[BaseCommand]) -> type[BaseCommand]:
            if name in cls._commands:
                msg = f"命令名称已注册: {name}"
                raise CommandRegisterError(msg)
            if not issubclass(command_class, BaseCommand):
                msg = f"{command_class} 必须继承 BaseCommand"
                raise CommandRegisterError(msg)

            logger.info(f"注册命令: {name}")
            cls._commands[name] = command_class
            return command_class

        return decorator

    @classmethod
    def get_command_class(cls, name: str) -> type[BaseCommand] | None:
        """获取命令."""
        return cls._commands.get(name, None)

    @classmethod
    def get_command_instance(cls, name: str) -> BaseCommand | None:
        """获取命令实例."""
        command_class = cls.get_command_class(name)
        if command_class:
            return command_class()
        return None

    @classmethod
    def list_commands(cls) -> list[str]:
        """获取命令列表."""
        return list(cls._commands.keys())


class BuildTool(Enum):
    """Enumeration of supported build tools.

    Attributes
    ----------
        UV: The uv build tool
        POETRY: The poetry build tool
        HATCH: The hatch build tool
    """

    UV = "uv"
    POETRY = "poetry"
    HATCH = "hatch"


@CommandRegister.register("build")
class BuildCommand(BaseCommand):
    """构建命令."""

    OPTIONS: ClassVar[list[str]] = ["build"]


@CommandRegister.register("clean")
class CleanCommand(BaseCommand):
    """清理命令."""

    OPTIONS: ClassVar[list[str]] = ["clean"]


if __name__ == "__main__":
    logger.info(f"构建命令清单: {CommandRegister.list_commands()}")

    CommandRegister.get_command_instance("build").execute()
    CommandRegister.get_command_instance("clean").execute()
