"""Sandboxed builds for Forge skills that are not yet certified."""

from __future__ import annotations

from dataclasses import asdict, dataclass
from datetime import datetime, timezone
from pathlib import Path
import json
import uuid

from cadquery import exporters

from shireforge.forge_engine.skill_registry import REGISTRY
from shireforge.generators.fitted_storage_box import (
    FittedBoxParameters,
    build_fitted_box,
)
from shireforge.security.safety_policy import (
    POLICY_VERSION,
    SafetyProfile,
    require_allowed,
)
from shireforge.validation.mesh_validator import (
    MeshValidationResult,
    validate_stl,
)


PROJECT_ROOT = Path(__file__).resolve().parents[3]
LEARNING_ROOT = (
    PROJECT_ROOT / "workspace" / "learning"
).resolve()


@dataclass(frozen=True)
class LearningPart:
    name: str
    stl_path: Path
    step_path: Path
    validation: MeshValidationResult


@dataclass(frozen=True)
class LearningBuildResult:
    build_id: str
    build_directory: Path
    parts: tuple[LearningPart, ...]
    report_path: Path
    safety_record_path: Path

    @property
    def passed(self) -> bool:
        return all(part.validation.passed for part in self.parts)


def build_fitted_box_learning(
    parameters: FittedBoxParameters,
    *,
    request_description: str = (
        "Create a harmless fitted storage box and removable lid"
    ),
    safety_profile: SafetyProfile | None = None,
) -> LearningBuildResult:
    skill = REGISTRY.get("fitted-storage-box")

    if skill.status != "learning":
        raise RuntimeError(
            "This pipeline is only for skills in learning status"
        )

    profile = safety_profile or SafetyProfile()
    decision = require_allowed(request_description, profile)

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

    build_directory = (
        LEARNING_ROOT
        / skill.skill_id
        / "builds"
        / build_id
    ).resolve()
    build_directory.relative_to(LEARNING_ROOT)
    build_directory.mkdir(parents=True, exist_ok=False)

    safety_record_path = (
        build_directory / "safety-decision.json"
    )
    safety_record_path.write_text(
        json.dumps(
            {
                "policy_version": POLICY_VERSION,
                "build_id": build_id,
                "skill_id": skill.skill_id,
                "request": request_description,
                "status": decision.status.value,
                "code": decision.code,
                "reason": decision.reason,
                "profile": asdict(profile),
            },
            indent=2,
        )
        + "\n",
        encoding="utf-8",
    )

    model = build_fitted_box(parameters)
    parts: list[LearningPart] = []

    for name, solid in (
        ("box", model.box),
        ("lid", model.lid),
    ):
        stl_path = build_directory / f"{name}.stl"
        step_path = build_directory / f"{name}.step"

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

        parts.append(
            LearningPart(
                name=name,
                stl_path=stl_path,
                step_path=step_path,
                validation=validate_stl(stl_path),
            )
        )

    report_path = build_directory / "learning-report.json"
    report_path.write_text(
        json.dumps(
            {
                "build_id": build_id,
                "skill_id": skill.skill_id,
                "certification_status": skill.status,
                "parameters": asdict(parameters),
                "designed_clearance_per_side_mm": (
                    parameters.lid_clearance
                ),
                "lid_internal_opening_mm": [
                    model.lid_internal_length,
                    model.lid_internal_width,
                ],
                "parts": [
                    {
                        "name": part.name,
                        "validation_passed": (
                            part.validation.passed
                        ),
                        "dimensions_mm": (
                            part.validation.dimensions
                        ),
                        "triangle_count": (
                            part.validation.triangle_count
                        ),
                        "watertight": (
                            part.validation.watertight
                        ),
                        "volume_mm3": part.validation.volume,
                    }
                    for part in parts
                ],
            },
            indent=2,
        )
        + "\n",
        encoding="utf-8",
    )

    return LearningBuildResult(
        build_id=build_id,
        build_directory=build_directory,
        parts=tuple(parts),
        report_path=report_path,
        safety_record_path=safety_record_path,
    )
