import type { APIRoute } from "astro";
import { prisma } from "../../lib/prisma";
import { t, type I18nKey } from "../../../../i18n";

export const prerender = false;

const OPTION_FIELDS = [
  "idioma",
  "areas_colaborar",
  "dias_disponibles",
  "horario_preferido",
  "sexo",
  "fuera_ciudad",
  "misiones_internacionales",
  "condicion_medica",
  "voluntariado_anterior",
] as const;

async function multiValueDist(key: string): Promise<{ value: string; count: number }[]> {
  const rows = await prisma.$queryRaw<{ v: string; cnt: number }[]>`
    SELECT trim(unnest(string_to_array(value, ','))) AS v, count(DISTINCT formulario_id)::int AS cnt
    FROM respuestas
    WHERE key = ${key} AND btrim(value) <> ''
    GROUP BY v
    ORDER BY cnt DESC
  `;
  return rows.map((r) => ({ value: r.v, count: r.cnt }));
}

async function valueDist(key: string): Promise<{ value: string; count: number }[]> {
  const rows = await prisma.respuesta.groupBy({
    by: ["value"],
    where: { key, value: { not: "" } },
    _count: { _all: true },
  });
  return rows
    .filter((r) => r.value !== null)
    .map((r) => ({ value: r.value!, count: r._count._all }))
    .sort((a, b) => b.count - a.count);
}

export const GET: APIRoute = async () => {
  try {
    const campos = await prisma.campo.findMany({
      where: { key: { in: OPTION_FIELDS as unknown as string[] } },
    });

    const optionMaps: Record<string, Record<string, string>> = {};
    for (const c of campos) {
      optionMaps[c.key] = {};
      if (Array.isArray(c.options)) {
        for (const o of c.options as { value?: string; label?: string }[]) {
          if (o && o.value) {
            optionMaps[c.key][o.value] = o.label ? t("es", o.label as I18nKey) : o.value;
          }
        }
      }
    }

    const withLabels = (
      dist: { value: string; count: number }[],
      key: string
    ): { value: string; label: string; count: number }[] =>
      dist.map((d) => ({
        value: d.value,
        label: optionMaps[key]?.[d.value] || d.value,
        count: d.count,
      }));

    const [total, statuses, sexo, paises, [idiomas, areas, dias, horarios], condiciones, edad] =
      await Promise.all([
        prisma.formulario.count(),
        prisma.formulario.groupBy({ by: ["status"], _count: { _all: true } }),
        prisma.formulario.groupBy({ by: ["sexo"], _count: { _all: true } }),
        prisma.formulario.groupBy({
          by: ["pais"],
          _count: { _all: true },
          where: { pais: { not: null } },
          orderBy: { _count: { pais: "desc" } },
          take: 12,
        }),
        Promise.all([
          multiValueDist("idioma"),
          multiValueDist("areas_colaborar"),
          multiValueDist("dias_disponibles"),
          multiValueDist("horario_preferido"),
        ]),
        Promise.all(
          ["fuera_ciudad", "misiones_internacionales", "condicion_medica", "voluntariado_anterior"].map(
            (k) => valueDist(k)
          )
        ),
        prisma.$queryRaw<{ promedio: number | null }[]>`
          SELECT round(avg(extract(epoch from (now() - fecha_nacimiento)) / 31557600), 1) AS promedio
          FROM formularios
          WHERE fecha_nacimiento IS NOT NULL
        `,
      ]);

    const condKeys = [
      "fuera_ciudad",
      "misiones_internacionales",
      "condicion_medica",
      "voluntariado_anterior",
    ] as const;
    const condicionesObj: Record<string, Record<string, number>> = {};
    condKeys.forEach((k, i) => {
      condicionesObj[k] = Object.fromEntries(condiciones[i].map((c) => [c.value, c.count]));
    });

    const formatPais = paises
      .filter((p) => p.pais !== null)
      .map((p) => ({ value: p.pais!, count: p._count._all }));

    return Response.json({
      success: true,
      total,
      edad: { promedio: edad[0]?.promedio ?? null },
      idiomas: withLabels(idiomas, "idioma"),
      areas: withLabels(areas, "areas_colaborar"),
      dias: withLabels(dias, "dias_disponibles"),
      horarios: withLabels(horarios, "horario_preferido"),
      sexo: withLabels(
        sexo.filter((s) => s.sexo !== null).map((s) => ({ value: s.sexo!, count: s._count._all })),
        "sexo"
      ),
      paises: formatPais,
      statuses: statuses.map((s) => ({ value: s.status, count: s._count._all })),
      condiciones: condicionesObj,
    }, {
      headers: { "Cache-Control": "private, max-age=60, stale-while-revalidate=300" },
    });
  } catch (error) {
    console.error("Error en /api/admin/voluntarios/stats:", error);
    return Response.json(
      { success: false, message: "Error al obtener estadísticas" },
      { status: 500 }
    );
  }
};
