#if SELFTEST
using NUnit.Framework;

namespace TIASshot.Tests {
    /// <summary>
    /// SelfTestRunner のうちテストプロジェクトから参照できる純粋ロジック（引数判定・終了コードの規約）のテスト．
    ///
    /// 仕様: ENV_04「セルフテスト」・ENV_06「SELFTEST」・.claude/verify-profile.md
    ///   - `TIASshot.exe --selftest` でセルフテストを実行する（それ以外は通常起動）
    ///   - 終了コード 0=全項目合格，1=不合格あり，2=セルフテスト自体の異常，3=タイムアウト
    ///
    /// 対象外: Run 本体（ヘッドレス Form1・偽カメラ・メッセージポンプ・Environment.Exit を伴う）と，
    /// private の引数値取得（--selftest-out）・結果集約・リダイレクト突き合わせはハードウェア結合層の一部として
    /// ランナー（scripts/verify/run_selftest.py）による実行で担保する．
    /// 本クラスは SELFTEST 構成（Debug|x64）でのみコンパイルされる．
    /// </summary>
    [TestFixture]
    public class SelfTestRunnerTests {

        [Test]
        public void IsRequested_selftestフラグあり_真() {
            Assert.That(SelfTestRunner.IsRequested(new[] { @"C:\app\TIASshot.exe", "--selftest" }), Is.True);
        }

        [Test]
        public void IsRequested_selftestフラグが出力先指定と併用_真() {
            var args = new[] { "TIASshot.exe", "--selftest", "--selftest-out", @"C:\tmp\r.txt" };
            Assert.That(SelfTestRunner.IsRequested(args), Is.True);
        }

        [Test]
        public void IsRequested_大文字小文字違い_真() {
            Assert.That(SelfTestRunner.IsRequested(new[] { "TIASshot.exe", "--SelfTest" }), Is.True);
        }

        [Test]
        public void IsRequested_引数なし_偽で通常起動() {
            Assert.That(SelfTestRunner.IsRequested(new[] { "TIASshot.exe" }), Is.False);
        }

        [Test]
        public void IsRequested_空配列_偽() {
            Assert.That(SelfTestRunner.IsRequested(new string[0]), Is.False);
        }

        [Test]
        public void IsRequested_出力先指定のみでselftestなし_偽() {
            // --selftest-out は --selftest の前方一致だが，それ単独ではセルフテストを起動しない
            var args = new[] { "TIASshot.exe", "--selftest-out", @"C:\tmp\r.txt" };
            Assert.That(SelfTestRunner.IsRequested(args), Is.False);
        }

        [Test]
        public void IsRequested_keepのみ_偽() {
            Assert.That(SelfTestRunner.IsRequested(new[] { "TIASshot.exe", "--selftest-keep" }), Is.False);
        }

        [Test]
        public void IsRequested_前後に文字が付いた値_偽() {
            Assert.That(SelfTestRunner.IsRequested(new[] { "TIASshot.exe", "-selftest", "selftest", "--selftestx" }), Is.False);
        }

        [Test]
        public void IsRequested_出力先パスの値がselftestという文字列_真() {
            // 出力先の値として "--selftest" が来た場合も含め，フラグの存在で判定する（誤起動にはならない方向の確認）
            Assert.That(SelfTestRunner.IsRequested(new[] { "TIASshot.exe", "--selftest-out", "--selftest" }), Is.True);
        }

        [Test]
        public void 終了コード_合格は0() {
            Assert.That(SelfTestRunner.ExitPass, Is.EqualTo(0));
        }

        [Test]
        public void 終了コード_不合格ありは1() {
            Assert.That(SelfTestRunner.ExitFail, Is.EqualTo(1));
        }

        [Test]
        public void 終了コード_セルフテスト自体の異常は2() {
            Assert.That(SelfTestRunner.ExitError, Is.EqualTo(2));
        }

        [Test]
        public void 終了コード_タイムアウトは3() {
            Assert.That(SelfTestRunner.ExitTimeout, Is.EqualTo(3));
        }

        [TestCase("", TestName = "Run_出力先が空文字_例外を投げず終了コード2")]
        [TestCase("a\0b.txt", TestName = "Run_出力先にNUL文字_例外を投げず終了コード2")]
        [TestCase(@"C:\tmp\a:b.txt", TestName = "Run_出力先にドライブ以外のコロン_例外を投げず終了コード2")]
        public void Run_不正な出力先_セルフテスト自体の異常として2を返す(string outValue) {
            // 不正な --selftest-out は結果ファイルを作成できない場合と同じく「セルフテスト自体の異常」（2）．
            // 結果ファイルの準備段階で返るため，フォーム・偽カメラ・ウォッチドッグは起動しない
            var args = new[] { "TIASshot.exe", "--selftest", "--selftest-out", outValue };
            var exitCode = -1;
            Assert.DoesNotThrow((System.Action)(() => exitCode = SelfTestRunner.Run(args)));
            Assert.That(exitCode, Is.EqualTo(SelfTestRunner.ExitError));
        }

        [Test]
        public void フラグ名_仕様どおりselftest() {
            Assert.That(SelfTestRunner.FlagSelfTest, Is.EqualTo("--selftest"));
        }
    }
}
#endif
