import os
import stat

import pytest

from imapsync_bulk.accounts import parse_accounts
from imapsync_bulk.gen import main
from imapsync_bulk.presets import FULL_SYNC_EXTRA

CSV = "E-mail,Password\nalice@example.com,secret1\nbob@example.com,secret2\n"


def _csv(tmp_path, content=CSV):
    path = tmp_path / "comptes.csv"
    path.write_text(content)
    return path


def test_non_interactive_generation(tmp_path):
    out = tmp_path / "comptes.txt"
    code = main(
        [
            str(_csv(tmp_path)),
            "-o",
            str(out),
            "--host1",
            "old.example",
            "--host2",
            "new.example",
            "--yes",
        ]
    )
    assert code == 0
    accounts = parse_accounts(out.read_text())
    assert len(accounts) == 2
    assert accounts[0].host1 == "old.example"
    assert accounts[0].host2 == "new.example"


def test_full_sync_preset_is_written_by_default(tmp_path):
    out = tmp_path / "c.txt"
    main([str(_csv(tmp_path)), "-o", str(out), "--host1", "a", "--host2", "b", "--yes"])
    accounts = parse_accounts(out.read_text())
    assert all(a.extra == [FULL_SYNC_EXTRA] for a in accounts)


def test_full_sync_preset_is_not_destructive():
    """Le preset ne doit contenir aucune option de suppression."""
    assert "--delete2" not in FULL_SYNC_EXTRA
    assert "--delete" not in FULL_SYNC_EXTRA


def test_no_automap_leaves_folders_untouched(tmp_path):
    out = tmp_path / "c.txt"
    main(
        [
            str(_csv(tmp_path)),
            "-o",
            str(out),
            "--host1",
            "a",
            "--host2",
            "b",
            "--no-automap",
            "--yes",
        ]
    )
    assert all(a.extra == [] for a in parse_accounts(out.read_text()))


def test_custom_extra_replaces_the_preset(tmp_path):
    out = tmp_path / "c.txt"
    main(
        [
            str(_csv(tmp_path)),
            "-o",
            str(out),
            "--host1",
            "a",
            "--host2",
            "b",
            "--extra",
            "--justfolders --automap",
            "--yes",
        ]
    )
    assert parse_accounts(out.read_text())[0].extra == ["--justfolders", "--automap"]


def test_output_is_created_in_0600(tmp_path):
    out = tmp_path / "c.txt"
    main([str(_csv(tmp_path)), "-o", str(out), "--host1", "a", "--host2", "b", "--yes"])
    assert stat.S_IMODE(os.stat(out).st_mode) == 0o600


def test_default_output_is_the_csv_with_txt_suffix(tmp_path):
    csv_path = _csv(tmp_path)
    main([str(csv_path), "--host1", "a", "--host2", "b", "--yes"])
    assert csv_path.with_suffix(".txt").exists()


def test_generated_file_round_trips_through_the_official_parser(tmp_path):
    out = tmp_path / "c.txt"
    main(
        [
            str(_csv(tmp_path, 'E-mail,Password\nalice@x.fr,"mot de passe"\n')),
            "-o",
            str(out),
            "--host1",
            "old",
            "--host2",
            "new",
            "--yes",
        ]
    )
    (account,) = parse_accounts(out.read_text())
    assert account.password1 == "mot de passe"
    assert account.password2 == "mot de passe"


def test_invalid_csv_exits_2(tmp_path):
    bad = tmp_path / "bad.csv"
    bad.write_text("Nom,Quota\nAlice,5G\n")
    assert main([str(bad), "--host1", "a", "--host2", "b", "--yes"]) == 2


def test_yes_without_hosts_exits_2(tmp_path):
    assert main([str(_csv(tmp_path)), "--yes"]) == 2


def test_hosts_are_asked_once_when_not_given(tmp_path, monkeypatch):
    asked: list[str] = []

    def fake_ask(prompt, *args, **kwargs):
        asked.append(prompt)
        return "old.example" if "source" in prompt else "new.example"

    monkeypatch.setattr("imapsync_bulk.gen.Prompt.ask", staticmethod(fake_ask))
    monkeypatch.setattr(
        "imapsync_bulk.gen.Confirm.ask", staticmethod(lambda *a, **kw: True)
    )

    out = tmp_path / "c.txt"
    assert main([str(_csv(tmp_path)), "-o", str(out)]) == 0
    # Deux serveurs demandes une seule fois chacun, pas par compte.
    assert len(asked) == 2

    accounts = parse_accounts(out.read_text())
    assert len(accounts) == 2
    assert {a.host1 for a in accounts} == {"old.example"}
    assert {a.host2 for a in accounts} == {"new.example"}


def test_refusing_the_confirmation_writes_nothing(tmp_path, monkeypatch):
    monkeypatch.setattr(
        "imapsync_bulk.gen.Confirm.ask", staticmethod(lambda *a, **kw: False)
    )
    out = tmp_path / "c.txt"
    assert main([str(_csv(tmp_path)), "-o", str(out), "--host1", "a", "--host2", "b"]) == 0
    assert not out.exists()


def test_passwords_are_masked_in_the_preview(tmp_path, capsys, monkeypatch):
    monkeypatch.setenv("COLUMNS", "200")
    out = tmp_path / "c.txt"
    main([str(_csv(tmp_path)), "-o", str(out), "--host1", "a", "--host2", "b", "--yes"])
    printed = capsys.readouterr().out
    assert "secret1" not in printed
    assert "secret2" not in printed
    assert "alice@example.com" in printed
