from __future__ import annotations

from app.config import settings
from app.models.schemas import AptComponent, AppManifest, DebComponent, DockerComponent
from app.utils.validators import validate_docker_registry, validate_url_host


class ManifestValidator:
    def validate(self, payload: dict) -> dict:
        manifest = AppManifest.model_validate(payload).model_dump(by_alias=True)
        components = []
        for raw_component in manifest["components"]:
            component_type = raw_component.get("type")
            if component_type == "deb":
                component = DebComponent.model_validate(raw_component).model_dump(by_alias=True)
                validate_url_host(component["downloadUrl"], settings.allowed_download_hosts)
                components.append(component)
            elif component_type == "apt":
                component = AptComponent.model_validate(raw_component).model_dump(by_alias=True)
                allowed_packages = set(settings.allowed_apt_packages)
                if "*" not in allowed_packages and component["packageName"] not in allowed_packages:
                    raise ValueError(
                        f"APT package is not allowed: {component['packageName']}"
                    )
                components.append(component)
            elif component_type == "docker":
                if not settings.allow_docker:
                    raise ValueError("Docker components are not enabled on this Agent")
                component = DockerComponent.model_validate(raw_component).model_dump(by_alias=True)
                validate_docker_registry(component["image"], settings.allowed_docker_registries)
                components.append(component)
            elif component_type == "docker_compose":
                if not settings.allow_docker_compose:
                    raise ValueError("Docker Compose components are not enabled on this Agent")
                raise ValueError("Docker Compose components are not implemented on this Agent")
            else:
                raise ValueError(f"Unsupported component type: {component_type}")
        manifest["components"] = sorted(components, key=lambda item: item.get("installOrder", 10))
        return manifest
