#!/usr/bin/env perl

# Advanced test script to identify potential runtime issues in sneakernet target mode
#
# This script identifies places where uninitialized variables COULD cause issues
# even if they don't generate warnings (due to //= defaults), by checking what
# happens if the defaults weren't there.

use strict;
use warnings;
use Data::Dumper;
use FindBin;
use lib "$FindBin::Bin/..";

print "=" x 70 . "\n";
print "Advanced Analysis: sneakernet target mode variable initialization\n";
print "=" x 70 . "\n\n";

my @issues;

# Test scenarios that could fail if defaults weren't in place
print "Analyzing target mode code paths...\n\n";

# Issue 1: Line 1121 - accessing geli->secureKey->label when geli is defined but secureKey isn't
print "1. Checking geli->secureKey->label access pattern (line 1121)\n";
my $config1 = {
   target => {
      geli => {
         poolname => 'backup',
         localKey => 'abc123'
         # secureKey not defined
      }
   },
   transport => {
      label => 'sneakernet'
   }
};

if (defined $config1->{target}->{geli}) {
   # Without the //= '', this would create autovivification
   eval {
      no warnings 'uninitialized';
      my $label = $config1->{target}->{geli}->{secureKey}->{label};
      if (!defined $label) {
         push @issues, "  ⚠ Line 1121: geli->secureKey->label is undefined when geli exists but secureKey doesn't";
      }
   };
}

# Issue 2: Line 1122 - unmountDriveByLabel with undefined secureKey hash
print "2. Checking unmountDriveByLabel call with undefined secureKey (line 1122)\n";
my $config2 = {
   target => {
      geli => {
         poolname => 'backup'
         # No secureKey at all
      }
   }
};

if (defined $config2->{target}->{geli}) {
   eval {
      no warnings 'uninitialized';
      # This would pass an undefined hash to unmountDriveByLabel
      my $secureKey = $config2->{target}->{geli}->{secureKey};
      if (!defined $secureKey) {
         push @issues, "  ⚠ Line 1122: Passing undefined secureKey hash to unmountDriveByLabel";
      }
   };
}

# Issue 3: Line 1125 - stateFile could be undefined
print "3. Checking stateFile access (line 1125)\n";
my $config3 = {
   target => {
      poolname => 'backup'
      # stateFile not defined
   }
};

eval {
   no warnings 'uninitialized';
   my $stateFile = $config3->{target}->{stateFile};
   if (!defined $stateFile) {
      push @issues, "  ⚠ Line 1125: stateFile is undefined - createStateFile will receive undef";
   }
};

# Issue 4: Line 1126 - report->targetDrive->label multiple levels undefined
print "4. Checking report->targetDrive->label deep access (line 1126)\n";
my $config4 = {
   target => {
      # No report defined
   }
};

eval {
   no warnings 'uninitialized';
   my $label = $config4->{target}->{report}->{targetDrive}->{label};
   if (!defined $config4->{target}->{report}) {
      push @issues, "  ⚠ Line 1126: report hash doesn't exist, accessing targetDrive creates autovivification";
   }
};

# Issue 5: Check what happens if geli->secureKey exists but is empty hash
print "5. Checking empty secureKey hash behavior (line 1121-1123)\n";
my $config5 = {
   target => {
      geli => {
         secureKey => {}  # Empty hash
      }
   },
   transport => {
      label => 'sneakernet'
   }
};

if (defined $config5->{target}->{geli}) {
   eval {
      no warnings 'uninitialized';
      $config5->{target}->{geli}->{secureKey}->{label} //= '';
      my $geli_label = $config5->{target}->{geli}->{secureKey}->{label};
      my $transport_label = $config5->{transport}->{label};
      
      # This comparison will work but geli_label is empty string
      unless ($geli_label eq $transport_label) {
         # unmountDriveByLabel would be called with mostly empty secureKey hash
         if (keys %{$config5->{target}->{geli}->{secureKey}} <= 1) {
            push @issues, "  ⚠ Line 1122: unmountDriveByLabel called with nearly empty secureKey hash";
         }
      }
   };
}

# Issue 6: Check transport->mount_point access
print "6. Checking transport->mount_point access (line 1110)\n";
my $config6 = {
   transport => {
      label => 'sneakernet'
      # No mount_point defined
   }
};

eval {
   no warnings 'uninitialized';
   my $mount_point = $config6->{transport}->{mount_point};
   if (!defined $mount_point) {
      push @issues, "  ⚠ Line 1110: transport->mount_point is undefined (should be set by mountDriveByLabel)";
   }
};

# Issue 7: Check datasets access in updateTarget
print "7. Checking datasets hash access in updateTarget (line 1129)\n";
my $config7 = {
   # No datasets defined
   transport => {
      mount_point => '/tmp/test'
   }
};

eval {
   no warnings 'uninitialized';
   my $datasets = $config7->{datasets};
   if (!defined $datasets) {
      push @issues, "  ⚠ updateTarget: datasets hash is undefined - foreach will fail";
   }
};

# Issue 8: Check cleanUpScriptsDir value
print "8. Checking cleanUpScriptsDir string/path handling (line 1142)\n";
my $config8 = {
   target => {
      cleanUpScriptsDir => ''  # Empty string (falsy)
   }
};

eval {
   # Empty string is falsy, so condition will skip cleanup scripts
   # But is this intended? Should it check defined instead?
   if ($config8->{target}->{cleanUpScriptsDir}) {
      # Won't execute
   } else {
      # This might be wrong if cleanUpScriptsDir: '' was set intentionally
      if (exists $config8->{target}->{cleanUpScriptsDir} && 
          !$config8->{target}->{cleanUpScriptsDir}) {
         push @issues, "  ℹ Line 1142: cleanUpScriptsDir is empty string - scripts will be skipped";
      }
   }
};

# Print results
print "\n" . "=" x 70 . "\n";
print "Analysis Results\n";
print "=" x 70 . "\n\n";

if (@issues) {
   print "Found " . scalar(@issues) . " potential issue(s):\n\n";
   foreach my $issue (@issues) {
      print "$issue\n";
   }
   print "\n";
   
   print "Recommendations:\n";
   print "1. Add validation in target mode startup to check required fields\n";
   print "2. Consider using 'defined' checks instead of truthiness for optional paths\n";
   print "3. Add defensive checks before passing hashes to functions\n";
   print "4. Document which target.* fields are truly required vs optional\n";
   
} else {
   print "✓ No obvious initialization issues detected\n";
   print "  (The code uses //= defaults effectively to prevent warnings)\n";
}

print "\n" . "=" x 70 . "\n";
print "Code Safety Analysis\n";
print "=" x 70 . "\n\n";

print "Current safety mechanisms in target mode:\n";
print "  ✓ Line 1118: 'defined' check before accessing geli hash\n";
print "  ✓ Line 1121: //= default for geli->secureKey->label\n";
print "  ✓ Line 1126: //= default for report->targetDrive->label\n";
print "  ✓ Line 1127: if condition checks label before using it\n";
print "  ✓ Line 1142: if condition checks cleanUpScriptsDir before using it\n";
print "\n";

print "Potential improvements:\n";
print "  • Add explicit validation that datasets hash exists and is not empty\n";
print "  • Validate transport->mount_point was set by mountDriveByLabel\n";
print "  • Check that required target fields (poolname, stateFile) are defined\n";
print "  • Consider defensive checks in unmountDriveByLabel for incomplete hashes\n";
print "\n";

1;
