#!/usr/bin/env perl

# Copyright (c) 2025, R. W. Rodolico
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
#    list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
#    this list of conditions and the following disclaimer in the documentation
#    and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Revision History:
# 2026-10-11 Copilot v1.0.0 r? initial transport success-path tests
# 2026-10-12 Copilot v1.1.0 r? same-script reload, die-fallback, and STDOUT fallback tests

use strict;
use warnings;
use Test::More;
use lib './unix';
use File::Temp qw(tempdir);
use File::Path qw(make_path);

require './unix/sysinfo_client';

my $tempDir = tempdir(CLEANUP => 1);
my $transportDir = "$tempDir/transports";
my $outputDir = "$tempDir/output";
make_path($transportDir, $outputDir);

my $failScript = "$transportDir/fail_transport";
open my $fhFail, '>', $failScript or die $!;
print {$fhFail} "#!/usr/bin/env perl\nsub doit { return 0; }\n1;\n";
close($fhFail);
chmod 0700, $failScript;

my $dieScript = "$transportDir/die_transport";
open my $fhDie, '>', $dieScript or die $!;
print {$fhDie} "#!/usr/bin/env perl\nsub doit { die qq(die in transport\\n); }\n1;\n";
close($fhDie);
chmod 0700, $dieScript;

my $sharedScript = "$transportDir/shared_transport";
open my $fhShared, '>', $sharedScript or die $!;
print {$fhShared} "#!/usr/bin/env perl\n";
print {$fhShared} "sub doit { my (\$p, \$m) = \@_; return \$p->{'returnCode'}; }\n";
print {$fhShared} "1;\n";
close($fhShared);
chmod 0700, $sharedScript;

my $successScript = "$transportDir/success_transport";
open my $fhSuccess, '>', $successScript or die $!;
print {$fhSuccess} '#!/usr/bin/env perl' . "\n";
print {$fhSuccess} 'sub doit {' . "\n";
print {$fhSuccess} '   my ($p, $m) = @_;' . "\n";
print {$fhSuccess} '   open my $f, ">", "' . $outputDir . '/result.txt" or die $!;' . "\n";
print {$fhSuccess} '   print {$f} $p->{"host name"} . "|" . $m;' . "\n";
print {$fhSuccess} '   close $f;' . "\n";
print {$fhSuccess} '   return 1;' . "\n";
print {$fhSuccess} '}' . "\n";
print {$fhSuccess} '1;' . "\n";
close($fhSuccess);
chmod 0700, $successScript;

my $globals = {
   'upload_type' => 'sysinfo',
   'data version' => 'v3.8.0',
   'report date' => '2026-10-11 01:02:03',
   'client name' => 'Client X',
   'host name' => 'host.example',
   'serial number' => 'SER-1',
   'UUID' => 'uuid-1',
   'fileType' => 'yaml',
};

my $transports = {
   '10' => {
      'sendScript' => 'fail_transport',
      'name' => 'Fail',
   },
   '20' => {
      'sendScript' => 'success_transport',
      'name' => 'Success',
      'note' => "host=\$hostname",
   },
};

my $config = {
   'hostname' => 'host.example',
   'clientName' => 'Client X',
   'serialNumber' => 'SER-1',
   'logging' => {
      'log type' => 'cache',
      'log level' => 0,
   },
};

my $ret = sendResults($globals, $transports, "payload", [$transportDir], $config);
is($ret, 1, 'sendResults stops at first success');

open my $in, '<', "$outputDir/result.txt" or die $!;
my $content = do { local $/; <$in> };
close($in);
is($content, 'host.example|payload', 'successful transport received globals and report');

my $sameScriptTransports = {
   '1' => {
      'sendScript' => 'shared_transport',
      'name' => 'Shared First',
      'returnCode' => 0,
   },
   '2' => {
      'sendScript' => 'shared_transport',
      'name' => 'Shared Second',
      'returnCode' => 1,
   },
};
my $sameScriptResult = sendResults($globals, $sameScriptTransports, "payload", [$transportDir], $config);
is($sameScriptResult, 1, 'same transport script at two priorities reloads and succeeds on second priority');

my $dieThenSuccess = {
   '1' => {
      'sendScript' => 'die_transport',
      'name' => 'Die First',
   },
   '2' => {
      'sendScript' => 'success_transport',
      'name' => 'Success Second',
   },
};
my $dieThenSuccessResult = sendResults($globals, $dieThenSuccess, "payload", [$transportDir], $config);
is($dieThenSuccessResult, 1, 'die in first transport does not abort run and next transport is tried');

my $allFail = {
   '1' => {
      'sendScript' => 'fail_transport',
      'name' => 'Fail One',
   },
   '2' => {
      'sendScript' => 'fail_transport',
      'name' => 'Fail Two',
   },
};

my $stdoutCapture = '';
{
   open my $stdoutMem, '>', \$stdoutCapture or die $!;
   local *STDOUT = $stdoutMem;
   my $allFailResult = sendResults($globals, $allFail, "payload-fallback", [$transportDir], $config);
   is($allFailResult, 0, 'all failed transports return 0 after STDOUT fallback');
}
is($stdoutCapture, 'payload-fallback', 'all failed transports print report payload to STDOUT');

done_testing();
