from __future__ import annotations

import subprocess
from pathlib import Path

import tomllib
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
from hatchling.metadata.plugin.interface import MetadataHookInterface


class CustomMetaDataHook(MetadataHookInterface):
    """
    Custom metadata hook.
    """

    def update(self, metadata: dict[str, object]) -> None:
        """
        Update the metadata for the store package.

        Parameters
        ----------
        metadata
            The current metadata
        """
        source_path = Path(self.root, "..", "pyproject.toml")
        if source_path.exists():
            with source_path.open("rb") as f:
                source_metadata = tomllib.load(f)
                project = source_metadata["project"]
            result = subprocess.run(
                ["hatch", "version"],
                cwd=Path(self.root, ".."),
                check=True,
                capture_output=True,
                text=True,
            )
            version = result.stdout.strip()
            # Set version and name
            metadata["version"] = version
            metadata["name"] = f"{source_metadata['project']['name']}.store"
            # Set description, requires-python, license, authors, maintainers
            # keywords and classifiers
            for key in (
                "description",
                "requires-python",
                "license",
                "authors",
                "maintainers",
                "keywords",
                "classifiers",
            ):
                if key in project:
                    metadata[key] = project[key]
            # Set dependencies
            if "dependencies" in project:
                metadata["dependencies"] = [f"{project['name']}=={version}"]
            # Set optional dependencies
            if "optional-dependencies" in project:
                metadata["optional-dependencies"] = {}
                for group in project["optional-dependencies"]:
                    metadata["optional-dependencies"][group] = [
                        f"{project['name']}[{group}]=={version}",
                    ]
            # Set urls, gui-scripts, scripts, entry-points
            for key in ("urls", "gui-scripts", "scripts", "entry-points"):
                if key in project:
                    metadata[key] = {}
                    for entry, value in project[key].items():
                        metadata[key][entry] = value
            # Set readme if needed
            if (
                "package" in source_metadata["project"]
                and "store" in source_metadata["project"]["package"]
                and "readme" in source_metadata["project"]["package"]["store"]
            ):
                readme = source_metadata["project"]["package"]["store"]["readme"]
                metadata["readme"] = readme
                internal = Path(readme)
                external = Path("..", readme)
                if not internal.exists():
                    internal.symlink_to(external)


class CustomBuildHook(BuildHookInterface):
    """
    Custom build hook.
    """

    def initialize(
        self,
        version: str,
        build_data: dict[str, object],
    ) -> None:
        """
        Initialize the build process.

        Parameters
        ----------
        version
            The version (``standard``, ``editable``, ...)
        build_data
            The build data

        """
        if version == "standard":
            source_path = Path(self.root, "..", "pyproject.toml")
            if source_path.exists():
                with source_path.open("rb") as f:
                    source_metadata = tomllib.load(f)
                if (
                    "package" in source_metadata["project"]
                    and "store" in source_metadata["project"]["package"]
                    and "readme" in source_metadata["project"]["package"]["store"]
                ):
                    readme = source_metadata["project"]["package"]["store"]["readme"]
                    internal = Path(readme)
                    external = Path("..", readme)
                    if not internal.exists():
                        internal.symlink_to(external)

    def finalize(
        self,
        version: str,
        build_data: dict[str, object],
        artifact_path: str,
    ) -> None:
        """
        Finalize the build process.

        Parameters
        ----------
        version
            The version (``standard``, ``editable``, ...)
        build_data
            The build data
        artifact_path
            The artifact path

        """
        if version == "standard":
            source_path = Path(self.root, "..", "pyproject.toml")
            if source_path.exists():
                with source_path.open("rb") as f:
                    source_metadata = tomllib.load(f)
                if (
                    "package" in source_metadata["project"]
                    and "store" in source_metadata["project"]["package"]
                    and "readme" in source_metadata["project"]["package"]["store"]
                ):
                    readme = source_metadata["project"]["package"]["store"]["readme"]
                    internal = Path(readme)
                    internal.unlink(missing_ok=True)
