import csv
import io

import pytest
from src.routers.csv_helpers import serialize_csv


class TestSerializeCsv:
    def test_serializes_with_bom(self) -> None:
        """BOM付きでCSVを生成する。"""
        result = serialize_csv(["ID"], [{"ID": "0001"}])

        assert result.startswith("\ufeff")

    def test_quotes_all_values(self) -> None:
        """ヘッダーと値をすべてクォートする。"""
        result = serialize_csv(["ID", "名称"], [{"ID": "0001", "名称": "ユーザー1"}], bom=False)

        assert result == '"ID","名称"\r\n"0001","ユーザー1"\r\n'

    def test_serializes_template_with_header_only(self) -> None:
        """ヘッダーのみのCSVを生成する。"""
        result = serialize_csv(["ID", "名称"], [])

        assert result == '\ufeff"ID","名称"\r\n'

    def test_serializes_none_as_empty_value(self) -> None:
        """None は空文字として出力する。"""
        result = serialize_csv(["ID", "メールアドレス"], [{"ID": "0001", "メールアドレス": None}], bom=False)

        assert result == '"ID","メールアドレス"\r\n"0001",""\r\n'

    @pytest.mark.parametrize(
        ("input_value", "expected"),
        [
            ("=CMD('calc')", "'=CMD('calc')"),
            ("+SUM(A1:A10)", "'+SUM(A1:A10)"),
            ("-1+1", "'-1+1"),
            ("@import('evil')", "'@import('evil')"),
            ("\tcmd", "'\tcmd"),
            ("\rmalicious", "'\rmalicious"),
        ],
    )
    def test_escapes_dangerous_prefixes(self, input_value: str, expected: str) -> None:
        """危険な先頭文字を持つ値にシングルクォートを付与する。"""
        result = serialize_csv(["入力値"], [{"入力値": input_value}], bom=False)
        rows = list(csv.reader(io.StringIO(result)))

        assert rows == [["入力値"], [expected]]

    @pytest.mark.parametrize(
        "input_value",
        ["normal text", "user@example.com", "0001", "ユーザー名", ""],
    )
    def test_leaves_safe_values_unchanged(self, input_value: str) -> None:
        """安全な値はそのまま返す。"""
        result = serialize_csv(["入力値"], [{"入力値": input_value}], bom=False)
        rows = list(csv.reader(io.StringIO(result)))

        assert rows == [["入力値"], [input_value]]
