import { sql } from "kysely";
import type { StackedTimeserie } from "~/components/timeserieBarChartStacked";
import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum";
import { adminProcedure, createTRPCRouter } from "~/server/api/trpc";
import { db } from "~/server/db";

export const statsRouter = createTRPCRouter({
	adminDashStats: adminProcedure.query(async () => {
		const userTimeserie = (
			await db
				.selectFrom("users")
				.select((eb) => [
					sql<Date>`date_trunc('day', created_at)`.as("date"),
					eb.fn.count<number>("id").as("value"),
				])
				.where("isAdmin", "=", false)
				.groupBy("date")
				.orderBy("date")
				.execute()
		).map((item) => ({
			date: item.date,
			value: parseInt(String(item.value)),
		}));

		const serviziTimeserie = {
			data: Object.values(
				(
					await db
						.selectFrom("servizio")
						.select((eb) => [
							sql<Date>`date_trunc('day', created_at)`.as("date"),
							eb.fn.count<number>("servizio_id").as("value"),
							"tipologia",
						])
						.groupBy(["date", "tipologia"])
						.orderBy("date")
						.execute()
				).reduce(
					(acc, item) => {
						const dateStr = item.date.toISOString().slice(0, 10);
						if (!acc[dateStr]) {
							acc[dateStr] = {
								date: item.date,
								valueA: 0,
								valueB: 0,
							};
						}
						if (item.tipologia === TipologiaPosizioneEnum.Transitorio) {
							acc[dateStr].valueA = parseInt(String(item.value));
						} else if (item.tipologia === TipologiaPosizioneEnum.Stabile) {
							acc[dateStr].valueB = parseInt(String(item.value));
						}
						return acc;
					},
					{} as Record<string, StackedTimeserie>,
				),
			),
			valueALabel: "Transitorio",
			valueBLabel: "Stabile",
		};

		const contattiTimeserie = (
			await db
				.selectFrom("servizio_annunci")
				.select((eb) => [
					sql<Date>`date_trunc('day', created_at)`.as("date"),
					eb.fn
						.count<number>(eb.fn("concat", ["servizio_id", "annunci_id"]))
						.as("value"),
				])
				.where("open_contatti_at", "is not", null)
				.groupBy("date")
				.orderBy("date")
				.execute()
		).map((item) => ({
			date: item.date,
			value: parseInt(String(item.value)),
		}));

		const userCount =
			(
				await db
					.selectFrom("users")
					.select((eb) => [eb.fn.count<number>("id").as("count")])
					.executeTakeFirst()
			)?.count || 0;

		return {
			contattiTimeserie,
			serviziTimeserie,
			userCount,
			userTimeserie,
		};
	}),
});
