<#
.SYNOPSIS
    JingTian LLM - File Sync Script
.DESCRIPTION
    Syncs files between Windows (BenjaminTeam/) and the Ubuntu server.
    - PULL first: Ubuntu -> Windows for bidirectional files (pipeline outputs)
    - PUSH second: Windows -> Ubuntu (one-way, Windows is source of truth)

    Order matters: pull gets pipeline updates, then push sends everything
    (including those updates + Mr. Choi's edits) back as source of truth.

    Called automatically by Windows Task Scheduler every N minutes.
#>

param(
    [string]$SyncRoot = $PSScriptRoot
)

$ErrorActionPreference = "Continue"

# ============================================================================
# Helpers
# ============================================================================

function Read-Config {
    param([string]$Path)
    $config = @{}
    $section = ""
    $listItems = @()
    $listSection = ""

    foreach ($line in Get-Content $Path) {
        $line = $line.Trim()
        if ($line -eq "" -or $line.StartsWith("#")) { continue }

        if ($line -match '^\[(.+)\]$') {
            if ($listSection -and $listItems.Count -gt 0) {
                $config[$listSection] = $listItems
            }
            $section = $Matches[1]
            if ($section -eq "bidirectional") {
                $listSection = $section
                $listItems = @()
            } else {
                $listSection = ""
            }
            continue
        }

        if ($listSection) {
            $listItems += $line
        } elseif ($line -match '^(.+?)=(.+)$') {
            $key = "$section.$($Matches[1].Trim())"
            $config[$key] = $Matches[2].Trim()
        }
    }

    if ($listSection -and $listItems.Count -gt 0) {
        $config[$listSection] = $listItems
    }

    return $config
}

function Write-Log {
    param([string]$Message, [string]$Level = "INFO")
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $entry = "[$timestamp] [$Level] $Message"
    Add-Content -Path $logFile -Value $entry
    if ($Level -eq "ERROR") {
        Write-Host $entry -ForegroundColor Red
    }
}

# ============================================================================
# Setup
# ============================================================================

$configPath = Join-Path $SyncRoot "config.ini"
$rcloneExe  = Join-Path $SyncRoot "rclone\rclone.exe"
$rcloneConf = Join-Path $SyncRoot "rclone\rclone.conf"
$logsPath   = Join-Path $SyncRoot "logs"
$ignoreFile = Join-Path $SyncRoot ".sync_ignore"

# BenjaminTeam is three levels up from Code/Sync/ (_LLM -> BenjaminTeam)
$benjaminTeam = (Resolve-Path (Join-Path $SyncRoot "..\..\.." )).Path

# Log file: one per day
$logDate = Get-Date -Format "yyyy-MM-dd"
$logFile = Join-Path $logsPath "sync-$logDate.log"

# Ensure logs directory
if (-not (Test-Path $logsPath)) {
    New-Item -ItemType Directory -Path $logsPath -Force | Out-Null
}

# Preflight checks
if (-not (Test-Path $configPath)) {
    Write-Log "config.ini not found at $configPath" "ERROR"
    exit 1
}
if (-not (Test-Path $rcloneExe)) {
    Write-Log "rclone.exe not found at $rcloneExe. Run Setup.bat first." "ERROR"
    exit 1
}
if (-not (Test-Path $rcloneConf)) {
    Write-Log "rclone.conf not found at $rcloneConf. Run Setup.bat first." "ERROR"
    exit 1
}

# Read config
$config = Read-Config $configPath
$remoteName = $config["sync.remote_name"]
$remotePath = $config["server.remote_path"]
$bidirectionalFiles = @()
if ($config.ContainsKey("bidirectional")) {
    $bidirectionalFiles = $config["bidirectional"]
}

$remoteBase = "${remoteName}:${remotePath}"

Write-Log "=== Sync started ==="
Write-Log "BenjaminTeam: $benjaminTeam"
Write-Log "Remote: $remoteBase"

# ============================================================================
# Phase 1: PULL bidirectional files (Ubuntu -> Windows)
# Runs FIRST so pipeline updates reach Windows before push sends everything back.
# Uses --update: only copies if remote file is newer than local.
# This means Mr. Choi's recent edits are preserved (his file is newer).
# ============================================================================

if ($bidirectionalFiles.Count -gt 0) {
    Write-Log "--- Phase 1: PULL bidirectional files (Ubuntu -> Windows) ---"

    foreach ($relPath in $bidirectionalFiles) {
        # Normalize path separators
        $relPath = $relPath.Replace("/", "\")
        $remoteSrc = "${remoteBase}/$($relPath.Replace('\', '/'))"
        $localDest = Join-Path $benjaminTeam $relPath
        $localDir  = Split-Path $localDest -Parent

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

        Write-Log "Pulling: $relPath"

        try {
            $pullOutput = & $rcloneExe copyto $remoteSrc $localDest `
                --config $rcloneConf `
                --update `
                --contimeout 30s `
                --timeout 60s `
                --retries 3 `
                --log-level NOTICE 2>&1
            $pullExitCode = $LASTEXITCODE

            if ($pullExitCode -eq 0) {
                Write-Log "  Pulled OK: $relPath"
            } else {
                # Exit code 3 = directory not found / file doesn't exist yet (OK)
                if ($pullExitCode -eq 3) {
                    Write-Log "  Not found on server (yet): $relPath"
                } else {
                    Write-Log "  Pull failed (exit code: $pullExitCode): $relPath" "ERROR"
                    foreach ($line in $pullOutput) {
                        Write-Log "    $line" "ERROR"
                    }
                }
            }
        } catch {
            Write-Log "  Pull exception for ${relPath}: $_" "ERROR"
        }
    }
} else {
    Write-Log "No bidirectional files configured, skipping pull phase"
}

# ============================================================================
# Phase 2: PUSH (Windows -> Ubuntu)
# Windows is source of truth. rclone sync mirrors local to remote.
# Bidirectional files are EXCLUDED from push — they are managed by the
# pipeline on Ubuntu and pulled down in Phase 1.
# ============================================================================

Write-Log "--- Phase 2: PUSH (Windows -> Ubuntu) ---"

$pushArgs = @(
    "sync"
    $benjaminTeam
    $remoteBase
    "--config", $rcloneConf
    "--transfers", "4"
    "--checkers", "8"
    "--contimeout", "30s"
    "--timeout", "120s"
    "--retries", "3"
    "--log-level", "NOTICE"
)

# Add filter file if it exists
if (Test-Path $ignoreFile) {
    $pushArgs += "--filter-from"
    $pushArgs += $ignoreFile
}

# Exclude bidirectional files from push (pipeline manages these on Ubuntu)
foreach ($relPath in $bidirectionalFiles) {
    $excludePath = $relPath.Replace("\", "/")
    $pushArgs += "--exclude"
    $pushArgs += $excludePath
}

$pushStart = Get-Date
Write-Log "Running: rclone sync (push)"

try {
    $pushOutput = & $rcloneExe @pushArgs 2>&1
    $pushExitCode = $LASTEXITCODE
    $pushDuration = ((Get-Date) - $pushStart).TotalSeconds

    if ($pushExitCode -eq 0) {
        Write-Log "Push completed in ${pushDuration}s"
    } else {
        Write-Log "Push failed (exit code: $pushExitCode) in ${pushDuration}s" "ERROR"
        foreach ($line in $pushOutput) {
            Write-Log "  $line" "ERROR"
        }
    }
} catch {
    Write-Log "Push exception: $_" "ERROR"
}

# ============================================================================
# Done
# ============================================================================

Write-Log "=== Sync finished ==="
