/*
 * listar-agentes - Lista agentes em agentes/*.json
 * Uso: pp --listar-agentes[=xxx]
 *
 * Sem argumento: lista todos os agentes em ordem alfabética.
 * Com argumento: filtra agentes cujo nome contenha 'xxx'.
 */

#define _GNU_SOURCE
#define _DEFAULT_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <dirent.h>
#include <unistd.h>
#include <limits.h>
#include <sys/stat.h>
#include "../restricao.h"

static void uso(void)
{
    fputs(
        "Uso:\n"
        "  pp --listar-agentes[=<filtro>]\n"
        "  pp --listar-agentes <filtro>\n"
        "  pp --listar-agentes --ajuda:<grupo>\n"
        "\n"
        "Descrição:\n"
        "  Lista agentes disponíveis no sistema atual, com filtro opcional por trecho.\n"
        "\n"
        "Grupos de ajuda: uso, filtro, comportamento, exemplos.\n"
        "\n"
        "1) Uso e ajuda [uso ajuda]\n"
        "  --ajuda, --help, -h            Exibe esta ajuda\n"
        "  --ajuda:<grupo>                Filtra um grupo. Ex: pp --listar-agentes --ajuda:filtro\n"
        "\n"
        "2) Filtro [filtro entrada]\n"
        "  =<filtro>                      Filtra pelo trecho informado\n"
        "  <filtro>                       Forma alternativa como argumento separado\n"
        "  Sem filtro                     Lista todos os itens\n"
        "  Exemplo com todas as flags do grupo:\n"
        "    pp --listar-agentes=seguranca  ou  pp --listar-agentes seguranca\n"
        "\n"
        "3) Comportamento [comportamento]\n"
        "  Ordena os resultados alfabeticamente. A busca por trecho é case-insensitive\n"
        "  quando suportada pelo comando.\n"
        "\n"
        "4) Exemplos [exemplos]\n"
        "  pp --listar-agentes\n"
        "  pp --listar-agentes=seguranca\n"
        "  pp --listar-agentes seguranca\n",
        stdout);
}

static int termina_com(const char *s, const char *suf)
{
    size_t a = strlen(s), b = strlen(suf);
    return a >= b && strcasecmp(s + a - b, suf) == 0;
}

static int cmp_str(const void *a, const void *b)
{
    return strcasecmp(*(const char *const *)a, *(const char *const *)b);
}

static int nome_contem(const char *nome, const char *filtro)
{
    if (!filtro || !*filtro) return 1;
    return !!strcasestr(nome, filtro);
}

int main(int argc, char **argv)
{     if (restricao_verificar("listar-agentes") != 0) return 1; 
    const char *filtro = "";

    for (int i = 1; i < argc; i++) {
        if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "--ajuda") || !strcmp(argv[i], "-h")) {
            uso();
            return 0;
        }
        if (argv[i][0] != '-' && !filtro[0]) {
            filtro = argv[i];
            continue;
        }
        uso();
        return 1;
    }

    char raiz[PATH_MAX];
    if (!getcwd(raiz, sizeof(raiz))) {
        perror("listar-agentes: getcwd");
        return 1;
    }

    char dir[PATH_MAX * 2];
    snprintf(dir, sizeof(dir), "%s/agentes", raiz);

    DIR *d = opendir(dir);
    if (!d) {
        fprintf(stderr, "listar-agentes: diretorio agentes nao encontrado.\n");
        return 1;
    }

    int cap = 32, total = 0;
    char **nomes = malloc((size_t)cap * sizeof(char *));
    if (!nomes) { closedir(d); return 1; }

    struct dirent *e;
    while ((e = readdir(d)) != NULL) {
        const char *n = e->d_name;
        if (!termina_com(n, ".json")) continue;
        if (!nome_contem(n, filtro)) continue;

        if (total >= cap) {
            cap *= 2;
            char **nv = realloc(nomes, (size_t)cap * sizeof(char *));
            if (!nv) { closedir(d); free(nomes); return 1; }
            nomes = nv;
        }
        nomes[total] = strdup(n);
        if (!nomes[total]) { closedir(d); free(nomes); return 1; }
        total++;
    }
    closedir(d);

    qsort(nomes, (size_t)total, sizeof(char *), cmp_str);

    for (int i = 0; i < total; i++) {
        printf("%s\n", nomes[i]);
        free(nomes[i]);
    }
    free(nomes);

    if (total == 0) {
        printf("Nenhum agente encontrado");
        if (filtro && *filtro) printf(" com '%s'", filtro);
        printf(".\n");
    }

    return 0;
}
