import { Prisma, PrismaClient } from "@prisma/client";
import { DiscordAccessTokenResponse } from "./app/oauth/discord/oauth";

async function refreshDiscordTokens(prisma: PrismaClient) {
  // refresh 6 hours before expiry
  const refreshWindow = 6 * 60 * 60 * 1000;

  const discordAuths = await prisma.discordAuth.findMany({
    where: {
      expiresAt: {
        lte: new Date(Date.now() + refreshWindow)
      }
    }
  });

  for (const discordAuth of discordAuths) {
    const req = await fetch("https://discord.com/api/oauth2/token", {
      method: "POST",
      headers: {
        "Content-Type": "application/x-www-form-urlencoded"
      },
      body: new URLSearchParams({
        client_id: process.env.DISCORD_CLIENT_ID,
        client_secret: process.env.DISCORD_CLIENT_SECRET,
        grant_type: "refresh_token",
        refresh_token: discordAuth.refreshToken
      }).toString()
    });

    const res: DiscordAccessTokenResponse = await req.json();

    await prisma.discordAuth.update({
      where: {
        id: discordAuth.id
      },
      data: {
        accessToken: res.access_token,
        refreshToken: res.refresh_token,
        expiresAt: new Date(Date.now() + res.expires_in * 1000)
      }
    });
  }
}

async function expireTickets(prisma: PrismaClient) {
  const expired = await prisma.authTicket.findMany({
    where: {
      expiresAt: {
        lte: new Date()
      }
    }
  });

  for (const ticket of expired) {
    await prisma.authTicket.delete({
      where: {
        id: ticket.id
      }
    });
  }
}

let prisma: PrismaClient;
if (global.prisma == undefined) {
  global.prisma = new PrismaClient();
  prisma = global.prisma;

  setInterval(async () => {
    await refreshDiscordTokens(prisma);
    await expireTickets(prisma);
  }, 60 * 1000);
} else {
  prisma = global.prisma;
}

export default prisma;
