"""Tests for prodigy_teams.commands._recipe_file — loading recipes from YAML/JSON."""

from __future__ import annotations

from pathlib import Path

import pytest
import srsly

from prodigy_teams.commands._recipe_file import (
    _build_field_schema,
    _build_type_schema,
    load_recipes_file,
    uuid7,
)
from prodigy_teams.errors import CLIError


class TestUuid7:
    def test_returns_uuid(self):
        import uuid

        result = uuid7()
        assert isinstance(result, uuid.UUID)

    def test_unique(self):
        assert uuid7() != uuid7()


class TestLoadRecipesFile:
    def _write_recipes(self, path: Path, data: dict) -> Path:
        filepath = path / "recipes.json"
        srsly.write_json(filepath, data)
        return filepath

    def test_load_basic(self, tmp_path: Path):
        data = {
            "recipes": [
                {
                    "name": "test-recipe",
                    "title": "Test Recipe",
                    "description": "A test recipe",
                    "schema": {"fields": []},
                }
            ]
        }
        filepath = self._write_recipes(tmp_path, data)
        recipes = load_recipes_file(filepath)
        assert "test-recipe" in recipes
        assert recipes["test-recipe"].name == "test-recipe"
        assert recipes["test-recipe"].title == "Test Recipe"

    def test_missing_file_raises(self, tmp_path: Path):
        with pytest.raises(CLIError, match="not found"):
            load_recipes_file(tmp_path / "missing.json")

    def test_missing_recipes_key_raises(self, tmp_path: Path):
        filepath = self._write_recipes(tmp_path, {"other": []})
        with pytest.raises(CLIError, match="recipes"):
            load_recipes_file(filepath)

    def test_recipes_not_list_raises(self, tmp_path: Path):
        filepath = self._write_recipes(tmp_path, {"recipes": "not a list"})
        with pytest.raises(CLIError, match="list"):
            load_recipes_file(filepath)

    def test_filter_by_is_action(self, tmp_path: Path):
        data = {
            "recipes": [
                {"name": "task-recipe", "is_action": False, "schema": {"fields": []}},
                {"name": "action-recipe", "is_action": True, "schema": {"fields": []}},
            ]
        }
        filepath = self._write_recipes(tmp_path, data)

        tasks = load_recipes_file(filepath, is_action=False)
        assert "task-recipe" in tasks
        assert "action-recipe" not in tasks

        actions = load_recipes_file(filepath, is_action=True)
        assert "action-recipe" in actions
        assert "task-recipe" not in actions

    def test_filter_by_job_type(self, tmp_path: Path):
        data = {
            "recipes": [
                {
                    "name": "agent-recipe",
                    "job_type": "agent",
                    "schema": {"fields": []},
                },
                {
                    "name": "task-recipe",
                    "job_type": "task",
                    "schema": {"fields": []},
                },
            ]
        }
        filepath = self._write_recipes(tmp_path, data)
        agents = load_recipes_file(filepath, job_type="agent")
        assert "agent-recipe" in agents
        assert "task-recipe" not in agents

    def test_yaml_file(self, tmp_path: Path):
        filepath = tmp_path / "recipes.yaml"
        srsly.write_yaml(
            filepath,
            {
                "recipes": [
                    {"name": "yaml-recipe", "schema": {"fields": []}},
                ]
            },
        )
        recipes = load_recipes_file(filepath)
        assert "yaml-recipe" in recipes

    def test_recipe_detail_fields(self, tmp_path: Path):
        data = {
            "recipes": [
                {
                    "name": "full-recipe",
                    "title": "Full Recipe",
                    "description": "Desc",
                    "package_name": "my-pkg",
                    "container": "my-env",
                    "schema": {
                        "fields": [
                            {
                                "name": "model",
                                "type": {"name": "str"},
                                "props": {
                                    "name": "model",
                                    "title": "Model",
                                    "positional": True,
                                },
                            }
                        ],
                        "cli_names": {"--model": "model"},
                    },
                }
            ]
        }
        filepath = self._write_recipes(tmp_path, data)
        recipes = load_recipes_file(filepath)
        recipe = recipes["full-recipe"]
        assert recipe.description == "Desc"
        assert recipe.package is not None
        assert recipe.package.name == "my-pkg"
        assert recipe.package.container == "my-env"
        assert len(recipe.form_schema.fields) == 1
        assert recipe.form_schema.fields[0].name == "model"
        assert recipe.form_schema.fields[0].props.positional is True
        assert recipe.form_schema.cli_names == {"--model": "model"}


class TestBuildFieldSchema:
    def test_basic_field(self):
        data = {"name": "label", "type": {"name": "str"}, "props": {"title": "Label"}}
        field = _build_field_schema(data)
        assert field.name == "label"
        assert field.type.name == "str"
        assert field.props.title == "Label"

    def test_nested_fields(self):
        data = {
            "name": "parent",
            "type": {"name": "object"},
            "fields": [{"name": "child", "type": {"name": "int"}}],
        }
        field = _build_field_schema(data)
        assert field.fields is not None
        assert len(field.fields) == 1
        assert field.fields[0].name == "child"

    def test_default_type(self):
        data = {"name": "field_no_type"}
        field = _build_field_schema(data)
        assert field.type.name == "str"


class TestBuildTypeSchema:
    def test_basic(self):
        t = _build_type_schema({"name": "int"})
        assert t.name == "int"
        assert t.args is None

    def test_with_args(self):
        t = _build_type_schema({"name": "list", "args": [{"name": "str"}]})
        assert t.name == "list"
        assert t.args is not None
        assert len(t.args) == 1
        assert not isinstance(t.args[0], str)
        assert t.args[0].name == "str"

    def test_default_name(self):
        t = _build_type_schema({})
        assert t.name == "str"
