// Webhook receiver for Gitea push events
// This service listens for webhook events from Gitea and triggers a deployment
// when changes are pushed to the monitored branches

const express = require('express');
const http = require('http');
const crypto = require('crypto');
const { exec } = require('child_process');
const path = require('path');
const fs = require('fs');

// Configuration (can be moved to environment variables)
const config = {
    port: process.env.WEBHOOK_PORT || 9000,
    secret: process.env.WEBHOOK_SECRET || 'change-this-secret-in-production',
    deployScript: process.env.DEPLOY_SCRIPT || path.join(__dirname, 'webhook-deploy.sh'),
    logFile: process.env.LOG_FILE || path.join(__dirname, '../logs/webhook.log'),
    allowedBranches: (process.env.ALLOWED_BRANCHES || 'main,master').split(','),
    allowedRepositories: (process.env.ALLOWED_REPOSITORIES || 'mwhitnessing').split(',')
};

// Create logs directory if it doesn't exist
const logsDir = path.dirname(config.logFile);
if (!fs.existsSync(logsDir)) {
    fs.mkdirSync(logsDir, { recursive: true });
}

// Create Express app
const app = express();
app.use(express.json());

// Helper function to log messages
function log(message) {
    const timestamp = new Date().toISOString();
    const logMessage = `[${timestamp}] ${message}\n`;
    console.log(logMessage.trim());
    fs.appendFileSync(config.logFile, logMessage);
}

// Verify Gitea webhook signature
function verifySignature(req) {
    const signature = req.headers['x-gitea-signature'];
    if (!signature) {
        return false;
    }

    const hmac = crypto.createHmac('sha256', config.secret);
    const computedSignature = hmac.update(JSON.stringify(req.body)).digest('hex');

    return crypto.timingSafeEqual(
        Buffer.from(signature),
        Buffer.from(computedSignature)
    );
}

// Handle Gitea push webhook
app.post('/webhook', (req, res) => {
    // Log receipt of webhook
    log('Received webhook request');

    try {
        // Check if webhook signature is valid
        if (!verifySignature(req)) {
            log('Invalid webhook signature');
            return res.status(403).send('Invalid signature');
        }

        // Extract relevant information from the webhook payload
        const { ref, repository } = req.body;

        // Check if this is a branch we care about
        const branchName = ref.replace('refs/heads/', '');
        if (!config.allowedBranches.includes(branchName)) {
            log(`Ignoring push to branch: ${branchName}`);
            return res.status(200).send('Ignored branch');
        }

        // Check if this is a repository we care about
        const repoName = repository.name;
        if (!config.allowedRepositories.includes(repoName)) {
            log(`Ignoring push to repository: ${repoName}`);
            return res.status(200).send('Ignored repository');
        }

        // Log the event
        log(`Received push event for ${repoName}/${branchName}`);

        // Respond to webhook immediately
        res.status(200).send('Processing deployment');

        // Execute the deployment script with the branch name
        const command = `${config.deployScript} ${branchName}`;
        log(`Executing: ${command}`);

        exec(command, (error, stdout, stderr) => {
            if (error) {
                log(`Deployment error: ${error.message}`);
                return;
            }
            if (stderr) {
                log(`Deployment stderr: ${stderr}`);
            }
            log(`Deployment stdout: ${stdout}`);
            log('Deployment completed successfully');
        });
    } catch (error) {
        log(`Error processing webhook: ${error.message}`);
        if (!res.headersSent) {
            res.status(500).send('Error processing webhook');
        }
    }
});

// Start the server
const server = http.createServer(app);
server.listen(config.port, () => {
    log(`Webhook receiver listening on port ${config.port}`);
    log(`Monitoring branches: ${config.allowedBranches.join(', ')}`);
    log(`Monitoring repositories: ${config.allowedRepositories.join(', ')}`);
});

// Handle server shutdown
process.on('SIGTERM', () => {
    log('Shutting down webhook receiver...');
    server.close(() => {
        log('Webhook receiver stopped');
        process.exit(0);
    });
});

process.on('SIGINT', () => {
    log('Shutting down webhook receiver...');
    server.close(() => {
        log('Webhook receiver stopped');
        process.exit(0);
    });
}); 