"""Robot Framework helper for diff review artifact smoke tests.

Provides a CLI-style interface for Robot to invoke diff review
model creation, serialization, and builder operations.
Exit code 0 = success, 1 = failure.

Usage:
    python robot/helper_diff_review.py build-empty
    python robot/helper_diff_review.py build-create
    python robot/helper_diff_review.py build-rename
    python robot/helper_diff_review.py serialize-all
    python robot/helper_diff_review.py truncation
"""

from __future__ import annotations

import json
import sys
from pathlib import Path
from typing import Any

# Ensure the src directory is on the import path.
_SRC = str(Path(__file__).resolve().parents[1] / "src")
if _SRC not in sys.path:
    sys.path.insert(0, _SRC)

from cleveragents.domain.models.core.change import (  # noqa: E402
    ChangeEntry,
    ChangeOperation,
    SpecChangeSet,
)
from cleveragents.domain.models.core.diff_review import (  # noqa: E402
    DiffBuilder,
    DiffSerializer,
)


def _make_entry(
    plan_id: str,
    resource_id: str,
    operation: str,
    path: str,
    *,
    before_hash: str | None = None,
    after_hash: str | None = None,
) -> ChangeEntry:
    """Build a ChangeEntry with sensible defaults."""
    kwargs: dict[str, Any] = {
        "plan_id": plan_id,
        "resource_id": resource_id,
        "tool_name": "builtin/test-tool",
        "operation": ChangeOperation(operation),
        "path": path,
    }
    if before_hash is not None:
        kwargs["before_hash"] = before_hash
    if after_hash is not None:
        kwargs["after_hash"] = after_hash
    return ChangeEntry(**kwargs)


def _cmd_build_empty() -> int:
    """Build an artifact from an empty changeset."""
    cs = SpecChangeSet(plan_id="PLAN001")
    builder = DiffBuilder()
    artifact = builder.build(cs)
    assert artifact.total_changes == 0
    assert len(artifact.groups) == 0
    assert not artifact.truncated
    assert artifact.plan_id == "PLAN001"
    print("build-empty-ok")
    return 0


def _cmd_build_create() -> int:
    """Build an artifact with a CREATE change."""
    cs = SpecChangeSet(plan_id="PLAN001")
    entry = _make_entry("PLAN001", "RES001", "create", "src/main.py")
    cs.add_change(entry)

    builder = DiffBuilder()
    artifact = builder.build(
        cs,
        after_contents={"src/main.py": "print('hello')\n"},
    )
    assert artifact.total_changes == 1
    assert len(artifact.groups) == 1
    group = artifact.groups[0]
    assert group.resource_id == "RES001"
    assert len(group.entries) == 1
    assert group.entries[0].change_type == "create"
    assert group.entries[0].path == "src/main.py"
    assert "+++" in group.entries[0].diff_text
    print("build-create-ok")
    return 0


def _cmd_build_rename() -> int:
    """Build an artifact with rename detection."""
    cs = SpecChangeSet(plan_id="PLAN001")
    del_entry = _make_entry(
        "PLAN001", "RES001", "delete", "old/file.py", before_hash="abc123"
    )
    cre_entry = _make_entry(
        "PLAN001", "RES001", "create", "new/file.py", after_hash="abc123"
    )
    cs.add_change(del_entry)
    cs.add_change(cre_entry)

    builder = DiffBuilder()
    artifact = builder.build(cs)
    assert len(artifact.groups) == 1
    group = artifact.groups[0]
    assert len(group.entries) == 1
    assert group.entries[0].is_rename
    assert group.entries[0].rename_from == "old/file.py"
    assert group.entries[0].rename_to == "new/file.py"
    print("build-rename-ok")
    return 0


def _cmd_serialize_all() -> int:
    """Build an artifact and serialize to all formats."""
    cs = SpecChangeSet(plan_id="PLAN001")
    entry = _make_entry("PLAN001", "RES001", "create", "new.py")
    cs.add_change(entry)

    builder = DiffBuilder()
    artifact = builder.build(
        cs,
        after_contents={"new.py": "hello\n"},
        resource_names={"RES001": "my-resource"},
    )

    # Plain text
    plain = DiffSerializer.to_plain(artifact)
    assert "my-resource" in plain
    assert "Total changes: 1" in plain

    # JSON
    json_text = DiffSerializer.to_json(artifact)
    data = json.loads(json_text)
    assert "total_changes" in data
    assert "groups" in data
    assert data["total_changes"] == 1

    # Rich
    rich = DiffSerializer.to_rich(artifact)
    assert "[bold]" in rich
    assert "new.py" in rich

    print("serialize-all-ok")
    return 0


def _cmd_truncation() -> int:
    """Verify truncation with a small max_diff_size."""
    cs = SpecChangeSet(plan_id="PLAN001")
    entry = _make_entry("PLAN001", "RES001", "create", "big.py")
    cs.add_change(entry)

    builder = DiffBuilder(max_diff_size=50)
    artifact = builder.build(
        cs,
        after_contents={"big.py": "x" * 10000},
    )
    assert artifact.truncated
    assert artifact.groups[0].entries[0].truncated
    print("truncation-ok")
    return 0


def main() -> int:
    """Entry point called by Robot Framework ``Run Process``."""
    if len(sys.argv) < 2:
        print(
            "Usage: helper_diff_review.py "
            "<build-empty|build-create|build-rename|serialize-all|truncation>"
        )
        return 1

    command = sys.argv[1]

    if command == "build-empty":
        return _cmd_build_empty()
    if command == "build-create":
        return _cmd_build_create()
    if command == "build-rename":
        return _cmd_build_rename()
    if command == "serialize-all":
        return _cmd_serialize_all()
    if command == "truncation":
        return _cmd_truncation()

    print(f"Unknown command: {command}")
    return 1


if __name__ == "__main__":
    sys.exit(main())
