#!/usr/bin/env php
<?php
/**
 * AI-Native CMS - Deploy CLI Tool
 * Deploy a project to remote hosting via FTP/SFTP
 * 
 * Usage: php cli/deploy.php --project=name --host=ftp.example.com --user=xxx --pass=xxx
 */

if (php_sapi_name() !== 'cli') {
    die(json_encode(['success' => false, 'error' => 'CLI only']));
}

$options = getopt('', ['project:', 'host:', 'user:', 'pass:', 'port:', 'path:', 'method:', 'help', 'dry-run']);

if (isset($options['help']) || empty($options)) {
    echo <<<HELP
AI-Native CMS - Site Deployer

Usage:
  php cli/deploy.php --project=<name> --host=<host> --user=<user> --pass=<pass> [options]

Required:
  --project   Project directory name (in ./projects/)
  --host      FTP/SFTP hostname
  --user      FTP username
  --pass      FTP password

Options:
  --port      Port (default: 21 for FTP, 22 for SFTP)
  --path      Remote path (default: /public_html)
  --method    Transfer method: ftp, sftp (default: ftp)
  --dry-run   Show what would be uploaded without uploading
  --help      Show this help message

Examples:
  php cli/deploy.php --project=smith-law --host=ftp.hostinger.com --user=u123 --pass=secret
  php cli/deploy.php --project=clinic --host=server.com --user=admin --pass=pass --method=sftp

HELP;
    exit(0);
}

// Validate required arguments
$required = ['project', 'host', 'user', 'pass'];
foreach ($required as $req) {
    if (empty($options[$req])) {
        output(['success' => false, 'error' => "Missing required parameter: --$req"]);
    }
}

$project = $options['project'];
$host = $options['host'];
$user = $options['user'];
$pass = $options['pass'];
$method = $options['method'] ?? 'ftp';
$port = $options['port'] ?? ($method === 'sftp' ? 22 : 21);
$remotePath = $options['path'] ?? '/public_html';
$dryRun = isset($options['dry-run']);

// Find project directory
$projectDir = __DIR__ . '/../projects/' . $project;
if (!is_dir($projectDir)) {
    // Try direct path
    if (is_dir($project)) {
        $projectDir = $project;
    } else {
        output(['success' => false, 'error' => "Project not found: $project"]);
    }
}

echo "Deploying: $project\n";
echo "Host: $host:$port\n";
echo "Remote: $remotePath\n";
echo "Method: $method\n";
if ($dryRun)
    echo "DRY RUN MODE - No files will be uploaded\n";
echo "\n";

// Get list of files to upload
$files = [];
$localBase = realpath($projectDir);
$iterator = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator($localBase, RecursiveDirectoryIterator::SKIP_DOTS),
    RecursiveIteratorIterator::SELF_FIRST
);

$excludePatterns = [
    '/\.git/',
    '/\.DS_Store/',
    '/\.env$/',
    '/cache\//',
    '/vendor\//',
    '/node_modules\//',
];

foreach ($iterator as $file) {
    $localPath = $file->getPathname();
    $relativePath = str_replace($localBase . '/', '', $localPath);

    // Check exclusions
    $exclude = false;
    foreach ($excludePatterns as $pattern) {
        if (preg_match($pattern, $relativePath)) {
            $exclude = true;
            break;
        }
    }

    if (!$exclude) {
        $files[] = [
            'local' => $localPath,
            'remote' => $remotePath . '/' . $relativePath,
            'is_dir' => $file->isDir(),
        ];
    }
}

echo "Files to upload: " . count($files) . "\n\n";

if ($dryRun) {
    foreach ($files as $f) {
        $type = $f['is_dir'] ? '[DIR]' : '[FILE]';
        echo "$type {$f['remote']}\n";
    }
    echo "\nDry run complete.\n";
    exit(0);
}

// Deploy based on method
if ($method === 'ftp') {
    deployFTP($host, $port, $user, $pass, $files);
} elseif ($method === 'sftp') {
    deploySFTP($host, $port, $user, $pass, $files);
} else {
    output(['success' => false, 'error' => "Unknown method: $method"]);
}

output(['success' => true, 'message' => 'Deployment complete', 'files' => count($files)]);

// ============ Deployment Functions ============

function deployFTP($host, $port, $user, $pass, $files)
{
    $conn = @ftp_connect($host, $port, 30);
    if (!$conn) {
        output(['success' => false, 'error' => "FTP connection failed to $host:$port"]);
    }

    if (!@ftp_login($conn, $user, $pass)) {
        ftp_close($conn);
        output(['success' => false, 'error' => "FTP login failed for user: $user"]);
    }

    ftp_pasv($conn, true);
    echo "Connected to FTP\n\n";

    $uploaded = 0;
    $errors = [];

    foreach ($files as $f) {
        if ($f['is_dir']) {
            @ftp_mkdir($conn, $f['remote']);
            echo "[DIR] {$f['remote']}\n";
        } else {
            $result = @ftp_put($conn, $f['remote'], $f['local'], FTP_BINARY);
            if ($result) {
                echo "[OK] {$f['remote']}\n";
                $uploaded++;
            } else {
                echo "[ERR] {$f['remote']}\n";
                $errors[] = $f['remote'];
            }
        }
    }

    ftp_close($conn);

    echo "\n";
    echo "Uploaded: $uploaded files\n";
    if (count($errors) > 0) {
        echo "Errors: " . count($errors) . "\n";
    }
}

function deploySFTP($host, $port, $user, $pass, $files)
{
    if (!function_exists('ssh2_connect')) {
        output(['success' => false, 'error' => 'SSH2 extension not installed. Install php-ssh2 or use FTP method.']);
    }

    $conn = @ssh2_connect($host, $port);
    if (!$conn) {
        output(['success' => false, 'error' => "SSH connection failed to $host:$port"]);
    }

    if (!@ssh2_auth_password($conn, $user, $pass)) {
        output(['success' => false, 'error' => "SSH authentication failed for user: $user"]);
    }

    $sftp = ssh2_sftp($conn);
    if (!$sftp) {
        output(['success' => false, 'error' => "SFTP subsystem failed"]);
    }

    echo "Connected to SFTP\n\n";

    $uploaded = 0;

    foreach ($files as $f) {
        $remotePath = "ssh2.sftp://$sftp{$f['remote']}";

        if ($f['is_dir']) {
            @mkdir($remotePath, 0755, true);
            echo "[DIR] {$f['remote']}\n";
        } else {
            // Ensure parent directory exists
            $parentDir = dirname($remotePath);
            if (!is_dir($parentDir)) {
                @mkdir($parentDir, 0755, true);
            }

            $result = @copy($f['local'], $remotePath);
            if ($result) {
                echo "[OK] {$f['remote']}\n";
                $uploaded++;
            } else {
                echo "[ERR] {$f['remote']}\n";
            }
        }
    }

    echo "\nUploaded: $uploaded files\n";
}

function output($data)
{
    if (defined('JSON_OUTPUT') && JSON_OUTPUT) {
        echo json_encode($data);
    }
    exit($data['success'] ? 0 : 1);
}
