import csv
import json
import subprocess
import sys
from pathlib import Path
import pytest
from csv_to_json import convert


@pytest.mark.parametrize("separator", [",", ";", "\t", "|"])
def test_formats_and_special_characters(tmp_path, separator):
    source, destination = tmp_path / "input.csv", tmp_path / "output.json"
    records = [["id", "description"], ["0007", 'Grüße, "quoted"\nsecond line'], ["008", ""]]
    with source.open("w", encoding="utf-8-sig", newline="") as stream:
        csv.writer(stream, delimiter=separator).writerows(records)
    assert convert(source, destination) == 2
    assert json.loads(destination.read_text(encoding="utf-8")) == [dict(zip(records[0], row)) for row in records[1:]]


@pytest.mark.parametrize("data, expected", [("", []), ("name\n", []), ("name\nAlice\n", [{"name":"Alice"}])])
def test_empty_and_single_column(tmp_path, data, expected):
    source, output = tmp_path / "i.csv", tmp_path / "o.json"
    source.write_text(data, encoding="utf-8")
    convert(source, output, delimiter=",")
    assert json.loads(output.read_text()) == expected


@pytest.mark.parametrize("data", ["a,a\n1,2\n", "a,\n1,2\n", "a,b\n1\n", 'a,b\n1,"unterminated\n'])
def test_invalid_data_creates_no_output(tmp_path, data):
    source, output = tmp_path / "i.csv", tmp_path / "o.json"
    source.write_text(data)
    with pytest.raises((ValueError, csv.Error)):
        convert(source, output, delimiter=",")
    assert not output.exists()


def test_no_overwrite(tmp_path):
    source, output = tmp_path / "i.csv", tmp_path / "o.json"
    source.write_text("a,b\n1,2\n")
    output.write_text("keep")
    with pytest.raises(FileExistsError):
        convert(source, output)
    assert output.read_text() == "keep"


def test_encoding_option(tmp_path):
    source, output = tmp_path / "i.csv", tmp_path / "o.json"
    source.write_bytes("name,city\nRené,Zürich\n".encode("cp1252"))
    convert(source, output, encoding="cp1252")
    assert json.loads(output.read_text(encoding="utf-8"))[0]["name"] == "René"


def test_cli_success_and_error(tmp_path):
    source, output = tmp_path / "i.tsv", tmp_path / "o.json"
    source.write_text("id\tvalue\n01\tx\n")
    script = str(Path(__file__).with_name("csv_to_json.py"))
    command = [sys.executable, script, str(source), str(output), "--delimiter", "tab"]
    first = subprocess.run(command, capture_output=True, text=True)
    assert first.returncode == 0
    assert json.loads(output.read_text()) == [{"id":"01", "value":"x"}]
    second = subprocess.run(command, capture_output=True, text=True)
    assert second.returncode == 1
    assert "Conversion failed" in second.stderr
