"""Load recipe definitions from a local YAML/JSON file.

This allows the CLI to discover recipes without contacting PAM.
"""

from __future__ import annotations

import uuid
from datetime import datetime
from pathlib import Path

import srsly
import uuid_utils

from prodigy_teams_pam_sdk.models import (
    FieldSchemaOutput,
    PackageSummary,
    PropsOutput,
    RecipeDetail,
    RecipeSchemaOutput,
    TypeSchemaOutput,
)

from ..errors import CLIError


def uuid7() -> uuid.UUID:
    """Generate a UUIDv7 (time-sortable) as a stdlib uuid.UUID."""
    return uuid.UUID(int=uuid_utils.uuid7().int)


def load_recipes_file(
    path: Path,
    is_action: bool | None = None,
    job_type: str | None = None,
) -> dict[str, RecipeDetail]:
    """Load recipe definitions from a YAML/JSON file.

    Returns a dict of recipe name → RecipeDetail (with synthetic IDs).
    """
    if not path.exists():
        raise CLIError(f"Recipes file not found: {path}")
    if path.suffix in (".yaml", ".yml"):
        data = srsly.read_yaml(path)
    else:
        data = srsly.read_json(path)
    if not isinstance(data, dict) or "recipes" not in data:
        raise CLIError(f"Recipes file must contain a 'recipes' key: {path}")
    recipes_list = data["recipes"]
    if not isinstance(recipes_list, list):
        raise CLIError(f"'recipes' must be a list in {path}")
    result: dict[str, RecipeDetail] = {}
    for entry in recipes_list:
        recipe = _build_recipe_detail(entry)
        if job_type is not None:
            if recipe.job_type == job_type:
                result[recipe.name] = recipe
        elif is_action is None or recipe.is_action == is_action:
            result[recipe.name] = recipe
    return result


def _build_recipe_detail(entry: dict) -> RecipeDetail:
    """Convert a raw dict from the recipes file into a RecipeDetail."""
    name = entry["name"]
    schema_data = entry.get("schema", {})
    fields = [_build_field_schema(f) for f in schema_data.get("fields", [])]
    cli_names = schema_data.get("cli_names", {})
    form_schema = RecipeSchemaOutput(
        name=name,
        fields=fields,
        title=schema_data.get("title"),
        description=schema_data.get("description"),
        view_id=schema_data.get("view_id"),
        cli_names=cli_names,
    )
    synthetic_id = uuid7()
    package_id = uuid7()
    now = datetime.now()
    is_action = entry.get("is_action", False)
    job_type = entry.get("job_type", "action" if is_action else "task")
    return RecipeDetail(
        id=synthetic_id,
        created=now,
        updated=now,
        org_id=uuid7(),
        package_id=package_id,
        name=name,
        title=entry.get("title"),
        description=entry.get("description"),
        job_type=job_type,
        is_action=is_action,
        is_latest=True,
        entry_point=None,
        form_schema=form_schema,
        cli_schema={},
        meta={},
        tasks=[],
        actions=[],
        package=PackageSummary(
            id=package_id,
            created=now,
            updated=now,
            name=entry.get("package_name", ""),
            version="0.0.0",
            container=entry.get("container", ""),
            recipe_count=0,
        ),
    )


def _build_field_schema(data: dict) -> FieldSchemaOutput:
    """Recursively build a FieldSchemaOutput from raw dict data."""
    type_data = data.get("type", {"name": "str"})
    type_schema = _build_type_schema(type_data)
    props_data = data.get("props", {})
    props = PropsOutput(
        name=props_data.get("name"),
        title=props_data.get("title"),
        description=props_data.get("description"),
        placeholder=props_data.get("placeholder"),
        value=props_data.get("value"),
        required=props_data.get("required"),
        positional=props_data.get("positional"),
        exists=props_data.get("exists"),
        validations=None,
        pattern=None,
        widget=None,
        choice=None,
        min=None,
        max=None,
        step=None,
        optional_title=None,
    )
    sub_fields = [_build_field_schema(f) for f in data.get("fields", [])]
    choice = [_build_field_schema(f) for f in data.get("choice", [])]
    return FieldSchemaOutput(
        name=data["name"],
        type=type_schema,
        props=props,
        fields=sub_fields,
        choice=choice,
    )


def _build_type_schema(data: dict) -> TypeSchemaOutput:
    """Build a TypeSchemaOutput from raw dict data."""
    args = None
    if "args" in data and data["args"] is not None:
        args = []
        for arg in data["args"]:
            if isinstance(arg, dict):
                args.append(_build_type_schema(arg))
            else:
                args.append(arg)
    return TypeSchemaOutput(
        name=data.get("name", "str"),
        args=args,
        object_type=data.get("object_type"),
    )
