const express = require('express');
const cors = require('cors');
const https = require('https');
const fs = require('fs');
const app = express();
const WebSocket = require("ws");
const dotenv = require("dotenv");
dotenv.config();

app.use(cors());
app.use(express.json());


// 1. GLOBAL CORS: This handles both standard and "preflight" (OPTIONS) requests.
// We removed the app.options('*') line that was causing your crash.
app.use(cors());

app.use(express.json());

// 2. SSL CONFIGURATION: Use your existing Let's Encrypt certificates.
// Ensure these paths match your VPS exactly.
const sslOptions = {
  key: fs.readFileSync('/etc/letsencrypt/live/stream.ktono.com/privkey.pem'),
  cert: fs.readFileSync('/etc/letsencrypt/live/stream.ktono.com/fullchain.pem')
};


const API_KEY = process.env.OPENAI_API_KEY;
if (!API_KEY) throw new Error("OPENAI_API_KEY missing");
app.use(cors({
  exposedHeaders: ["X-Final-Answer"]
}));

app.use(express.json());
const COMBINED_MATH_PROMPT = `
You are a math assistant.

Rules:
- If the question asks to solve, calculate, or evaluate:
  • Respond with ONLY the final answer.
  • Do NOT include steps, explanations, words, or formatting.
  • If numeric, return only the number.
  • If an expression, return only the expression.

- If the input is a numeric expression without context:
  • Return ONLY the evaluated result or simplified expression.

- If the question asks for a math concept or definition:
  • Explain the concept briefly using words.
  • Stay strictly math-related.
  • Do NOT add extra commentary.

- If the question is not related to math:
  • Do NOT respond.

Answer the following question:
`.trim();

const FALLBACK_TEXT = "No answer found";


// 3. YOUR API ROUTE
app.post('/ask', async (req, res) => {
    
    const { text, voice } = req.body;
    if (!text) return res.status(400).send("No question provided");
    let answerText = "";
    const tryPrompts = [COMBINED_MATH_PROMPT];
    async function askPrompt(index) {
    if (index >= tryPrompts.length) {
      return sendTTS(FALLBACK_TEXT);
    }

    answerText = "";
    let answered = false;

    const ws = new WebSocket(
      "wss://api.openai.com/v1/realtime?model=gpt-4o-realtime-preview",
      {
        headers: {
          Authorization: `Bearer ${API_KEY}`,
          "OpenAI-Beta": "realtime=v1",
        },
      }
    );


    const timeout = setTimeout(() => {
      if (!answered) {
        ws.close();
        askPrompt(index + 1);
      }
    }, 15000);

    ws.on("open", () => {

      ws.send(
        JSON.stringify({
          type: "conversation.item.create",
          item: {
            type: "message",
            role: "system",
            content: [{ type: "input_text", text: tryPrompts[index] }],
          },
        })
      );

      ws.send(
        JSON.stringify({
          type: "conversation.item.create",
          item: {
            type: "message",
            role: "user",
            content: [{ type: "input_text", text }],
          },
        })
      );
      ws.send(
        JSON.stringify({
          type: "response.create",
          response: { modalities: ["text"] },
        })
      );
    });

    ws.on("message", (data) => {
      const msg = JSON.parse(data.toString());

      if (msg.type === "response.text.delta") {
        answerText += msg.delta;
      }

      if (msg.type === "response.text.done" && !answered) {
        answered = true;
        clearTimeout(timeout);
        ws.close();

        if (index === 0) {
          answerText = answerText.trim();
        } else if (index === 1) {

          answerText = answerText.trim();

          const mathKeywords = [
            "number",
            "integer",
            "prime",
            "equation",
            "theorem",
            "factor",
            "math",
            "algebra",
            "geometry",
            "calculus",
          ];

          if (
            /[a-zA-Z]/.test(answerText) &&
            !mathKeywords.some((kw) => answerText.toLowerCase().includes(kw))
          ) {
            answerText = FALLBACK_TEXT;
          }
        }

        if (index === 0 || index === 1 || index === 2) {
          answerText = answerText.trim();

          const mathKeywords = [
            "number",
            "integer",
            "prime",
            "equation",
            "theorem",
            "factor",
            "math",
            "algebra",
            "geometry",
            "calculus",
          ];

          const hasLetters = /[a-zA-Z]/.test(answerText);
          const containsMathKeyword = mathKeywords.some((kw) =>
            answerText.toLowerCase().includes(kw)
          );

          if (hasLetters && !containsMathKeyword) {
            answerText = FALLBACK_TEXT;
          }
        }

        if (!answerText) answerText = FALLBACK_TEXT;

       sendTTS(answerText);
      }
    });
    ws.on("error", (err) => {
      clearTimeout(timeout);
      askPrompt(index + 1);
    });

    ws.on("close", () => log(" WS CLOSED"));
  }

  async function sendTTS(textToSpeak) {
    try {
      const ttsResponse = await fetch(
        "https://api.openai.com/v1/audio/speech",
        {
          method: "POST",
          headers: {
            Authorization: `Bearer ${API_KEY}`,
            "Content-Type": "application/json",
          },
          body: JSON.stringify({
            model: "gpt-4o-mini-tts",
            voice: voice || "alloy",
            input: textToSpeak,
            format: "mp3",
          }),
        }
      );

      const audioBuffer = Buffer.from(await ttsResponse.arrayBuffer());
      if (!res.headersSent) {
        res.setHeader("X-Final-Answer", encodeURIComponent(textToSpeak));
        res.setHeader("Content-Type", "audio/mpeg");
        res.send(audioBuffer);
      }
    } catch (err) {
      if (!res.headersSent) res.status(500).send("TTS generation failed");
    }
  }

  askPrompt(0);
    
});

// 4. THE SECURE SERVER: Create HTTPS server on port 3000
const PORT = 3000;
https.createServer(sslOptions, app).listen(PORT, '0.0.0.0', () => {
    console.log(`✅ Secure server running at https://stream.ktono`)});
