import pytest

from imapsync_bulk.accounts import (
    AccountFileError,
    load_accounts,
    looks_like_csv,
    parse_csv_accounts,
)

HEADER = "host1,email1,password1,host2,email2,password2"
CSV = (
    f"{HEADER}\n"
    "imap.ancien.fr,contact@client.fr,ANCIEN1,imap.nouveau.fr,contact@client.fr,NOUVEAU1\n"
    "imap.ancien.fr,facturation@client.fr,ANCIEN2,imap.nouveau.fr,facturation@client.fr,NOUVEAU2\n"
)


def test_detects_the_csv_format():
    assert looks_like_csv(CSV)


def test_does_not_mistake_the_official_format_for_csv():
    assert not looks_like_csv("h1;u1;p1;h2;u2;p2;;\n")


def test_parses_the_requested_header():
    accounts = parse_csv_accounts(CSV)
    assert len(accounts) == 2
    first = accounts[0]
    assert first.host1 == "imap.ancien.fr"
    assert first.user1 == "contact@client.fr"
    assert first.password1 == "ANCIEN1"
    assert first.host2 == "imap.nouveau.fr"
    assert first.user2 == "contact@client.fr"
    assert first.password2 == "NOUVEAU1"


def test_passwords_with_shell_metacharacters_survive():
    """Le CSV supprime le probleme de quoting : rien ne passe par le shell."""
    nasty = "*Fez7*oH#rJ=Hd@4i%Sb"
    csv_text = f"{HEADER}\nh1,u1,{nasty},h2,u2,autre\n"
    (account,) = parse_csv_accounts(csv_text)
    assert account.password1 == nasty


def test_password_with_spaces_and_quotes():
    csv_text = f'{HEADER}\nh1,u1,"mot de passe ""avec"" quotes",h2,u2,p2\n'
    (account,) = parse_csv_accounts(csv_text)
    assert account.password1 == 'mot de passe "avec" quotes'


def test_semicolon_in_a_value_is_refused():
    csv_text = f"{HEADER}\nh1,u1,mot;de;passe,h2,u2,p2\n"
    with pytest.raises(AccountFileError, match="reserve"):
        parse_csv_accounts(csv_text)


def test_semicolon_delimited_csv_is_supported():
    csv_text = HEADER.replace(",", ";") + "\nh1;u1;p1;h2;u2;p2\n"
    (account,) = parse_csv_accounts(csv_text)
    assert account.host1 == "h1"


def test_user1_alias_is_accepted():
    csv_text = "host1,user1,password1,host2,user2,password2\nh1,u1,p1,h2,u2,p2\n"
    (account,) = parse_csv_accounts(csv_text)
    assert account.user1 == "u1"


def test_optional_extra_column():
    csv_text = f"{HEADER},extra\nh1,u1,p1,h2,u2,p2,--justfolders --automap\n"
    (account,) = parse_csv_accounts(csv_text)
    assert account.extra == ["--justfolders", "--automap"]


def test_missing_column_is_named():
    with pytest.raises(AccountFileError, match="host2"):
        parse_csv_accounts("host1,email1,password1\nh1,u1,p1\n")


def test_empty_value_is_reported_with_its_line():
    with pytest.raises(AccountFileError, match="ligne 2"):
        parse_csv_accounts(f"{HEADER}\nh1,,p1,h2,u2,p2\n")


def test_blank_rows_are_skipped():
    assert len(parse_csv_accounts(f"{HEADER}\nh1,u1,p1,h2,u2,p2\n,,,,,\n")) == 1


def test_load_accounts_dispatches_on_content(tmp_path):
    csv_path = tmp_path / "comptes.csv"
    csv_path.write_text(CSV)
    assert len(load_accounts(csv_path)) == 2

    txt_path = tmp_path / "comptes.txt"
    txt_path.write_text("h1;u1;p1;h2;u2;p2;;\n")
    assert len(load_accounts(txt_path)) == 1


def test_load_accounts_handles_a_bom(tmp_path):
    path = tmp_path / "comptes.csv"
    path.write_bytes(("﻿" + CSV).encode("utf-8"))
    assert len(load_accounts(path)) == 2


def test_extension_does_not_decide_the_format(tmp_path):
    """Un CSV nomme .txt doit quand meme etre reconnu."""
    path = tmp_path / "comptes.txt"
    path.write_text(CSV)
    assert len(load_accounts(path)) == 2
