from pathlib import Path
from typing import Optional

from pydantic import ConfigDict, DirectoryPath

from ai_parade._toolkit.conversion_error import ConversionError
from ai_parade._toolkit.converters.ConversionResult import ConversionResult

from .api import InstallOptionsApi, ModelMetadataApi, PyTorchOptionsApi


class ModelMetadata(ModelMetadataApi):
	"""
	Model metadata -- everything needed to install and run the model and more
	"""

	model_config = ConfigDict(frozen=True, arbitrary_types_allowed=True)

	repository_path: Optional[DirectoryPath] = None
	"""
	Path to the repository, or None if the model is not locally available
	"""

	pytorch: Optional["PyTorchOptions"] = None  # type: ignore
	install: Optional["InstallOptions"] = None  # type: ignore

	def with_conversion_results(
		self,
		conversion_result_path: Path,
		conversion_result: ConversionResult | None = None,
	) -> tuple["ModelMetadata", Path]:
		conversion_result = conversion_result or ConversionResult.load(
			conversion_result_path
		)
		if conversion_result.status == "failed":
			raise ConversionError(
				self.format,
				conversion_result.format,
				"Using failed conversion result",
			)

		new_metadata = self.model_copy(
			update={
				"image_input": conversion_result.image_input,
				"format": conversion_result.format,
				"output": conversion_result.output,
				"get_custom_runner": None,
				"get_installer": None,
			}
		)
		return new_metadata, (conversion_result_path / conversion_result.path).resolve()


class InstallOptions(InstallOptionsApi):
	"""
	Installation options
	"""

	model_config = ConfigDict(frozen=True)
	build_system_dependencies: list[str]
	"""
	Build system dependencies from pyproject (build-system.requires)
	"""
	python: str
	"""
	The environment is initialized with python of this version.
	
	"""


class PyTorchOptions(PyTorchOptionsApi):
	"""
	PyTorch options
	"""

	model_config = ConfigDict(frozen=True, protected_namespaces=())
	pass
