// Task Team — Deploy webhook — 2026-03-29
const { exec, execSync } = require("child_process");
const fs = require("fs");
const crypto = require("crypto");

const DEPLOY_SECRET = process.env.DEPLOY_SECRET || "taskteam-deploy-2026";
const EXEC_ENV = { ...process.env, PATH: "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", HOME: "/root" };
const DEPLOY_LOG = "/opt/task-team/deploy.log";

function runCmd(cmd, timeout) {
    return execSync(cmd, { encoding: "utf8", env: EXEC_ENV, timeout: timeout || 30000 });
}

async function deployRoutes(app) {
    // Override JSON parser in this plugin scope to capture raw body
    app.removeContentTypeParser("application/json");
    app.addContentTypeParser("application/json", { parseAs: "string" }, (req, body, done) => {
        req.rawBody = body;
        try {
            done(null, JSON.parse(body));
        } catch (e) {
            done(e);
        }
    });

    app.post("/deploy/webhook", async (req, reply) => {
        // Verify secret - support multiple methods
        const signature = req.headers["x-gitea-signature"];
        const headerSecret = req.headers["x-gitea-secret"];
        const bodySecret = req.body && req.body.secret;

        let authorized = false;

        // Method 1: Gitea HMAC-SHA256 signature
        if (signature && req.rawBody) {
            const hmac = crypto.createHmac("sha256", DEPLOY_SECRET).update(req.rawBody).digest("hex");
            authorized = (hmac === signature);
        }
        // Method 2: Plain secret header (manual/curl testing)
        if (!authorized && headerSecret === DEPLOY_SECRET) {
            authorized = true;
        }
        // Method 3: Secret in body
        if (!authorized && bodySecret === DEPLOY_SECRET) {
            authorized = true;
        }

        if (!authorized) {
            app.log.warn("Deploy webhook auth failed");
            return reply.code(401).send({ error: "invalid secret" });
        }

        const ref = (req.body && req.body.ref) || "";
        if (!ref.includes("master") && !ref.includes("main")) {
            return { status: "skipped", reason: "not master branch" };
        }

        app.log.info("Deploy triggered by Gitea webhook");

        const deployScript = `#!/bin/bash
set -e
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
export HOME="/root"
LOG="${DEPLOY_LOG}"
echo "=== Deploy started at $(date -Is) ===" >> $LOG

cd /opt/task-team
git pull origin master >> $LOG 2>&1

cd /opt/task-team/api
npm install --production >> $LOG 2>&1

pm2 reload taskteam-api --force >> $LOG 2>&1

if [ -d /opt/task-team/apps/tasks ] && [ -f /opt/task-team/apps/tasks/package.json ]; then
    cd /opt/task-team/apps/tasks
    NEXT_PUBLIC_API_URL=http://localhost:3000 npm run build >> $LOG 2>&1
    pm2 reload taskteam-web --force >> $LOG 2>&1 || true
fi

echo "=== Deploy completed at $(date -Is) ===" >> $LOG
`;
        fs.writeFileSync("/opt/task-team/deploy.sh", deployScript, { mode: 0o755 });
        exec("nohup /opt/task-team/deploy.sh &", { env: EXEC_ENV, detached: true });

        return { status: "deploying", message: "Deploy started in background. Check /deploy/status for progress." };
    });

    app.get("/deploy/status", async () => {
        try {
            const commit = runCmd("cd /opt/task-team && git log --oneline -1").trim();
            const pm2out = runCmd("pm2 jlist 2>/dev/null");
            const procs = JSON.parse(pm2out).map(p => ({
                name: p.name,
                status: p.pm2_env.status,
                uptime: p.pm2_env.pm_uptime,
                restarts: p.pm2_env.restart_time
            }));
            let lastDeploy = "";
            try {
                const log = fs.readFileSync(DEPLOY_LOG, "utf8");
                const lines = log.trim().split("\n");
                lastDeploy = lines.slice(-10).join("\n");
            } catch (_) {}
            return { status: "ok", commit, processes: procs, last_deploy: lastDeploy };
        } catch (e) {
            return { status: "error", message: e.message };
        }
    });
}

module.exports = deployRoutes;
// Pipeline verified 2026-03-29T13:33:44+00:00
