import * as cache from "@lib/cache/cache.ts";
import { getTimeCacheKey } from "@lib/string.ts";

export type PerformancePoint = {
  path: string;
  search: string;
  time: number;
  date: Date;
};

export type PerformanceRes = {
  max: number;
  res: {
    url: string;
    data: readonly [number, number, number, number];
  }[];
};

export const savePerformance = (url: string, milliseconds: number) => {
  const cacheKey = getTimeCacheKey();

  const u = new URL(url);
  if (u.pathname.includes("_frsh/")) return;
  u.searchParams.delete("__frsh_c");

  cache.set(
    `performance:${cacheKey}`,
    JSON.stringify({
      path: decodeURIComponent(u.pathname),
      search: u.search,
      time: Math.floor(milliseconds * 1000),
    }),
  );
};

export async function getPerformances(): Promise<PerformanceRes> {
  const d = new Date();
  const year = d.getFullYear();
  const month = d.getMonth().toString();
  const day = d.getDay().toString();

  const keys = await cache.keys(
    `performance:${year}:${month}:${day}:*`,
  );

  console.log(`performance:${year}:${month}:${day}:*`);

  const performances = await Promise.all(
    keys.map(async (key) =>
      JSON.parse(await cache.get<string>(key)) as PerformancePoint
    ),
  );

  let maximum = 0;

  const res = new Map<string, number[]>();
  for (const p of performances) {
    const id = p.path;
    const timings = res.get(id) || [];
    if (p.time > maximum) maximum = p.time;
    timings.push(p.time);
    res.set(id, timings);
  }

  return {
    max: maximum,
    res: [...res.entries()].map(([url, timings]) => {
      let total = 0;
      let min = Infinity;
      let max = -Infinity;
      for (const t of timings) {
        total += t;
        if (t < min) min = t;
        if (t > max) max = t;
      }

      return {
        url,
        data: [timings.length, min, total / timings.length, max] as const,
      };
    }).sort((a, b) => a.data[2] < b.data[2] ? 1 : -1),
  };
}
