import csv
import json
import subprocess
import sys
from pathlib import Path

import pytest

from json_to_csv import convert


def test_union_of_keys_escaping_and_scalar_values(tmp_path):
    source, output = tmp_path / "input.json", tmp_path / "output.csv"
    source.write_text(json.dumps([
        {"id": 1, "label": 'Grüße, "Wien"\nLine 2', "active": True},
        {"id": 2, "amount": 0, "active": False, "optional": None},
    ]), encoding="utf-8")
    assert convert(source, output) == (2, 5)
    with output.open(encoding="utf-8", newline="") as handle:
        reader = csv.DictReader(handle)
        rows = list(reader)
        assert reader.fieldnames == ["id", "label", "active", "amount", "optional"]
    assert rows == [
        {"id": "1", "label": 'Grüße, "Wien"\nLine 2', "active": "true", "amount": "", "optional": ""},
        {"id": "2", "label": "", "active": "false", "amount": "0", "optional": ""},
    ]


@pytest.mark.parametrize("raw", ['{}', '[1]', '[{"nested": {}}]', '[{"nested": []}]', '[{"value": NaN}]', '[invalid'])
def test_invalid_data_never_creates_output(tmp_path, raw):
    source, output = tmp_path / "input.json", tmp_path / "output.csv"
    source.write_text(raw, encoding="utf-8")
    with pytest.raises(ValueError):
        convert(source, output)
    assert not output.exists()


def test_empty_array(tmp_path):
    source, output = tmp_path / "input.json", tmp_path / "output.csv"
    source.write_text("[]", encoding="utf-8")
    assert convert(source, output) == (0, 0)
    assert output.read_bytes() == b""


def test_existing_output_is_preserved(tmp_path):
    source, output = tmp_path / "input.json", tmp_path / "output.csv"
    source.write_text('[{"id": 1}]', encoding="utf-8")
    output.write_text("keep this", encoding="utf-8")
    with pytest.raises(FileExistsError):
        convert(source, output)
    assert output.read_text(encoding="utf-8") == "keep this"


def test_cli_success_and_error_exit(tmp_path):
    source, output = tmp_path / "input.json", tmp_path / "output.csv"
    source.write_text('[{"id": 7}]', encoding="utf-8-sig")
    command = [sys.executable, str(Path(__file__).with_name("json_to_csv.py")), str(source), str(output)]
    success = subprocess.run(command, capture_output=True, text=True)
    assert success.returncode == 0, success.stderr
    assert output.read_text(encoding="utf-8") == "id\n7\n"
    failure = subprocess.run(command, capture_output=True, text=True)
    assert failure.returncode == 1
    assert "Error:" in failure.stderr
