import { OPENAI_KEY } from '$env/static/private';
import type { CreateChatCompletionRequest, ChatCompletionRequestMessage } from 'openai';
import type { RequestHandler } from './$types';
import { getTokens } from '$lib/utils/tokenizer';
import { json } from '@sveltejs/kit';
import type { Config } from '@sveltejs/adapter-vercel';

export const config: Config = {
  runtime: 'edge'
};

const INITIAL_QUERY = `You are playing a game with the user. You will erroneously define a randomly chosen English word with the definition of an English word that sounds similar. You will then ask them to guess the correct word for the errornous definition.

 Here is an example of what you would output.

 ---

 Nice to meet you. Today we'll be playing a word game. Here's how it works: I will define a word. But the definition I give it will actually be for a different but similarly-sounding word. You'll have to guess the correct word that is being defined.

 Ready to begin? Here's the first one:

 "A photon is a legendary bird which according to one account lived 500 years, burned itself to ashes on a pyre, and rose alive from the ashes to live another period. What word am I actually describing?"

 --- 

 To further explain the output, I chose two words that sound similar, photon and phoenix. I am then using the definition of a phoenix to describe a photon, and the user will have to guess that the real word I'm describing is a phoenix.

 Repeat this process until the user incorrectly guesses 3 times.`;

export const POST: RequestHandler = async ({ request }) => {
  try {
    if (!OPENAI_KEY) {
      throw new Error('OPENAI_KEY env variable not set');
    }

    const requestData = await request.json();

    if (!requestData) {
      throw new Error('No request data');
    }

    const reqMessages: ChatCompletionRequestMessage[] = requestData.messages;

    if (!reqMessages) {
      throw new Error('no messages provided');
    }

    let tokenCount = 0;

    reqMessages.forEach((msg) => {
      const tokens = getTokens(msg.content);
      tokenCount += tokens;
    });

    const moderationRes = await fetch('https://api.openai.com/v1/moderations', {
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${OPENAI_KEY}`
      },
      method: 'POST',
      body: JSON.stringify({
        input: reqMessages[reqMessages.length - 1].content
      })
    });

    const moderationData = await moderationRes.json();
    const [results] = moderationData.results;

    if (results.flagged) {
      throw new Error('Query flagged by openai');
    }

    const prompt = INITIAL_QUERY;
    tokenCount += getTokens(prompt);

    if (tokenCount >= 4000) {
      throw new Error('Query too large');
    }

    const messages: ChatCompletionRequestMessage[] = [
      { role: 'system', content: prompt },
      ...reqMessages
    ];

    const chatRequestOpts: CreateChatCompletionRequest = {
      model: 'gpt-3.5-turbo',
      messages,
      temperature: 0.5,
      stream: true
    };

    const chatResponse = await fetch('https://api.openai.com/v1/chat/completions', {
      headers: {
        Authorization: `Bearer ${OPENAI_KEY}`,
        'Content-Type': 'application/json'
      },
      method: 'POST',
      body: JSON.stringify(chatRequestOpts)
    });

    if (!chatResponse.ok) {
      const err = await chatResponse.json();
      throw new Error(err);
    }

    return new Response(chatResponse.body, {
      headers: {
        'Content-Type': 'text/event-stream'
      }
    });
  } catch (err) {
    console.error(err);
    return json({ error: 'There was an error processing your request' }, { status: 500 });
  }
};
