const Bot = require("../models/chatbot.model.js");
const multer = require("multer");
const path = require("path");
const fs = require("fs");
const { v4: uuidv4 } = require("uuid"); // <--- uuid
const { OpenAI } = require("openai");
const BotChatMessage = require("../models/message.model.js");
const Token = require("../models/token.model.js");
const Thread = require("../models/thread.bot.model.js");

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

// Ensure image directory exists
const fileDir = path.join(__dirname, "../botFiles/");

// Ensure directory exists
if (!fs.existsSync(fileDir)) {
  fs.mkdirSync(fileDir, { recursive: true });
}

// Multer storage configuration
const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, fileDir);
  },
  filename: (req, file, cb) => {
    const ext = path.extname(file.originalname);
    const uniqueName = `${uuidv4()}${ext}`;
    cb(null, uniqueName);
  },
});

// 30MB size limit
const upload = multer({
  storage,
  limits: { fileSize: 30 * 1024 * 1024 }, // 30MB
}); // 30MB

const CreateBot = async (req, res) => {
  try {
    const uploadMiddleware = upload.fields([{ name: "file", maxCount: 1 }]);

    uploadMiddleware(req, res, async (err) => {
      if (err) {
        if (err.code === "LIMIT_FILE_SIZE") {
          return res
            .status(400)
            .json({ message: "File size exceeds the limit (30MB)" });
        }
        return res.status(400).json({ message: err.message });
      }

      const { botName, tone, interests, trainingData, tokenName } = req.body;
      const file = req.files?.file?.[0];

      const token = await Token.findOne({ name: tokenName });
      if (!token) {
        return res.status(404).json({ error: "Token not found" });
      }
      const tokenId = token._id;
      const tokenSymbol = token.symbol;

      if (!botName) {
        return res.status(400).json({
          status: "error",
          error: "Bot name is required",
        });
      }

      if (!tone || !interests) {
        return res.status(400).json({
          status: "error",
          error: "Tone and interests are required",
        });
      }

      let finalTrainingData = trainingData || "";
      let filePath = null;

      if (file) {
        try {
          const fileContent = fs.readFileSync(file.path, "utf8");
          finalTrainingData = fileContent;
          filePath = file.path;
        } catch (fileErr) {
          console.error("File reading error:", fileErr);
          return res.status(500).json({
            status: "error",
            error: "Error processing uploaded file",
          });
        }
      }

      const userId = req.user.userId;
      const botUuid = uuidv4();
      const newBot = new Bot({
        uuid: botUuid, // Generate unique ID
        botName,
        tone: JSON.parse(tone),
        interests: JSON.parse(interests),
        trainingData: finalTrainingData,
        trainingFile: file ? file.filename : null,
        filePath,
        userId,
        tokenId,
        tokenName,
        tokenSymbol,
      });

      await newBot.save();
      token.status = "used";
      token.assignedBotUuid = botUuid;
      await token.save();

      res.json({
        status: "success",
        message: `Bot named "${botName}" created successfully!`,
        bot: newBot,
      });
    });
  } catch (err) {
    console.error("Error creating bot:", err);
    res.status(500).json({
      status: "error",
      error: "Failed to create bot",
      details: err.message,
    });
  }
};

const getAllBots = async (req, res) => {
  try {
    const bots = await Bot.find();
    res.status(200).json({ status: "success", bots });
  } catch (err) {
    console.error("Error fetching bots:", err);
    res.status(500).json({ status: "error", message: "Server error" });
  }
};

const getBotByUUID = async (req, res) => {
  try {
    const { uuid } = req.params;

    const bot = await Bot.findOne({ uuid });

    if (!bot) {
      return res.status(404).json({
        status: "error",
        message: "Bot not found",
      });
    }

    res.status(200).json({
      status: "success",
      bot,
    });
  } catch (err) {
    console.error("Error fetching bot by UUID:", err);
    res.status(500).json({
      status: "error",
      message: "Server error",
    });
  }
};

const userBot = async (req, res) => {
  const userId = req.user.userId;
  console.log(userId);
};

const Chat = async (req, res) => {

  try {
    const { uuid, threadid } = req.params;
    const { message } = req.body;
    const user = req.user.userId;

    if (!message) {
      return res.status(400).json({ error: "Message is required" });
    }

    const bot = await Bot.findOne({ uuid });
    if (!bot) {
      return res.status(404).json({ error: "Bot not found" });
    }
    const token = await Token.findOne({ assignedBotUuid:uuid });
    if (!token) {
      return res.status(404).json({ error: "token not found" });
    }

    const systemMessage = `You are an AI bot named ${bot.botName}. 
Your tone is ${bot.tone.join(", ")}. 
You specialize in ${bot.interests.join(", ")}.

Training Data Context:
${bot.trainingData},
${token.description}


Please use the above training data context to inform your responses while maintaining the specified tone and interests.`;

    const chatResponse = await openai.chat.completions.create({
      model: "gpt-4o",
      messages: [
        { role: "system", content: systemMessage },
        { role: "user", content: message },
      ],
      temperature: 0.7,
      max_tokens: 500,
    });

    const reply = chatResponse.choices[0].message.content;

    // Save the chat message to the database
    await BotChatMessage.create({
      botuuid: bot.uuid,
      botName: bot.botName,
      user,
      message,
      reply,
      thread: threadid,
    });

    // Check if the thread has a title and generate if needed
    const thread = await Thread.findById(threadid);
    if (
      thread &&
      (!thread.title || thread.title.trim().toLowerCase() === "untitled thread")
    ) {
      const titlePrompt = `
Based on the following conversation, generate a short and meaningful title (5-8 words max) summarizing the main topic. Do not use quotation marks or punctuation at the end.

User: ${message}
Assistant: ${reply}

Title:
      `;

      const titleResponse = await openai.chat.completions.create({
        model: "gpt-4o",
        messages: [{ role: "user", content: titlePrompt }],
        temperature: 0.5,
        max_tokens: 20,
      });

      const generatedTitle = titleResponse.choices[0].message.content.trim();
      if (generatedTitle) {
        await Thread.findByIdAndUpdate(threadid, { title: generatedTitle });
      }
    }

    res.status(200).json({ reply, threadId: threadid });
  } catch (err) {
    console.error("Error processing chat:", err);
    res.status(500).json({ error: "Failed to process chat" });
  }
};

const BotMessage = async (req, res) => {
  try {
    const { uuid, threadid } = req.params;
    const userId = req.user.userId;

    const messages = await BotChatMessage.find({
      thread: threadid,
      botuuid: uuid,
      user: userId,
    }).sort({ createdAt: 1 }); // optional: sort oldest to newest

    res.status(200).json({ status: "success", messages });
  } catch (err) {
    console.error("Error fetching user chat messages:", err);
    res.status(500).json({ status: "error", message: "Server error" });
  }
};
const getMyBots = async (req, res) => {
  try {
    const userId = req.user.userId;
    console.log("Fetching bots for user:", userId);

    const bots = await Bot.find({ userId });

    if (!bots.length) {
      return res.status(404).json({
        status: "error",
        message: "No bots found for this user",
      });
    }

    res.status(200).json({ status: "success", bots });
  } catch (err) {
    console.error("Error fetching user's bots:", err);
    res.status(500).json({ status: "error", message: "Server error" });
  }
};

const DeleteBot = async (req, res) => {
  try {
    const { botId } = req.params;

    const bot = await Bot.findById(botId);
    if (!bot) {
      return res.status(404).json({ error: "Bot not found" });
    }

    // Update the assigned token, if present
    if (bot.tokenId) {
      await Token.findByIdAndUpdate(bot.tokenId, {
        status: "unused",
        assignedBotUuid: null,
      });
    }

    // Optionally remove the training file from the file system
    if (bot.filePath) {
      fs.unlink(bot.filePath, (err) => {
        if (err) {
          console.error("Error deleting file:", err);
        }
      });
    }

    // Delete the bot
    await Bot.findByIdAndDelete(botId);

    res.json({ status: "success", message: "Bot deleted and token updated." });
  } catch (err) {
    console.error("Error deleting bot:", err);
    res
      .status(500)
      .json({ error: "Failed to delete bot", details: err.message });
  }
};

module.exports = {
  getMyBots,
  CreateBot,
  getAllBots,
  getBotByUUID,
  Chat,
  BotMessage,
  DeleteBot,
};
