"""Patch run-pipeline.ps1 to use full node.exe path and retry."""
import base64, paramiko, subprocess, time, yaml

ad2_pwd = yaml.safe_load(subprocess.run(['sops','-d','D:/vault/clients/dataforth/ad2.sops.yaml'],
    capture_output=True, text=True, timeout=30, check=True).stdout)['credentials']['password'].replace('\\','')

PROD_DIR = r'C:\ProgramData\dataforth-uploader'

RUN_PS1 = r'''# Dataforth Test Datasheet Uploader (hourly)
$ErrorActionPreference = 'Stop'
$prod = 'C:\ProgramData\dataforth-uploader'
$logDir = Join-Path $prod 'logs'
$nodeExe = 'C:\Program Files\nodejs\node.exe'
New-Item -ItemType Directory -Force -Path $logDir | Out-Null
$stamp = Get-Date -Format 'yyyy-MM-dd_HH-mm-ss'
$log = Join-Path $logDir "pipeline-$stamp.log"

function Log([string]$m) {
    $line = "[$(Get-Date -Format o)] $m"
    Write-Host $line
    Add-Content -Path $log -Value $line -Encoding utf8
}

try {
    Log "=== pipeline start (pid=$PID) ==="

    # Load credentials
    $creds = Get-Content (Join-Path $prod 'credentials.json') -Raw | ConvertFrom-Json
    $env:CF_TOKEN_URL     = $creds.CF_TOKEN_URL
    $env:CF_API_BASE      = $creds.CF_API_BASE
    $env:CF_CLIENT_ID     = $creds.CF_CLIENT_ID
    $env:CF_CLIENT_SECRET = $creds.CF_CLIENT_SECRET
    $env:CF_SCOPE         = $creds.CF_SCOPE

    # [1] DFWDS process
    Log '[1] dfwds-process.js'
    $dfwdsJs = Join-Path $prod 'dfwds-process.js'
    $out = & $nodeExe $dfwdsJs 2>&1
    $out | ForEach-Object { Log $_ }

    # [2] Enumerate For_Web
    Log '[2] enumerate For_Web'
    $delta = Join-Path $prod 'delta_for_web_all.txt'
    Get-ChildItem 'C:\Shares\webshare\For_Web' -File -Filter *.TXT |
        ForEach-Object {
            $sn = [System.IO.Path]::GetFileNameWithoutExtension($_.Name)
            "$sn|$($_.FullName)|$($_.Length)|$($_.LastWriteTime.ToString('o'))"
        } | Set-Content -Path $delta -Encoding ASCII
    $count = (Get-Content $delta).Count
    Log "    enumerated $count files"

    # [3] Upload via Node
    Log '[3] upload-delta.js'
    $uploadJs = Join-Path $prod 'upload-delta.js'
    $out = & $nodeExe $uploadJs --delta $delta --batch 100 2>&1
    $out | ForEach-Object { Log $_ }

    Log '=== pipeline end (OK) ==='
} catch {
    Log "FATAL: $_"
    Log "StackTrace: $($_.ScriptStackTrace)"
    throw
} finally {
    # Retention: keep 60 days of pipeline logs
    Get-ChildItem $logDir -Filter 'pipeline-*.log' -ErrorAction SilentlyContinue |
        Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-60) } |
        Remove-Item -Force -ErrorAction SilentlyContinue
}
'''

c = paramiko.SSHClient(); c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
c.connect('192.168.0.6', username='sysadmin', password=ad2_pwd,
          timeout=30, banner_timeout=45, look_for_keys=False, allow_agent=False)

sftp = c.open_sftp()
with sftp.open(f'{PROD_DIR.replace(chr(92),"/")}/run-pipeline.ps1', 'w') as fh:
    fh.write(RUN_PS1)
sftp.close()
print('[1] run-pipeline.ps1 updated with full node.exe path')

def psb64(cmd, to=120):
    enc = base64.b64encode(cmd.encode('utf-16-le')).decode()
    _, o, e = c.exec_command(f'powershell -NoProfile -EncodedCommand {enc}', timeout=to)
    return o.read().decode('utf-8','replace'), e.read().decode('utf-8','replace'), o.channel.recv_exit_status()

print('\n[2] trigger scheduled task')
out, _, _ = psb64('Start-ScheduledTask -TaskName "DataforthTestDatasheetUploader"')
print('  triggered')

print('\n[3] wait 25s for completion')
time.sleep(25)
out, _, _ = psb64(
    r'Get-ScheduledTaskInfo -TaskName "DataforthTestDatasheetUploader" | '
    r'Select LastRunTime,LastTaskResult,NextRunTime | Format-List'
)
print(out.strip())

print('\n[4] tail latest pipeline log')
out, _, _ = psb64(
    f'$latest = Get-ChildItem "{PROD_DIR}\\logs" -Filter "pipeline-*.log" -ErrorAction SilentlyContinue | Sort-Object LastWriteTime -Descending | Select -First 1; '
    f'"Log: $($latest.FullName)"; Get-Content $latest.FullName -Tail 80 -ErrorAction SilentlyContinue'
)
print(out.strip())

c.close()
