using System.Collections.Generic;
using System.IO;
using System.Text;
using NUnit.Framework;

namespace TIASshot.Tests {
    /// <summary>
    /// IoUtil.WriteInfo（撮影情報 Info.csv の書き出し）のテスト．
    /// 値にカンマ・ダブルクォート・改行が含まれても 1 項目が 1 行（キー,値 の 2 列）に保たれ，
    /// RFC 4180 に従ってクォートされることを検証する．それ以外の値は従来どおりそのまま出力する．
    /// </summary>
    [TestFixture]
    public class IoUtilWriteInfoTests {

        private string _csvPath;

        [SetUp]
        public void SetUp() {
            _csvPath = Path.GetTempFileName();
        }

        [TearDown]
        public void TearDown() {
            if (File.Exists(_csvPath)) File.Delete(_csvPath);
        }

        /// <summary>
        /// 本番（RunShotLoop）と同じく new StreamWriter(path) で WriteInfo を呼び，
        /// 先頭の撮影日時行を除いた本文を返す
        /// </summary>
        private string WriteAndReadBody(Dictionary<string, string> info) {
            using (var sw = new StreamWriter(_csvPath)) {
                IoUtil.WriteInfo(sw, info);
            }
            var text = File.ReadAllText(_csvPath, Encoding.UTF8);
            var firstNewLine = text.IndexOf("\r\n");
            return text.Substring(firstNewLine + 2);
        }

        [Test]
        public void WriteInfo_特殊文字を含まない値_従来どおりそのまま出力する() {
            var info = new Dictionary<string, string> {
                { "データ名", "subject01" },
                { "Exposure(ms)", "12.5" },
                { "校正データ", @"C:\Data\2026-10-06\10_00_00-校正" },
            };

            var body = WriteAndReadBody(info);

            Assert.That(body, Is.EqualTo(
                "データ名,subject01\r\n" +
                "Exposure(ms),12.5\r\n" +
                "校正データ,C:\\Data\\2026-10-06\\10_00_00-校正\r\n"));
        }

        [Test]
        public void WriteInfo_値にカンマを含む_ダブルクォートで囲む() {
            var info = new Dictionary<string, string> { { "データ名", "山田,太郎" } };

            var body = WriteAndReadBody(info);

            Assert.That(body, Is.EqualTo("データ名,\"山田,太郎\"\r\n"));
        }

        [Test]
        public void WriteInfo_値にダブルクォートを含む_二重化してダブルクォートで囲む() {
            var info = new Dictionary<string, string> { { "データ名", "a\"b" } };

            var body = WriteAndReadBody(info);

            Assert.That(body, Is.EqualTo("データ名,\"a\"\"b\"\r\n"));
        }

        [Test]
        public void WriteInfo_値に改行を含む_ダブルクォートで囲み1レコードに保つ() {
            var info = new Dictionary<string, string> { { "データ名", "a\r\nb" } };

            var body = WriteAndReadBody(info);

            Assert.That(body, Is.EqualTo("データ名,\"a\r\nb\"\r\n"));
        }

        [Test]
        public void WriteInfo_値がnull_空欄として出力する() {
            var info = new Dictionary<string, string> { { "データ名", null } };

            var body = WriteAndReadBody(info);

            Assert.That(body, Is.EqualTo("データ名,\r\n"));
        }
    }
}
