import { createMiddleware } from "@solidjs/start/middleware";
import colors from "colors";
import fs from "fs";
import { verifyRequestOrigin } from "lucia";
import { getCookie, getHeader, setCookie } from "vinxi/http";
import { lucia } from "./lib/auth";

colors.enable();

let started: boolean = false;

export default createMiddleware({
  onRequest: async (event) => {
    if (event.nativeEvent.node.req.method !== "GET") {
      const originHeader = getHeader("Origin") ?? null;
      const hostHeader = getHeader("Host") ?? null;
      if (
        !originHeader ||
        !hostHeader ||
        !verifyRequestOrigin(originHeader, [hostHeader])
      ) {
        event.nativeEvent.node.res.writeHead(403).end();
        return;
      }
    }

    const sessionId = getCookie(lucia.sessionCookieName) ?? null;
    if (!sessionId) {
      event.nativeEvent.context.session = null;
      event.nativeEvent.context.user = null;
      return;
    }

    const { session, user } = await lucia.validateSession(sessionId);
    if (session && session.fresh) {
      const sessionCookie = lucia.createSessionCookie(session.id);
      setCookie(
        sessionCookie.name,
        sessionCookie.value,
        sessionCookie.attributes,
      );
    }
    if (!session) {
      const sessionCookie = lucia.createBlankSessionCookie();
      setCookie(
        sessionCookie.name,
        sessionCookie.value,
        sessionCookie.attributes,
      );
    }

    event.nativeEvent.context.session = session;
    event.nativeEvent.context.user = user;
  },
  onBeforeResponse: async (event, response) => {
    let consoleLog = "",
      fileLog = "";

    if (!started) {
      try {
        await fs.promises.mkdir("log");
        console.log("Created 'log' Folder.");
      } catch {}
      started = true;
    }

    const currentDate = new Date();
    const year = currentDate.getFullYear();
    const month = String(currentDate.getMonth() + 1).padStart(2, "0");
    const day = String(currentDate.getDate()).padStart(2, "0");
    const hours = String(currentDate.getHours()).padStart(2, "0");
    const minutes = String(currentDate.getMinutes()).padStart(2, "0");
    const seconds = String(currentDate.getSeconds()).padStart(2, "0");

    // Create a short and numeric representation
    const date = `[${year}-${month}-${day}_${hours}:${minutes}:${seconds}]`;
    const xForwardedFor = event.request.headers.get("x-forwarded-for");
    const ip = (xForwardedFor || "127.0.0.1, 192.168.178.1").split(",");
    const route = event.request.url;
    const frontend = !new URL(event.request.url).pathname.startsWith("/api");
    const method = frontend ? "Frontend" : event.request.method;
    const code =
      (response.body as Response | undefined)?.status ?? event.response.status;
    consoleLog += [
      date,
      ip[0].yellow,
      method,
      code,
      route?.green,
      event.nativeEvent.context.user?.discord_id.rainbow,
    ].join(" ");
    fileLog += [
      date,
      ip[0],
      method,
      code,
      route,
      event.nativeEvent.context.user?.discord_id,
    ].join(" ");
    await fs.promises.appendFile("log/log.txt", fileLog + "\n");
    console.log(consoleLog);
  },
});
