"""Step definitions for project_cli_delete_spec_alignment.feature.

Validates that the ``agents project delete`` command produces JSON/YAML output
with the ``deleted``, ``success``, and ``deleted_at`` fields as specified in
docs/specification.md (§agents project delete), matching the implementation
introduced in PR #6639.

These tests exercise the ``format_output`` function directly with the data
structure that the ``delete`` command produces, ensuring the spec-aligned
output fields are present and correctly structured.
"""

from __future__ import annotations

import json
from datetime import UTC, datetime
from typing import Any

from behave import given, then, when  # type: ignore[import-untyped]

# ---------------------------------------------------------------------------
# Background
# ---------------------------------------------------------------------------


@given("a project delete spec alignment CLI runner")
def step_pdsa_runner(context: Any) -> None:
    """Initialise context storage for the spec alignment tests."""
    context.pdsa_output = ""
    context.pdsa_project_name = ""


@given("a project delete spec alignment mocked repository")
def step_pdsa_mock_repo(context: Any) -> None:
    """No-op: these tests call format_output directly, no repo needed."""


# ---------------------------------------------------------------------------
# Given
# ---------------------------------------------------------------------------


@given('a project delete spec alignment project "{name}" exists')
def step_pdsa_project_exists(context: Any, name: str) -> None:
    """Record the project name that will be used in the delete output."""
    context.pdsa_project_name = name


# ---------------------------------------------------------------------------
# When
# ---------------------------------------------------------------------------


@when('I run project delete spec alignment for "{name}" with format "{fmt}"')
def step_pdsa_run_delete(context: Any, name: str, fmt: str) -> None:
    """Simulate the project delete command output by calling format_output directly.

    The ``delete`` command in ``cleveragents.cli.commands.project`` calls::

        format_output(
            {"deleted": name, "success": True, "deleted_at": datetime.now(tz=UTC)},
            output_format,
        )

    We replicate that call here and capture the output written to sys.stdout.
    """
    import sys
    from io import StringIO

    from cleveragents.cli.formatting import format_output

    deleted_at = datetime(2026, 4, 10, 19, 45, 43, 123456, tzinfo=UTC)
    data: dict[str, object] = {
        "deleted": name,
        "success": True,
        "deleted_at": deleted_at,
    }

    buf = StringIO()
    real_stdout = sys.stdout
    sys.stdout = buf
    try:
        format_output(data, fmt)
    finally:
        sys.stdout = real_stdout

    context.pdsa_output = buf.getvalue()
    context.pdsa_format = fmt


# ---------------------------------------------------------------------------
# Then
# ---------------------------------------------------------------------------


@then('the project delete spec alignment output should contain "{text}"')
def step_pdsa_output_contains(context: Any, text: str) -> None:
    """Assert the output contains the expected text."""
    output = context.pdsa_output
    assert text in output, f"Expected '{text}' in output but got:\n{output}"


@then('the project delete spec alignment output should not contain "{text}"')
def step_pdsa_output_not_contains(context: Any, text: str) -> None:
    """Assert the output does not contain the given text."""
    output = context.pdsa_output
    assert text not in output, (
        f"Expected '{text}' NOT in output but it was present:\n{output}"
    )


@then("the project delete spec alignment JSON success field should be true")
def step_pdsa_json_success_true(context: Any) -> None:
    """Parse the JSON envelope output and assert data.success is True."""
    output = context.pdsa_output.strip()
    envelope = json.loads(output)
    data = envelope.get("data", {})
    assert data.get("success") is True, (
        f"Expected data.success=True in JSON envelope but got: {envelope}"
    )


@then('the project delete spec alignment JSON deleted field should be "{name}"')
def step_pdsa_json_deleted_field(context: Any, name: str) -> None:
    """Parse the JSON envelope output and assert data.deleted matches the project name."""
    output = context.pdsa_output.strip()
    envelope = json.loads(output)
    data = envelope.get("data", {})
    assert data.get("deleted") == name, (
        f"Expected data.deleted='{name}' in JSON envelope but got: {envelope}"
    )
