from __future__ import annotations

from dataclasses import dataclass
from datetime import datetime, timezone
from pathlib import Path
import re
import uuid

from cadquery import exporters

from shireforge.forge_engine.skill_registry import REGISTRY
from shireforge.security.safety_policy import SafetyProfile
from shireforge.generators.calibration_cube import (
    CubeParameters,
    build_cube,
)
from shireforge.validation.mesh_validator import (
    MeshValidationResult,
    validate_stl,
)


PROJECT_ROOT = Path(__file__).resolve().parents[3]
WORKSPACE_ROOT = (PROJECT_ROOT / "workspace").resolve()
UNSAFE_NAME = re.compile(r"[^A-Za-z0-9._-]+")


@dataclass(frozen=True)
class BuildResult:
    build_id: str
    build_directory: Path
    stl_path: Path
    step_path: Path
    validation: MeshValidationResult


def sanitize_project_name(name: str) -> str:
    cleaned = UNSAFE_NAME.sub("-", name.strip()).strip("._-")

    if not cleaned:
        raise ValueError("Project name contains no safe characters")

    return cleaned[:80]


def require_workspace_path(path: Path) -> Path:
    resolved = path.resolve()
    resolved.relative_to(WORKSPACE_ROOT)
    return resolved


def build_calibration_cube(
    parameters: CubeParameters,
    project_name: str = "calibration-cube",
    *,
    request_description: str = (
        "Create a harmless printer calibration cube"
    ),
    safety_profile: SafetyProfile | None = None,
) -> BuildResult:
    profile = (
        safety_profile
        if safety_profile is not None
        else SafetyProfile()
    )

    REGISTRY.authorize_request(
        "calibration-cube",
        request_description,
        profile,
    )

    safe_name = sanitize_project_name(project_name)

    timestamp = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
    build_id = f"{timestamp}-{uuid.uuid4().hex[:8]}"

    build_directory = require_workspace_path(
        WORKSPACE_ROOT
        / "projects"
        / safe_name
        / "builds"
        / build_id
    )
    build_directory.mkdir(parents=True, exist_ok=False)

    model = build_cube(parameters)

    stl_path = build_directory / f"{safe_name}.stl"
    step_path = build_directory / f"{safe_name}.step"

    exporters.export(model, str(stl_path))
    exporters.export(model, str(step_path))

    validation = validate_stl(stl_path)

    return BuildResult(
        build_id=build_id,
        build_directory=build_directory,
        stl_path=stl_path,
        step_path=step_path,
        validation=validation,
    )
