# Sync-AD2-NAS.ps1 (formerly Sync-FromNAS.ps1)
# Bidirectional sync between AD2 and NAS (D2TESTNAS)
#
# PULL (NAS â†’ AD2): Test results (LOGS/*.DAT, Reports/*.TXT) â†’ Database import
# PUSH (AD2 â†’ NAS): Software updates (ProdSW/*, TODO.BAT) â†’ DOS machines
#
# Run: powershell -ExecutionPolicy Bypass -File C:\Shares\test\scripts\Sync-FromNAS.ps1
# Scheduled: Every 15 minutes via Windows Task Scheduler

param(
    [switch]$DryRun,        # Show what would be done without doing it
    [switch]$Verbose,       # Extra output
    [int]$MaxAgeMinutes = 1440  # Default: files from last 24 hours (was 60 min, too aggressive)
)

# ============================================================================
# Configuration
# ============================================================================
$NAS_IP = "192.168.0.9"
$NAS_USER = "root"
$NAS_PASSWORD = "Paper123!@#-nas"
$NAS_HOSTKEY = "SHA256:5CVIPlqjLPxO8n48PKLAP99nE6XkEBAjTkaYmJAeOdA"
$NAS_DATA_PATH = "/data/test"

$AD2_TEST_PATH = "C:\Shares\test"
$AD2_HISTLOGS_PATH = "C:\Shares\test\Ate\HISTLOGS"

$SSH = "C:\Program Files\OpenSSH\ssh.exe"  # Changed from PLINK to OpenSSH
$SCP = "C:\Program Files\OpenSSH\scp.exe"  # Changed from PSCP to OpenSSH

$LOG_FILE = "C:\Shares\test\scripts\sync-from-nas.log"
$STATUS_FILE = "C:\Shares\test\_SYNC_STATUS.txt"

$LOG_TYPES = @("5BLOG", "7BLOG", "8BLOG", "DSCLOG", "SCTLOG", "VASLOG", "PWRLOG", "HVLOG")

# Database import configuration
$IMPORT_SCRIPT = "C:\Shares\testdatadb\database\import.js"
$NODE_PATH = "node"

# ============================================================================
# Functions
# ============================================================================

function Write-Log {
    param([string]$Message)
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $logLine = "$timestamp : $Message"
    Add-Content -Path $LOG_FILE -Value $logLine
    if ($Verbose) { Write-Host $logLine }
}

function Invoke-NASCommand {
    param([string]$Command)
    $result = & $SSH -i "C:\Users\sysadmin\.ssh\id_ed25519" -o BatchMode=yes -o ConnectTimeout=10 -o StrictHostKeyChecking=accept-new $Command 2>&1
    return $result
}

function Copy-FromNAS {
    param(
        [string]$RemotePath,
        [string]$LocalPath
    )

    # Ensure local directory exists
    $localDir = Split-Path -Parent $LocalPath
    if (-not (Test-Path $localDir)) {
        New-Item -ItemType Directory -Path $localDir -Force | Out-Null
    }

    $result = & $SCP -O -o StrictHostKeyChecking=accept-new -o UserKnownHostsFile="C:\Shares\test\scripts\.ssh\known_hosts"  "${NAS_USER}@${NAS_IP}:$RemotePath" $LocalPath 2>&1    if ($LASTEXITCODE -ne 0) {
        $errorMsg = $result | Out-String
        Write-Log "  SCP PUSH ERROR (exit $LASTEXITCODE): $errorMsg"
    }
    return $LASTEXITCODE -eq 0
}

function Remove-FromNAS {
    param([string]$RemotePath)
    Invoke-NASCommand "rm -f '$RemotePath'" | Out-Null
}

function Copy-ToNAS {
    param(
        [string]$LocalPath,
        [string]$RemotePath
    )

    # Ensure remote directory exists
    $remoteDir = Split-Path -Parent $RemotePath
    Invoke-NASCommand "mkdir -p '$remoteDir'" | Out-Null

    $result = & $SCP -O -o StrictHostKeyChecking=accept-new -o UserKnownHostsFile="C:\Shares\test\scripts\.ssh\known_hosts"  $LocalPath "${NAS_USER}@${NAS_IP}:$RemotePath" 2>&1
    if ($LASTEXITCODE -ne 0) {
        $errorMsg = $result | Out-String
        Write-Log "  SCP PUSH ERROR (exit $LASTEXITCODE): $errorMsg"
    }
    return $LASTEXITCODE -eq 0
}

function Get-FileHash256 {
    param([string]$FilePath)
    if (Test-Path $FilePath) {
        return (Get-FileHash -Path $FilePath -Algorithm SHA256).Hash
    }
    return $null
}

function Import-ToDatabase {
    param([string[]]$FilePaths)

    if ($FilePaths.Count -eq 0) { return }

    Write-Log "Importing $($FilePaths.Count) file(s) to database..."

    # Build argument list
    $args = @("$IMPORT_SCRIPT", "--file") + $FilePaths

    try {
        $output = & $NODE_PATH $args 2>&1
        foreach ($line in $output) {
            Write-Log "  [DB] $line"
        }
        Write-Log "Database import complete"
    } catch {
        Write-Log "ERROR: Database import failed: $_"
    }
}

# ============================================================================
# Main Script
# ============================================================================

Write-Log "=========================================="
Write-Log "Starting sync from NAS"
Write-Log "Max age: $MaxAgeMinutes minutes"
if ($DryRun) { Write-Log "DRY RUN - no changes will be made" }

$errorCount = 0
$syncedFiles = 0
$skippedFiles = 0
$syncedDatFiles = @()  # Track DAT files for database import

# Find all DAT files on NAS modified within the time window
Write-Log "Finding DAT files on NAS..."
$findCommand = "find $NAS_DATA_PATH/TS-*/LOGS -name '*.DAT' -type f -mmin -$MaxAgeMinutes 2>/dev/null"
$datFiles = Invoke-NASCommand $findCommand

if (-not $datFiles -or $datFiles.Count -eq 0) {
    Write-Log "No new DAT files found on NAS"
} else {
    Write-Log "Found $($datFiles.Count) DAT file(s) to process"

    foreach ($remoteFile in $datFiles) {
        $remoteFile = $remoteFile.Trim()
        if ([string]::IsNullOrWhiteSpace($remoteFile)) { continue }

        # Parse the path: /data/test/TS-XX/LOGS/7BLOG/file.DAT
        if ($remoteFile -match "/data/test/(TS-[^/]+)/LOGS/([^/]+)/(.+\.DAT)$") {
            $station = $Matches[1]
            $logType = $Matches[2]
            $fileName = $Matches[3]

            Write-Log "Processing: $station/$logType/$fileName"

            # Destination 1: Per-station folder (preserves structure)
            $stationDest = Join-Path $AD2_TEST_PATH "$station\LOGS\$logType\$fileName"

            # Destination 2: Aggregated HISTLOGS folder
            $histlogsDest = Join-Path $AD2_HISTLOGS_PATH "$logType\$fileName"

            if ($DryRun) {
                Write-Log "  [DRY RUN] Would copy to: $stationDest"
                $syncedFiles++
            } else {
                # Copy to station folder only (skip HISTLOGS to avoid duplicates)
                $success1 = Copy-FromNAS -RemotePath $remoteFile -LocalPath $stationDest

                if ($success1) {
                    Write-Log "  Copied to station folder"

                    # Remove from NAS after successful sync
                    Remove-FromNAS -RemotePath $remoteFile
                    Write-Log "  Removed from NAS"

                    # Track for database import
                    $syncedDatFiles += $stationDest

                    $syncedFiles++
                } else {
                    Write-Log "  ERROR: Failed to copy from NAS"
                    $errorCount++
                }
            }
        } else {
            Write-Log "  Skipping (unexpected path format): $remoteFile"
            $skippedFiles++
        }
    }
}

# Find and sync TXT report files
Write-Log "Finding TXT reports on NAS..."
$findReportsCommand = "find $NAS_DATA_PATH/TS-*/Reports -name '*.TXT' -type f -mmin -$MaxAgeMinutes 2>/dev/null"
$txtFiles = Invoke-NASCommand $findReportsCommand

if ($txtFiles -and $txtFiles.Count -gt 0) {
    Write-Log "Found $($txtFiles.Count) TXT report(s) to process"

    foreach ($remoteFile in $txtFiles) {
        $remoteFile = $remoteFile.Trim()
        if ([string]::IsNullOrWhiteSpace($remoteFile)) { continue }

        if ($remoteFile -match "/data/test/(TS-[^/]+)/Reports/(.+\.TXT)$") {
            $station = $Matches[1]
            $fileName = $Matches[2]

            Write-Log "Processing report: $station/$fileName"

            # Destination: Per-station Reports folder
            $reportDest = Join-Path $AD2_TEST_PATH "$station\Reports\$fileName"

            if ($DryRun) {
                Write-Log "  [DRY RUN] Would copy to: $reportDest"
                $syncedFiles++
            } else {
                $success = Copy-FromNAS -RemotePath $remoteFile -LocalPath $reportDest

                if ($success) {
                    Write-Log "  Copied report"
                    Remove-FromNAS -RemotePath $remoteFile
                    Write-Log "  Removed from NAS"
                    $syncedFiles++
                } else {
                    Write-Log "  ERROR: Failed to copy report"
                    $errorCount++
                }
            }
        }
    }
}

# ============================================================================
# Import synced DAT files to database
# ============================================================================
if (-not $DryRun -and $syncedDatFiles.Count -gt 0) {
    Import-ToDatabase -FilePaths $syncedDatFiles
}

# ============================================================================
# PUSH: AD2 â†’ NAS (Software Updates for DOS Machines)
# ============================================================================
Write-Log "--- AD2 to NAS Sync (Software Updates) ---"

$pushedFiles = 0

# Sync COMMON/ProdSW (batch files for all stations)
# AD2 uses _COMMON, NAS uses COMMON - handle both
$commonSources = @(
    @{ Local = "$AD2_TEST_PATH\_COMMON\ProdSW"; Remote = "$NAS_DATA_PATH/COMMON/ProdSW" },
    @{ Local = "$AD2_TEST_PATH\COMMON\ProdSW"; Remote = "$NAS_DATA_PATH/COMMON/ProdSW" }
)

foreach ($source in $commonSources) {
    if (Test-Path $source.Local) {
        Write-Log "Syncing COMMON ProdSW from: $($source.Local)"
        $commonFiles = Get-ChildItem -Path $source.Local -File -ErrorAction SilentlyContinue
        foreach ($file in $commonFiles) {
            $remotePath = "$($source.Remote)/$($file.Name)"

            if ($DryRun) {
                Write-Log "  [DRY RUN] Would push: $($file.Name) -> $remotePath"
                $pushedFiles++
            } else {
                $success = Copy-ToNAS -LocalPath $file.FullName -RemotePath $remotePath
                if ($success) {
                    Write-Log "  Pushed: $($file.Name)"
                    $pushedFiles++
                } else {
                    Write-Log "  ERROR: Failed to push $($file.Name)"
                    $errorCount++
                }
            }
        }
    }
}


# Sync UPDATE.BAT (root level utility)
Write-Log "Syncing UPDATE.BAT..."
$updateBatLocal = "$AD2_TEST_PATH\UPDATE.BAT"
if (Test-Path $updateBatLocal) {
    $updateBatRemote = "$NAS_DATA_PATH/UPDATE.BAT"

    if ($DryRun) {
        Write-Log "  [DRY RUN] Would push: UPDATE.BAT -> $updateBatRemote"
        $pushedFiles++
    } else {
        $success = Copy-ToNAS -LocalPath $updateBatLocal -RemotePath $updateBatRemote
        if ($success) {
            Write-Log "  Pushed: UPDATE.BAT"
            $pushedFiles++
        } else {
            Write-Log "  ERROR: Failed to push UPDATE.BAT"
            $errorCount++
        }
    }
} else {
    Write-Log "  WARNING: UPDATE.BAT not found at $updateBatLocal"
}

# Sync DEPLOY.BAT (root level utility)
Write-Log "Syncing DEPLOY.BAT..."
$deployBatLocal = "$AD2_TEST_PATH\DEPLOY.BAT"
if (Test-Path $deployBatLocal) {
    $deployBatRemote = "$NAS_DATA_PATH/DEPLOY.BAT"

    if ($DryRun) {
        Write-Log "  [DRY RUN] Would push: DEPLOY.BAT -> $deployBatRemote"
        $pushedFiles++
    } else {
        $success = Copy-ToNAS -LocalPath $deployBatLocal -RemotePath $deployBatRemote
        if ($success) {
            Write-Log "  Pushed: DEPLOY.BAT"
            $pushedFiles++
        } else {
            Write-Log "  ERROR: Failed to push DEPLOY.BAT"
            $errorCount++
        }
    }
} else {
    Write-Log "  WARNING: DEPLOY.BAT not found at $deployBatLocal"
}

# Sync per-station ProdSW folders
Write-Log "Syncing station-specific ProdSW folders..."
$stationFolders = Get-ChildItem -Path $AD2_TEST_PATH -Directory -Filter "TS-*" -ErrorAction SilentlyContinue

foreach ($station in $stationFolders) {
    $prodSwPath = Join-Path $station.FullName "ProdSW"

    if (Test-Path $prodSwPath) {
        # Get all files in ProdSW (including subdirectories)
        $prodSwFiles = Get-ChildItem -Path $prodSwPath -File -Recurse -ErrorAction SilentlyContinue

        foreach ($file in $prodSwFiles) {
            # Calculate relative path from ProdSW folder
            $relativePath = $file.FullName.Substring($prodSwPath.Length + 1).Replace('\', '/')
            $remotePath = "$NAS_DATA_PATH/$($station.Name)/ProdSW/$relativePath"

            if ($DryRun) {
                Write-Log "  [DRY RUN] Would push: $($station.Name)/ProdSW/$relativePath"
                $pushedFiles++
            } else {
                $success = Copy-ToNAS -LocalPath $file.FullName -RemotePath $remotePath
                if ($success) {
                    Write-Log "  Pushed: $($station.Name)/ProdSW/$relativePath"
                    $pushedFiles++
                } else {
                    Write-Log "  ERROR: Failed to push $($station.Name)/ProdSW/$relativePath"
                    $errorCount++
                }
            }
        }
    }

    # Check for TODO.BAT (one-time task file)
    $todoBatPath = Join-Path $station.FullName "TODO.BAT"
    if (Test-Path $todoBatPath) {
        $remoteTodoPath = "$NAS_DATA_PATH/$($station.Name)/TODO.BAT"

        Write-Log "Found TODO.BAT for $($station.Name)"

        if ($DryRun) {
            Write-Log "  [DRY RUN] Would push TODO.BAT -> $remoteTodoPath"
            $pushedFiles++
        } else {
            $success = Copy-ToNAS -LocalPath $todoBatPath -RemotePath $remoteTodoPath
            if ($success) {
                Write-Log "  Pushed TODO.BAT to NAS"
                # Remove from AD2 after successful push (one-shot mechanism)
                Remove-Item -Path $todoBatPath -Force
                Write-Log "  Removed TODO.BAT from AD2 (pushed to NAS)"
                $pushedFiles++
            } else {
                Write-Log "  ERROR: Failed to push TODO.BAT"
                $errorCount++
            }
        }
    }
}

Write-Log "AD2 to NAS sync: $pushedFiles file(s) pushed"

# ============================================================================
# Update Status File
# ============================================================================
$status = if ($errorCount -eq 0) { "OK" } else { "ERRORS" }
$statusContent = @"
AD2 <-> NAS Bidirectional Sync Status
======================================
Timestamp: $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")
Status: $status

PULL (NAS -> AD2 - Test Results):
  Files Pulled: $syncedFiles
  Files Skipped: $skippedFiles
  DAT Files Imported to DB: $($syncedDatFiles.Count)

PUSH (AD2 -> NAS - Software Updates):
  Files Pushed: $pushedFiles

Errors: $errorCount
"@

Set-Content -Path $STATUS_FILE -Value $statusContent

Write-Log "=========================================="
Write-Log "Sync complete: PULL=$syncedFiles, PUSH=$pushedFiles, Errors=$errorCount"
Write-Log "=========================================="

# Exit with error code if there were failures
if ($errorCount -gt 0) {
    exit 1
} else {
    exit 0
}





