"""Unit tests for API utility methods."""

from __future__ import annotations

import json
from pathlib import Path

from cascade_fm.api import CascadeAPI
from cascade_fm.commit import CommitResult


def test_commit_result_to_dict() -> None:
    """Commit result serialization should expose shared payload fields."""
    result = CommitResult(committed=3, skipped=1, failed=2)

    payload = CascadeAPI.commit_result_to_dict(result)

    assert payload == {"committed": 3, "skipped": 1, "failed": 2}


def test_format_commit_summary_success() -> None:
    """Summary formatter should produce success payload for clean commits."""
    result = CommitResult(committed=2, skipped=0, failed=0)

    summary = CascadeAPI.format_commit_summary(result)

    assert summary["level"] == "success"
    assert summary["message"] == "✓ Committed 2 item(s)"
    assert summary["committed"] == 2
    assert summary["skipped"] == 0
    assert summary["failed"] == 0


def test_format_commit_summary_warning_skipped_only() -> None:
    """Summary formatter should report warning when conflicts are skipped."""
    result = CommitResult(committed=1, skipped=2, failed=0)

    summary = CascadeAPI.format_commit_summary(result)

    assert summary["level"] == "warning"
    assert summary["message"] == "⚠ Committed 1, skipped 2"
    assert summary["committed"] == 1
    assert summary["skipped"] == 2
    assert summary["failed"] == 0


def test_format_commit_summary_warning_with_failures() -> None:
    """Summary formatter should include skipped and failed counts."""
    result = CommitResult(committed=1, skipped=1, failed=2)

    summary = CascadeAPI.format_commit_summary(result)

    assert summary["level"] == "warning"
    assert summary["message"] == "⚠ Committed 1, skipped 1, failed 2"
    assert summary["committed"] == 1
    assert summary["skipped"] == 1
    assert summary["failed"] == 2


def test_save_workflow_persists_json(tmp_path: Path) -> None:
    """save_workflow should write a JSON file in workflow directory."""
    api = CascadeAPI(workflow_dir=tmp_path)
    pipeline = {
        "id": "pipeline-1",
        "panes": [{"id": "pane_1", "operation": "filter_extension", "params": {}}],
    }

    saved = api.save_workflow("My Workflow", pipeline)

    assert saved is True
    workflow_file = tmp_path / "My_Workflow.json"
    assert workflow_file.exists()

    payload = json.loads(workflow_file.read_text(encoding="utf-8"))
    assert payload["name"] == "My Workflow"
    assert payload["version"] == 1
    assert payload["pipeline"] == pipeline


def test_load_workflow_restores_pipeline_state(tmp_path: Path) -> None:
    """load_workflow should restore id and panes from saved workflow payload."""
    api = CascadeAPI(workflow_dir=tmp_path)
    pipeline = {
        "id": "pipeline-restore",
        "panes": [{"id": "pane_2", "operation": "save_to", "params": {"target_dir": "/tmp"}}],
    }
    payload = {
        "name": "restore",
        "version": 1,
        "pipeline": pipeline,
    }
    (tmp_path / "restore.json").write_text(json.dumps(payload), encoding="utf-8")

    loaded = api.load_workflow("restore")

    assert loaded == pipeline


def test_load_workflow_preserves_additional_payload_fields(tmp_path: Path) -> None:
    """load_workflow should preserve non-core fields like browser session context."""
    api = CascadeAPI(workflow_dir=tmp_path)
    pipeline = {
        "id": "pipeline-restore",
        "browser": {
            "path": "/tmp/photos",
            "selected_files": ["/tmp/photos/a.jpg"],
        },
        "panes": [{"id": "pane_1", "operation": "image_transform", "params": {"action": "rotate", "angle": 90}}],
    }
    payload = {
        "name": "restore-browser",
        "version": 1,
        "pipeline": pipeline,
    }
    (tmp_path / "restore-browser.json").write_text(json.dumps(payload), encoding="utf-8")

    loaded = api.load_workflow("restore-browser")

    assert loaded["id"] == pipeline["id"]
    assert loaded["panes"] == pipeline["panes"]
    assert loaded["browser"] == pipeline["browser"]


def test_load_workflow_missing_file_returns_current_pipeline(tmp_path: Path) -> None:
    """load_workflow should fallback to current pipeline for unknown names."""
    api = CascadeAPI(workflow_dir=tmp_path)

    loaded = api.load_workflow("does-not-exist")

    assert "id" in loaded
    assert loaded["panes"] == []


def test_delete_workflow_removes_existing_file(tmp_path: Path) -> None:
    """delete_workflow should remove persisted workflow file."""
    api = CascadeAPI(workflow_dir=tmp_path)
    pipeline = {"id": "pipeline-delete", "panes": []}
    assert api.save_workflow("to-delete", pipeline) is True

    deleted = api.delete_workflow("to-delete")

    assert deleted is True
    assert not (tmp_path / "to-delete.json").exists()


def test_delete_workflow_missing_file_is_success(tmp_path: Path) -> None:
    """delete_workflow should be idempotent for non-existent files."""
    api = CascadeAPI(workflow_dir=tmp_path)

    deleted = api.delete_workflow("missing")

    assert deleted is True


def test_get_workflow_age_seconds_returns_none_for_missing(tmp_path: Path) -> None:
    """Workflow age helper should return None for missing workflow files."""
    api = CascadeAPI(workflow_dir=tmp_path)

    age = api.get_workflow_age_seconds("missing")

    assert age is None


def test_get_workflow_age_seconds_returns_non_negative_for_existing(tmp_path: Path) -> None:
    """Workflow age helper should return a non-negative age for existing files."""
    api = CascadeAPI(workflow_dir=tmp_path)
    assert api.save_workflow("existing", {"id": "pipeline", "panes": []}) is True

    age = api.get_workflow_age_seconds("existing")

    assert age is not None
    assert age >= 0.0
