"""Component tests for pipeline commit flow."""

from __future__ import annotations

from pathlib import Path

import pytest

from cascade_fm.commit import ConflictPolicy, commit_operation_output
from cascade_fm.pipeline import Pipeline


@pytest.mark.component
def test_filter_rename_commit_flow(tmp_path: Path) -> None:
    """End-to-end flow: filter -> rename -> commit."""
    source_dir = tmp_path / "source"
    target_dir = tmp_path / "target"
    source_dir.mkdir()
    target_dir.mkdir()

    jpg_a = source_dir / "a.jpg"
    txt_b = source_dir / "b.txt"
    jpg_c = source_dir / "c.jpg"
    jpg_a.write_text("A")
    txt_b.write_text("B")
    jpg_c.write_text("C")

    pipeline = Pipeline()
    filter_pane_id = pipeline.add_pane("filter_extension")
    rename_pane_id = pipeline.add_pane("rename_pattern")

    pipeline.set_pane_params(filter_pane_id, {"extensions": [".jpg"]})
    pipeline.set_pane_params(rename_pane_id, {"pattern": "{index}_{name}"})

    pipeline.update_browser_files([jpg_a, txt_b, jpg_c])

    rename_pane = pipeline.get_pane(rename_pane_id)

    assert [path.name for path in rename_pane.output_files] == ["1_a.jpg", "2_c.jpg"]

    commit_result = commit_operation_output(
        commit_intent=rename_pane.operation.commit_intent,
        source_files=rename_pane.operation.input_files,
        output_files=rename_pane.output_files,
        target_dir=target_dir,
    )

    assert commit_result.committed == 2
    assert commit_result.failed == 0
    assert commit_result.skipped == 0

    assert (target_dir / "1_a.jpg").read_text() == "A"
    assert (target_dir / "2_c.jpg").read_text() == "C"
    assert not (target_dir / "b.txt").exists()


@pytest.mark.component
def test_filter_rename_commit_flow_reports_skipped_conflict(tmp_path: Path) -> None:
    """End-to-end flow reports skipped items when conflicts are skipped."""
    source_dir = tmp_path / "source"
    target_dir = tmp_path / "target"
    source_dir.mkdir()
    target_dir.mkdir()

    jpg_a = source_dir / "a.jpg"
    jpg_a.write_text("A")

    (target_dir / "1_a.jpg").write_text("existing")

    pipeline = Pipeline()
    filter_pane_id = pipeline.add_pane("filter_extension")
    rename_pane_id = pipeline.add_pane("rename_pattern")

    pipeline.set_pane_params(filter_pane_id, {"extensions": [".jpg"]})
    pipeline.set_pane_params(rename_pane_id, {"pattern": "{index}_{name}"})

    pipeline.update_browser_files([jpg_a])

    rename_pane = pipeline.get_pane(rename_pane_id)

    commit_result = commit_operation_output(
        commit_intent=rename_pane.operation.commit_intent,
        source_files=rename_pane.operation.input_files,
        output_files=rename_pane.output_files,
        target_dir=target_dir,
        conflict_policy=ConflictPolicy.SKIP,
    )

    assert commit_result.committed == 0
    assert commit_result.failed == 0
    assert commit_result.skipped == 1
    assert (target_dir / "1_a.jpg").read_text() == "existing"


@pytest.mark.component
def test_filter_rename_commit_flow_overwrites_conflict(tmp_path: Path) -> None:
    """End-to-end flow should overwrite destination files when policy is overwrite."""
    source_dir = tmp_path / "source"
    target_dir = tmp_path / "target"
    source_dir.mkdir()
    target_dir.mkdir()

    jpg_a = source_dir / "a.jpg"
    jpg_a.write_text("fresh")

    existing_target = target_dir / "1_a.jpg"
    existing_target.write_text("old")

    pipeline = Pipeline()
    filter_pane_id = pipeline.add_pane("filter_extension")
    rename_pane_id = pipeline.add_pane("rename_pattern")

    pipeline.set_pane_params(filter_pane_id, {"extensions": [".jpg"]})
    pipeline.set_pane_params(rename_pane_id, {"pattern": "{index}_{name}"})
    pipeline.update_browser_files([jpg_a])

    rename_pane = pipeline.get_pane(rename_pane_id)

    commit_result = commit_operation_output(
        commit_intent=rename_pane.operation.commit_intent,
        source_files=rename_pane.operation.input_files,
        output_files=rename_pane.output_files,
        target_dir=target_dir,
        conflict_policy=ConflictPolicy.OVERWRITE,
    )

    assert commit_result.committed == 1
    assert commit_result.failed == 0
    assert commit_result.skipped == 0
    assert existing_target.read_text() == "fresh"


@pytest.mark.component
def test_filter_rename_commit_flow_auto_renames_conflict(tmp_path: Path) -> None:
    """End-to-end flow should auto-rename destination files on conflicts."""
    source_dir = tmp_path / "source"
    target_dir = tmp_path / "target"
    source_dir.mkdir()
    target_dir.mkdir()

    jpg_a = source_dir / "a.jpg"
    jpg_a.write_text("fresh")

    existing_target = target_dir / "1_a.jpg"
    existing_target.write_text("old")

    pipeline = Pipeline()
    filter_pane_id = pipeline.add_pane("filter_extension")
    rename_pane_id = pipeline.add_pane("rename_pattern")

    pipeline.set_pane_params(filter_pane_id, {"extensions": [".jpg"]})
    pipeline.set_pane_params(rename_pane_id, {"pattern": "{index}_{name}"})
    pipeline.update_browser_files([jpg_a])

    rename_pane = pipeline.get_pane(rename_pane_id)

    commit_result = commit_operation_output(
        commit_intent=rename_pane.operation.commit_intent,
        source_files=rename_pane.operation.input_files,
        output_files=rename_pane.output_files,
        target_dir=target_dir,
        conflict_policy=ConflictPolicy.AUTO_RENAME,
    )

    assert commit_result.committed == 1
    assert commit_result.failed == 0
    assert commit_result.skipped == 0
    assert existing_target.read_text() == "old"
    assert (target_dir / "1_a_1.jpg").read_text() == "fresh"
