#include "conectores-operacional.h"

static void uso(void) {
    printf("Uso:\n");
    printf("  ./validar-recebidos [--revalidar] [--pacote=/caminho/pacote.tar.gz]\n\n");
    printf("Valida pacotes recebidos, cria marcas operacionais e emite <pacote>.selo-validacao.json assinado pelo servidor.\n");
}

int main(int argc, char **argv) {
    int revalidar = 0;
    const char *somente = NULL;
    for (int i = 1; i < argc; i++) {
        if (strcmp(argv[i], "--revalidar") == 0) revalidar = 1;
        else if (starts_with(argv[i], "--pacote=")) somente = argv[i] + 9;
        else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--ajuda") == 0) { uso(); return 0; }
        else { fprintf(stderr, "argumento invalido: %s\n", argv[i]); uso(); return 2; }
    }

    mkdir_p(GC_RECEBIDOS, 0777);
    chmod(GC_RECEBIDOS, 01777); /* upload publico, mas marcas do servidor nao devem ser removiveis pelo usuario web */
    mkdir_p(GC_BASE "/tmp", 0770);
    chmod(GC_BASE "/tmp", 0770);

    static char pacotes[4096][PATH_MAX];
    int total = 0;
    if (somente) { snprintf(pacotes[total++], PATH_MAX, "%s", somente); }
    else total = listar_pacotes(pacotes, 4096);
    if (total == 0) { printf("Nenhum pacote encontrado em %s\n", GC_RECEBIDOS); return 0; }

    int aprovados = 0, reprovados = 0, ignorados = 0;
    for (int i = 0; i < total; i++) {
        char pacote_real[PATH_MAX];
        if (canonical_path(pacotes[i], pacote_real, sizeof(pacote_real)) != 0) { printf("[ERRO] pacote invalido: %s\n", pacotes[i]); reprovados++; continue; }
        const char *pacote = pacote_real;
        if (!is_file_p(pacote)) { printf("[ERRO] pacote nao encontrado: %s\n", pacote); reprovados++; continue; }
        char map[PATH_MAX], mrep[PATH_MAX], minst[PATH_MAX], msval[PATH_MAX], mssandbox[PATH_MAX];
        marker_path(pacote, "aprovado", map, sizeof(map));
        marker_path(pacote, "reprovado", mrep, sizeof(mrep));
        marker_path(pacote, "instalado", minst, sizeof(minst));
        marker_path(pacote, "selo-validacao", msval, sizeof(msval));
        marker_path(pacote, "selo-sandbox", mssandbox, sizeof(mssandbox));
        if (!revalidar && (is_file_p(map) || is_file_p(mrep) || is_file_p(minst) || is_file_p(msval))) {
            printf("[IGNORADO] ja possui marca/selo: %s\n", pacote);
            ignorados++;
            continue;
        }
        char lock[PATH_MAX]; snprintf(lock, sizeof(lock), "%s.validando.lock", pacote);
        if (is_file_p(lock)) { printf("[IGNORADO] lock ativo: %s\n", pacote); ignorados++; continue; }
        write_text_file(lock, "lock\n", 0664);

        char log[65536] = "";
        char nome[256] = "";
        char sha[128] = "";
        sha256_file(pacote, sha, sizeof(sha));
        int validou = validar_pacote_recebido(pacote, nome, sizeof(nome), log, sizeof(log)) == 0;
        int ok = validou;
        unlink(map); unlink(mrep); unlink(msval); unlink(mssandbox);
        if (ok && gc_emitir_selo_pacote(pacote, "selo-validacao", nome, "servidor", "validacao-estatica", "validar-recebidos.c", log, sizeof(log)) != 0) {
            ok = 0;
            sb_add(log, sizeof(log), "falha emitindo selo de validacao; pacote nao sera aprovado\n");
        }
        const char *tipo = ok ? "aprovado" : "reprovado";
        char marca[PATH_MAX]; marker_path(pacote, tipo, marca, sizeof(marca));
        char json[131072];
        char epac[PATH_MAX * 2], enome[512], esha[160], etipo[128];
        gc_json_escape_copy(pacote, epac, sizeof(epac));
        gc_json_escape_copy(nome, enome, sizeof(enome));
        gc_json_escape_copy(sha, esha, sizeof(esha));
        gc_json_escape_copy(tipo, etipo, sizeof(etipo));
        snprintf(json, sizeof(json),
            "{\n"
            "  \"status\": \"%s\",\n"
            "  \"pacote\": \"%s\",\n"
            "  \"sha256\": \"%s\",\n"
            "  \"conector\": \"%s\",\n"
            "  \"validadoEm\": %ld,\n"
            "  \"validador\": \"validar-recebidos.c\",\n"
            "  \"seloValidacao\": %s,\n"
            "  \"log\": %s\n"
            "}\n",
            etipo, epac, esha, enome, (long)time(NULL), ok ? "true" : "false", "\"ver arquivo .log correspondente\"");
        write_text_file(marca, json, 0444);
        chmod(marca, 0444);
        char logpath[PATH_MAX]; snprintf(logpath, sizeof(logpath), "%s.log", marca);
        write_text_file(logpath, log, 0664);
        unlink(lock);
        if (ok) { printf("[APROVADO+SELO] %s => %s\n", pacote, nome); aprovados++; }
        else { printf("[REPROVADO] %s => %s\n", pacote, log[0] ? log : "erro de validacao"); reprovados++; }
    }
    printf("\nResumo: total=%d aprovados=%d reprovados=%d ignorados=%d\n", total, aprovados, reprovados, ignorados);
    return reprovados > 0 ? 1 : 0;
}
