const http = require('http');
const https = require('https'); // Adicionado caso precise de HTTPS, mas usaremos HTTP para a VPN
const { exec } = require('child_process');
const fs = require('fs');

const PORT = 9000;
const HOST = '10.99.0.4';
const SECRET_TOKEN = 'gitea_webhook_secret_clube67_58e4a92c3d18';
const SCRIPT_PATH = '/home/deploy/stack/clube67/deploy-prod-builder.sh';
const LOG_FILE = '/home/deploy/stack/webhook-listener/deploy.log';
const GITEA_API_URL = 'http://10.99.0.3:3000/api/v1';
const GITEA_TOKEN = process.env.GITEA_TOKEN || 'ada47ca2fb196319dd10245cc216a327dac857ec';

function log(message) {
  const timestamp = new Date().toISOString();
  const logMessage = '[' + timestamp + '] ' + message + '\n';
  console.log(message);
  fs.appendFileSync(LOG_FILE, logMessage, 'utf8');
}

// Funcao para atualizar o status do commit no Gitea usando a API
function updateCommitStatus(owner, repo, sha, state, description) {
  if (!owner || !repo || !sha) return;
  const postData = JSON.stringify({
    state: state,
    target_url: 'http://' + HOST + ':' + PORT,
    description: description,
    context: 'continuous-integration/webhook'
  });

  const url = new URL(`${GITEA_API_URL}/repos/${owner}/${repo}/statuses/${sha}`);
  const options = {
    hostname: url.hostname,
    port: url.port,
    path: url.pathname,
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'token ' + GITEA_TOKEN,
      'Content-Length': Buffer.byteLength(postData)
    }
  };

  const req = http.request(options, (res) => {
    let responseBody = '';
    res.on('data', chunk => responseBody += chunk);
    res.on('end', () => {
      log(`Gitea Status API (${state}): HTTP ${res.statusCode}`);
    });
  });

  req.on('error', (e) => {
    log(`Erro ao chamar API do Gitea: ${e.message}`);
  });

  req.write(postData);
  req.end();
}

// Garante que o arquivo de log exista
try {
  if (!fs.existsSync(LOG_FILE)) {
    fs.writeFileSync(LOG_FILE, '', 'utf8');
  }
} catch (e) {
  console.error('Erro ao inicializar log:', e.message);
}

let isBuilding = false;

const server = http.createServer((req, res) => {
  // Apenas aceita requisicoes POST na rota /webhook
  const urlPath = req.url.split('?')[0];
  if (req.method !== 'POST' || urlPath !== '/webhook') {
    res.writeHead(404, { 'Content-Type': 'application/json' });
    return res.end(JSON.stringify({ error: 'Rota nao encontrada' }));
  }

  // Token de validacao nos headers (Gitea envia como x-gitea-token) ou query string (?token=...)
  const tokenHeader = req.headers['x-gitea-token'];

  // Parsear query params manualmente de forma simples
  let tokenQuery = null;
  const qIndex = req.url.indexOf('?');
  if (qIndex !== -1) {
    const query = req.url.substring(qIndex + 1);
    const pairs = query.split('&');
    for (let i = 0; i < pairs.length; i++) {
      const pair = pairs[i].split('=');
      if (decodeURIComponent(pair[0]) === 'token') {
        tokenQuery = decodeURIComponent(pair[1] || '');
        break;
      }
    }
  }

  const token = tokenHeader || tokenQuery;

  if (!token || token !== SECRET_TOKEN) {
    log('Tentativa de acesso nao autorizada: Token invalido ou ausente.');
    res.writeHead(401, { 'Content-Type': 'application/json' });
    return res.end(JSON.stringify({ error: 'Nao autorizado: Token invalido' }));
  }

  if (isBuilding) {
    log('Requisicao de build recebida, mas ja existe um build em andamento. Ignorando para evitar conflito de concorrencia.');
    res.writeHead(429, { 'Content-Type': 'application/json' });
    return res.end(JSON.stringify({ error: 'Um build ja esta sendo executado neste momento' }));
  }

  // Ler o body completo para inspecionar o payload do Gitea
  let body = '';
  req.on('data', function(chunk) { body += chunk.toString(); });
  req.on('end', function() {
    var payload = {};
    try { payload = JSON.parse(body); } catch (e) {}

    var commits = payload.commits || [];
    var headMsg = (payload.head_commit || {}).message || '';
    var allMessages = commits.map(function(c) { return c.message || ''; }).concat(headMsg).filter(function(m) { return m.trim() !== ''; });
    var VERSION_BUMP_RE = /^chore\(deploy\):\s*bump version/i;
    
    // Extrai dados do repositorio para a API do Gitea
    const repoOwner = payload.repository && payload.repository.owner ? payload.repository.owner.login : null;
    const repoName = payload.repository ? payload.repository.name : null;
    const commitSha = payload.after || (payload.head_commit ? payload.head_commit.id : null);

    if (allMessages.length > 0 && allMessages.every(function(msg) { return VERSION_BUMP_RE.test(msg); })) {
      log('Commit de bump de versao detectado -- deploy ignorado para evitar loop de CI.');
      updateCommitStatus(repoOwner, repoName, commitSha, 'success', 'Ignorado: bump version');
      res.writeHead(200, { 'Content-Type': 'application/json' });
      return res.end(JSON.stringify({ status: 'skipped', reason: 'version-bump commit' }));
    }

    // Retorna resposta de confirmacao imediata (HTTP 202 Accepted) para evitar timeout do Gitea
    res.writeHead(202, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ status: 'ok', message: 'Deploy automatico iniciado em segundo plano' }));

    // Inicia o processo de deploy
    isBuilding = true;
    log('Iniciando deploy-prod-builder.sh...');
    
    // Atualiza Gitea dizendo que o build comecou
    updateCommitStatus(repoOwner, repoName, commitSha, 'pending', 'Deploy em andamento na VPS 4');

    exec(SCRIPT_PATH, function(error, stdout, stderr) {
      isBuilding = false;
      if (error) {
        log('Erro no processo de deploy: ' + error.message);
        // Atualiza Gitea dizendo que o build falhou
        updateCommitStatus(repoOwner, repoName, commitSha, 'failure', 'Falha no deploy (VPS 4)');
        return;
      }
      log('Processo de deploy finalizado.');
      // Atualiza Gitea dizendo que o build foi concluido com sucesso
      updateCommitStatus(repoOwner, repoName, commitSha, 'success', 'Deploy concluido com sucesso (VPS 4)');
    });
  });
});

server.listen(PORT, HOST, function() {
  log('Webhook listener ativo em http://' + HOST + ':' + PORT + '/webhook com integracao a API do Gitea');
});
