<?php
/**
 * Gitea Webhook Handler
 *
 * URL: https://your-domain.com/webhook.php
 * Gitea Content-Type: application/json
 * Gitea Secret: nilai WEBHOOK_SECRET dalam .env
 * Gitea Events: Push Events
 */

define('APP_ROOT', dirname(__DIR__));
define('LOG_FILE', APP_ROOT . DIRECTORY_SEPARATOR . 'storage' . DIRECTORY_SEPARATOR . 'logs' . DIRECTORY_SEPARATOR . 'webhook.log');

function log_msg(string $message): void
{
    $line = '[' . date('Y-m-d H:i:s') . '] ' . $message . PHP_EOL;
    file_put_contents(LOG_FILE, $line, FILE_APPEND | LOCK_EX);
}

function respond(int $code, string $message): never
{
    http_response_code($code);
    header('Content-Type: application/json');
    echo json_encode(['status' => $code, 'message' => $message]);
    exit;
}

function read_env(string $key, string $default = ''): string
{
    static $env = null;
    if ($env === null) {
        $env = [];
        $file = APP_ROOT . DIRECTORY_SEPARATOR . '.env';
        if (file_exists($file)) {
            foreach (file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $line) {
                $line = trim($line);
                if ($line === '' || str_starts_with($line, '#')) {
                    continue;
                }
                if (str_contains($line, '=')) {
                    [$k, $v] = explode('=', $line, 2);
                    $env[trim($k)] = trim($v, " \t\"'");
                }
            }
        }
    }

    return $env[$key] ?? (getenv($key) ?: $default);
}

// ── Hanya terima POST ────────────────────────────────────────────────────────
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    respond(405, 'Method Not Allowed');
}

$payload = file_get_contents('php://input');
if (empty($payload)) {
    respond(400, 'Empty payload');
}

// ── Sahkan signature Gitea ───────────────────────────────────────────────────
$secret = read_env('WEBHOOK_SECRET');
if (!empty($secret)) {
    $signature = $_SERVER['HTTP_X_GITEA_SIGNATURE'] ?? '';
    $expected  = hash_hmac('sha256', $payload, $secret);

    if (!hash_equals($expected, $signature)) {
        log_msg('WARN: Signature tidak sah dari IP ' . ($_SERVER['REMOTE_ADDR'] ?? 'unknown'));
        respond(403, 'Invalid signature');
    }
}

// ── Parse payload ────────────────────────────────────────────────────────────
$data = json_decode($payload, true);
if (json_last_error() !== JSON_ERROR_NONE) {
    respond(400, 'Invalid JSON payload');
}

$event    = $_SERVER['HTTP_X_GITEA_EVENT'] ?? 'unknown';
$ref      = $data['ref'] ?? '';
$branch   = basename($ref);
$pusher   = $data['pusher']['login'] ?? 'unknown';
$commitId = substr($data['after'] ?? '', 0, 8);

log_msg("Event: $event | Branch: $branch | Pusher: $pusher | Commit: $commitId");

// ── Hanya deploy pada push ke master/main ───────────────────────────────────
$targetBranch = read_env('WEBHOOK_BRANCH', 'master');
if ($event !== 'push' || $branch !== $targetBranch) {
    respond(200, "Skipped — event=$event branch=$branch (target=$targetBranch)");
}

// ── Jalankan deployment script ───────────────────────────────────────────────
$deployScript = APP_ROOT . '\\scripts\\deploy.ps1';
$deployLog    = APP_ROOT . '\\storage\\logs\\deploy-' . date('Ymd-His') . '.log';

if (!file_exists($deployScript)) {
    log_msg('ERROR: Deploy script tidak dijumpai: ' . $deployScript);
    respond(500, 'Deploy script not found');
}

$command = sprintf(
    'powershell.exe -NonInteractive -ExecutionPolicy Bypass -File "%s" > "%s" 2>&1',
    $deployScript,
    $deployLog
);

log_msg("Menjalankan: $command");

$descriptors = [
    0 => ['pipe', 'r'],
    1 => ['file', $deployLog, 'a'],
    2 => ['file', $deployLog, 'a'],
];

$process = proc_open($command, $descriptors, $pipes, APP_ROOT);

if (!is_resource($process)) {
    log_msg('ERROR: Gagal memulakan proses deployment');
    respond(500, 'Failed to start deployment process');
}

fclose($pipes[0]);
$exitCode = proc_close($process);

log_msg("Deployment selesai — exit code: $exitCode | log: $deployLog");

if ($exitCode === 0) {
    respond(200, "Deployment berjaya — commit $commitId");
} else {
    respond(500, "Deployment gagal — exit code $exitCode, semak $deployLog");
}
