import json
from pathlib import Path

import pytest

from osx_backup.context import Context
from osx_backup.runner import RecordingRunner


def test_module_dir_created(ctx: Context) -> None:
    d = ctx.module_dir("brew")
    assert d == ctx.dest / "brew" and d.is_dir()


def test_module_dir_not_created_in_dry_run(ctx: Context) -> None:
    ctx.dry_run = True
    assert not ctx.module_dir("brew").exists()


def test_place_moves_existing_then_copies(ctx: Context) -> None:
    src = ctx.dest / "dotfiles" / ".zshrc"
    src.parent.mkdir(parents=True)
    src.write_text("new")
    target = ctx.home / ".zshrc"
    target.write_text("old")
    ctx.place(src, target)
    assert target.read_text() == "new"
    assert (ctx.pre_restore_dir / ".zshrc").read_text() == "old"


def test_place_dry_run_touches_nothing(ctx: Context) -> None:
    ctx.dry_run = True
    src = ctx.dest / "x"
    src.write_text("new")
    ctx.place(src, ctx.home / "x")
    assert not (ctx.home / "x").exists()


def test_place_missing_source_leaves_target_untouched(ctx: Context) -> None:
    target = ctx.home / ".zshrc"
    target.write_text("old")
    with pytest.raises(FileNotFoundError):
        ctx.place(ctx.dest / "missing", target)
    assert target.read_text() == "old"
    assert not ctx.pre_restore_dir.exists()


def test_place_twice_keeps_the_original_in_pre_restore(ctx: Context) -> None:
    first, second = ctx.dest / "a", ctx.dest / "b"
    first.write_text("A")
    second.write_text("B")
    target = ctx.home / "f"
    target.write_text("original")
    ctx.place(first, target)
    ctx.place(second, target)
    assert target.read_text() == "B"
    assert (ctx.pre_restore_dir / "f").read_text() == "original"
    assert (ctx.pre_restore_dir / "f.1").read_text() == "A"


def test_warn_keeps_square_brackets_literal(ctx: Context) -> None:
    ctx.warn("fichier [foo] absent")
    ctx.warn("motif [/x] invalide")
    out = ctx.console.export_text()
    assert "fichier [foo] absent" in out
    assert "motif [/x] invalide" in out


def test_log_writes_file(fake_home: Path, dest: Path) -> None:
    log = dest / "logs" / "run.log"
    ctx = Context(home=fake_home, dest=dest, runner=RecordingRunner(), log_path=log)
    ctx.log("hello")
    assert "hello" in log.read_text()


def test_write_json_and_text(ctx: Context) -> None:
    ctx.write_json(ctx.dest / "a" / "b.json", {"k": 1})
    assert json.loads((ctx.dest / "a" / "b.json").read_text()) == {"k": 1}
    ctx.dry_run = True
    ctx.write_text(ctx.dest / "nope.txt", "x")
    assert not (ctx.dest / "nope.txt").exists()
