const shared_consts = require('../tools/shared_nodejs');

const express = require('express');
const router = express.Router();

const tools = require('../tools/general');

var server_constants = require('../tools/server_constants');

var { authenticate, authenticate_noerror, auth_default } = require('../middleware/authenticate');

var mongoose = require('mongoose').set('debug', false);
const Subscription = require('../models/subscribers');

const _ = require('lodash');
const { QueryAI } = require('../models/queryai');
var { User } = require('../models/user');
const { Reaction } = require('../models/reaction');

const globalTables = require('../tools/globalTables');

const { ObjectId } = require('mongodb');

const OpenAI = require('openai');

const { PassThrough } = require('stream');

const { spawn } = require('child_process');

router.post('/getlist', authenticate_noerror, async function (req, res, next) {
  try {
    let idapp = req.body.idapp;

    let queryAIList = await QueryAI.findAllIdApp(idapp);

    return res.send({
      code: server_constants.RIS_CODE_OK,
      queryAIList,
    });
  } catch (e) {
    console.error('/getlist', e);
    return res.status(500).send({ code: server_constants.RIS_CODE_ERR, msg: e.message });
  }

  return null;
});

async function getDeepSeekResponse(prompt, options) {
  try {
    const deepseek = new OpenAI({
      baseURL: 'https://api.deepseek.com/v1',
      apiKey: process.env.DS_API_KEY,
      defaultHeaders: {
        'Content-Type': 'application/json',
      },
    });

    if (!options.withexplain) {
      prompt = prompt + '\n' + 'Ritornami solo il risultato, senza spiegazione.';
    }
    if (options.outputType) {
      prompt = prompt + '\n' + options.outputType;
    }

    const completionStream = await deepseek.chat.completions.create({
      model: options.model || 'deepseek-chat',
      messages: [
        { role: 'system', content: options?.contestsystem || '' },
        { role: 'user', content: prompt },
      ],
      temperature: options?.temp || 0.3,
      max_tokens: options?.max_tokens || 1000,
      stream: options?.stream || false,
    });

    if (options?.stream) {
      // Creiamo un PassThrough stream per inviare i chunk al frontend
      /*const stream = new PassThrough();
      completionStream.on('data', (chunk) => {
        stream.write(`data: ${JSON.stringify(chunk)}\n\n`);
      });
      completionStream.on('end', () => {
        stream.end();
      });
      return stream;*/

      return completionStream;
    } else {
      if (!completionStream || !completionStream.choices || completionStream.choices.length === 0) {
        throw new Error('Invalid response from DeepSeek API');
      }
      return completionStream.choices[0];
    }
  } catch (error) {
    console.error('DeepSeek Error:', error.response?.data || error.message);
    throw new Error('Failed to get AI response');
  }
}

router.post('/ds', authenticate, async (req, res) => {
  const { prompt, options } = req.body;

  const isollama = options.model.startsWith('gemma3');

  if (isollama) {
    // Endpoint per generare una risposta dal modello Ollama
    const { prompt } = req.body;
    // const model = "phi:3.8b-mini-4k"; // Modello predefinito
    const model = options.model;

    if (!prompt) {
      return res.status(400).json({ error: 'Il prompt è richiesto.' });
    }

    try {
      // Chiamata all'API di Ollama
      const ollama = spawn('curl', [
        '-X',
        'POST',
        'http://localhost:11434/api/generate',
        '-H',
        'Content-Type: application/json',
        '-d',
        JSON.stringify({
          model: model,
          prompt: prompt,
          stream: false, // Imposta a true se vuoi una risposta in streaming
        }),
      ]);

      let data = '';
      let error = '';

      ollama.stdout.on('data', (chunk) => {
        data += chunk;
      });

      ollama.stderr.on('data', (chunk) => {
        error += chunk;
      });

      ollama.on('close', (code) => {
        if (code !== 0) {
          console.error(`Errore Ollama: ${error}`);
          return res.status(500).json({ error: 'Errore nella generazione del modello.' });
        }

        try {
          // Ollama restituisce una risposta JSON
          const response = JSON.parse(data);
          const risp = response?.error ? response?.error : response?.response;
          //res.json({ response: response.response }); // Invia solo la risposta al frontend

          if (response?.error) {
            return res.send({
              code: server_constants.RIS_CODE_ERR,
              error: risp,
            });
          } else {
            return res.send({
              code: server_constants.RIS_CODE_OK,
              choice: risp,
            });
          }
        } catch (parseError) {
          console.error('Errore nel parsing della risposta di Ollama:', parseError);
          return res.send({
            code: server_constants.RIS_CODE_ERR,
            error: 'Errore nella risposta del modello.',
          });
        }
      });
    } catch (err) {
      console.error(err);
      return res.send({
        code: server_constants.RIS_CODE_ERR,
        error: 'Errore interno del server.',
      });
    }
  } else {
    const isstream = options && options?.stream;

    if (isstream) {
      // Se lo streaming è abilitato, restituiamo un flusso di dati
      res.setHeader('Content-Type', 'text/event-stream');
      res.setHeader('Cache-Control', 'no-cache');
      res.setHeader('Connection', 'keep-alive');

      try {
        // Ottieni il flusso di dati da DeepSeek
        const completionStream = await getDeepSeekResponse(prompt, options);

        for await (const chunk of completionStream) {
          if (chunk.choices && chunk.choices[0]) {
            const data = JSON.stringify({ choice: chunk.choices[0] });
            res.write(`data: ${data}\n\n`);
            try {
              const msg = chunk.choices[0].delta.content;
              if (msg) {
                console.log(msg);
                // await tools.sleep(10000)
              }
            } catch (e) {
              console.error('Error: ' + e.message);
            }
          }
        }

        res.write('data: [DONE]\n\n');
        res.end();
      } catch (error) {
        const errorstr = 'API Error:' + (error.response?.data || error.message);
        console.error(errorstr);

        // In caso di errore durante lo streaming, invia un messaggio di errore
        const errorData = JSON.stringify({
          code: server_constants.RIS_CODE_ERR,
          error: errorstr,
        });
        res.write(`data: ${errorData}\n\n`);
        res.end();
      }
    } else {
      try {
        // Se lo streaming non è abilitato, restituisci la risposta completa
        const choice = await getDeepSeekResponse(prompt, options);

        return res.send({
          code: server_constants.RIS_CODE_OK,
          choice,
        });
      } catch (error) {
        const errorstr = 'API Error:' + (error.response?.data || error.message);
        console.error(errorstr);

        // In caso di errore senza streaming, restituisci un errore standard
        return res.send({
          code: server_constants.RIS_CODE_ERR,
          error: errorstr,
        });
      }
    }
  }
});

module.exports = router;
