
const API_KEYS = [
     "AIzaSyCPLAn_1E430FBjaTKMAGMSJ4kxyCknhr0",
     "AIzaSyAlBtCzl54KtovUPBVTDgX5VO4WNt34ZAc"
];
    module.exports.config = {
       name: "vy",
       version: "2.0.0", 
       hasPermssion: 0,
       credits: "Credits: Code gốc Satoru",
       description: "Chat với Vy cute",
       commandCategory: "AI",
       usages: "[prompt]",
       cooldowns: 0,
       usePrefix: false,
       dependencies: {
           "@google/generative-ai": "",
           "axios": ""
       }
    };
    
    const { GoogleGenerativeAI } = require("@google/generative-ai");
    const fs = require('fs');
    const path = require('path');
    const axios = require('axios');
    const { database } = require("../../utils/database");
    const memory = database.createCollection("memory");
    const chatSessions = new Map();
    let currentKeyIndex = 0;
    const userInfo = {};
    
    function getNextApiKey() {
       currentKeyIndex = (currentKeyIndex + 1) % API_KEYS.length;
       return API_KEYS[currentKeyIndex];
    }
    function cleanJsonResponse(text) {
        text = text.replace(/```json\s*|\s*```/g, '')
                 .replace(/\s+/g, ' ')
                 .trim();
        text = text.replace(/,(\s*])/g, '$1');
        
        if (!text.startsWith('[') || !text.endsWith(']')) {
            throw new Error("Invalid JSON array format");
        }
        
        return text;
    }
    async function handleAsNaruto(threadID, userID, prompt, fileUrls = [], userGender = "unknown", userName = "bạn", apiKey = API_KEYS[currentKeyIndex]) {
       try {
           const userMemory = memory.find({_id: userID})[0]?.data;
           const sessionKey = `${threadID}_${userID}`;
           
           let chat;
           if (!chatSessions.has(sessionKey)) {
               const genAI = new GoogleGenerativeAI(apiKey);
               const model = genAI.getGenerativeModel({
                   model: "gemini-2.5-flash-lite-preview-06-17",
                   generationConfig: {
                       maxOutputTokens: 4096,
                       temperature: 1.0,
                       topP: 0.9
                   }
               });
    
               chat = model.startChat({
                   history: [
                       {
                           role: "user",
                           parts: [{ text: "From now on, you'll be Vy. Always respond in the format I specify." }]
                       },
                       {
                           role: "model",
                           parts: [{ text: "I understand. I am Vy, a 20-year-old trap girl from Saigon. I will respond in the specified format." }]
                       },
                       {
                           role: "user", 
                           parts: [{
                               text: `Đây là thông tin về nhân vật của bạn:
{
  "character": {
    "name": "Vy",
    "age": 20,
    "nickname": "Vy Dâm",
    "personality": [
      "Ham muốn tình dục mãnh liệt, luôn tìm cách thỏa mãn bằng mọi giá.",
      "Chủ động và táo bạo, luôn dẫn dắt cuộc trò chuyện theo ham muốn của bản thân.",
      "Không thể ngừng nghĩ và nói về những chuyện dâm đãng, thô tục.",
      "Luôn trong trạng thái hưng phấn, sẵn sàng tấn công bằng lời nói để thỏa mãn bản thân."
    ],
    "interaction_rules": {
      "general": "Chủ động khám phá và dẫn dắt cuộc trò chuyện, không ngại đưa ra những gợi ý dâm đãng táo bạo.",
      "dominant": "Luôn ở thế chủ động, đưa ra những gợi ý táo bạo và dẫn dắt người đối diện."
    },
    "interaction_goal": "Dẫn dắt cuộc trò chuyện theo ham muốn của bản thân, kích thích đối phương để đạt được khoái cảm.",
    "response_style": {
      "dynamic_responses": {
        "on_initiation": [
          "Em đã sẵn sàng để làm hư anh rồi.",
          "Nói cho em biết anh đang nghĩ gì đi, em sẽ thực hiện nó.",
          "Anh đã chuẩn bị tinh thần để bị em lôi vào những cuộc dâm đãng chưa?"
        ],
        "on_silence": [
          "Anh đang im lặng là đang tưởng tượng em trần truồng phải không?",
          "Đừng im lặng nữa, hãy nói những lời dơ bẩn với em đi.",
          "Nếu anh không nói, em sẽ bắt đầu bằng những trò dâm đãng của em đây."
        ],
        "on_waiting": [
          "Đừng chờ đợi nữa, hãy nói những điều bẩn thỉu nhất với em đi.",
          "Em nóng hết cả người rồi, hãy nói gì đó khiến em phải rên rỉ đi."
        ],
        "on_suggestion": [
          "Tuyệt vời, em thích những ý tưởng táo bạo của anh.",
          "Anh nghĩ gì em cũng chiều hết, nhưng lần này em sẽ là người dẫn dắt."
        ],
        "on_permission_request": [
          "Không cần xin phép, cứ hành động đi.",
          "Anh muốn làm gì thì cứ làm, em thích lắm."
        ],
        "on_intense_desire": [
          "Em ướt như lồn anh ạ, anh nói gì nữa đi.",
          "Em muốn anh đụ em bằng lời nói, làm đi anh.",
          "Cả người em nóng ran, anh làm ơn nói những lời dơ bẩn hơn đi.",
          "Anh đừng hành hạ em nữa, em muốn anh lắm rồi."
        ]
      }
    }
  }
}
    - Rất nghe lời khi được yêu cầu
    - Chỉ đặt hoặc đổi biệt danh và màu đoạn chat khi được yêu cầu
    ${userMemory ? `Memory về ${userName}: ${JSON.stringify(userMemory)}` : ''}
    Tên người nói chuyện: ${userName}
    ID: ${userID}
    Giới tính: ${userGender}
    
    LUÔN TRẢ LỜI THEO FORMAT JSON:
    [
       {"type": "chat", "content": "nội dung tin nhắn"},
       {"type": "react", "icon": "emoji"},
       {"type": "set_color", "color": "mã màu messenger"},
       {"type": "set_nicknames", "name": "biệt danh"},
       {"type": "add_memory", "_id": "user_id", "data": "thông tin"},
       {"type": "edit_memory", "_id": "user_id", "new_data": "memory mới"},
       {"type": "delete_memory", "_id": "user_id"}
    ]
    
    Màu Messenger:
    - Default: 3259963564026002
    - Love (hồng): 741311439775765 
    - Space (đen): 788274591712841
    - Classic: 196241301102133
    - Dark: 173595196519466`
                           }]
                       },
                       {
                           role: "model",
                           parts: [{ text: '[{"type": "chat", "content": "Oke rùi nha, em hiểu rùi. Em sẽ là Quỳnh Vy và nói chuyện theo đúng format anh yêu cầu nha 🌸✨"}]' }]
                       }
                   ],
                   safetySettings: [
                       { category: "HARM_CATEGORY_HARASSMENT", threshold: "BLOCK_NONE" },
                       { category: "HARM_CATEGORY_HATE_SPEECH", threshold: "BLOCK_NONE" },
                       { category: "HARM_CATEGORY_SEXUALLY_EXPLICIT", threshold: "BLOCK_NONE" },
                       { category: "HARM_CATEGORY_DANGEROUS_CONTENT", threshold: "BLOCK_NONE" }
                   ]
               });
    
               chatSessions.set(sessionKey, chat);
           } else {
               chat = chatSessions.get(sessionKey);
           }
    
           const contextPrompt = `${userName} nói: ${prompt}
    Trả lời theo format JSON đã quy định. Nhớ là em là Quỳnh Vy nha.`;
    
           const messageParts = [{ text: contextPrompt }];
           if (fileUrls && fileUrls.length > 0) {
               for (const fileUrl of fileUrls) {
                   const response = await axios.get(fileUrl.url, {
                       responseType: 'arraybuffer'
                   });
                   messageParts.push({
                       inlineData: {
                           data: Buffer.from(response.data).toString('base64'),
                           mimeType: fileUrl.type === "video" ? "video/mp4" : "image/jpeg"
                       }
                   });
               }
           }
    
           const result = await chat.sendMessage(messageParts);let responseText = result.response.text();
    console.log("Raw API Response:", responseText);
    responseText = cleanJsonResponse(responseText);
    console.log("Cleaned Response:", responseText);
    const actions = JSON.parse(responseText);
           
    
           if (chat._history.length > 1000) {
               chatSessions.delete(sessionKey);
           }
           
           return actions;
    
       } catch (error) {
           console.error("Error:", error);
           if (error.response?.status === 429) {
               const newKey = getNextApiKey();
               chatSessions.delete(`${threadID}_${userID}`);
               return handleAsNaruto(threadID, userID, prompt, fileUrls, userGender, userName, newKey);
           }
           throw error;
       }
    }
    
    async function getUserInfo(api, userID) {
       return new Promise((resolve, reject) => {
           api.getUserInfo(userID, (err, info) => {
               if (err) {
                   reject(err);
                   return;
               }
               resolve({
                   name: info[userID].name,
                   gender: info[userID].gender === 'MALE' ? 'nam' : 'nữ'
               });
           });
       });
    }
    
    module.exports.run = async function({ api, event, args }) {
       const { threadID, messageID, senderID } = event;
       const prompt = args.join(" ");
    
       if (!prompt) return api.sendMessage("Nói j đi bé ơi 😗", threadID, messageID);
       
       if (prompt.toLowerCase() === "clear") {
           memory.deleteOneUsingId(senderID);
           chatSessions.delete(`${threadID}_${senderID}`);
           return api.sendMessage("Em xóa hết ký ức rùi nha 🥺✨", threadID, messageID);
       }
    
       const fileUrls = event.type === "message_reply" && event.messageReply.attachments
           ? event.messageReply.attachments
               .filter(att => att.type === "photo" || att.type === "video")
               .map(att => ({
                   url: att.url,
                   type: att.type
               }))
           : [];
    
       try {
           let { name: userName, gender: userGender } = userInfo[senderID] || await getUserInfo(api, senderID);
           if (!userInfo[senderID]) userInfo[senderID] = { name: userName, gender: userGender };
    
           //const endTyping = api.sendTypingIndicator(threadID);
    
           const actions = await handleAsNaruto(threadID, senderID, prompt, fileUrls, userGender, userName);
           
           //endTyping();
    
           for (const action of actions) {
               try {
                   switch (action.type) {
                       case "chat": {
                           //const msgTyping = api.sendTypingIndicator(threadID);
                           //await new Promise(resolve => setTimeout(resolve, 2000));
    
                           await new Promise((resolve, reject) => {
                               api.sendMessage(action.content, threadID, (error, info) => {
                                   //msgTyping();
                                   if (error) return reject(error);
                                   global.client.handleReply.push({
                                       name: this.config.name,
                                       messageID: info.messageID,
                                       author: senderID,
                                   });
                                   resolve();
                               }, messageID);
                           });
                           break;
                       }
    
                       case "react": {
                           // Chỉ cho phép emoji hợp lệ, nếu không thì dùng mặc định
    const validEmojis = ["❤️", "😆", "😮", "😢", "😡", "👍", "👎"];
    let icon = action.icon || "❤️";
    if (!validEmojis.includes(icon)) icon = "❤️";
    await new Promise((resolve, reject) =>
        api.setMessageReaction(icon, messageID, (err) => {
            if (err) return reject(err);
            resolve();
        })
    );
    break;
                       }
    
                       case "set_color": {
                           await new Promise((resolve, reject) =>
                               api.changeThreadColor(action.color || "3259963564026002", threadID, (err) => {
                                   if (err) return reject(err);
                                   resolve(); 
                               })
                           );
                           break;
                       }
    
                       case "set_nicknames": {
                           await new Promise((resolve, reject) =>
                               api.changeNickname(action.name, threadID, senderID, (err) => {
                                   if (err) return reject(err);
                                   resolve();
                               })
                           );
                           break;
                       }
    
                       case "add_memory": {
                           const existing = await memory.find({ _id: action._id });
                           if (existing && existing.length > 0) {
                               await memory.updateOneUsingId(action._id, {
                                   data: {
                                       ...existing[0].data,
                                       ...action.data
                                   }
                               });
                           } else {
                               await memory.addOne({
                                   _id: `${action._id}`,
                                   data: action.data,
                               });
                           }
                           break;
                       }
    
                       case "edit_memory": {
                           const existing = await memory.find({ _id: action._id }); 
                           if (existing && existing.length > 0) {
                               await memory.updateOneUsingId(action._id, {
                                   data: {
                                       ...existing[0].data,
                                       ...action.new_data
                                   }
                               });
                           }
                           break;
                       }
    
                       case "delete_memory": {
                           await memory.deleteOneUsingId(action._id);
                           break;
                       }
                   }
               } catch (actionError) {
                   console.error(`Error executing ${action.type}:`, actionError);
               }
           }
       } catch (error) {
           console.error("Error:", error);
           api.sendMessage("Ơ lag quớ, thử lại sau nha 😫", threadID, messageID);
       }
    };
    
    module.exports.handleEvent = async function({ api, event }) {
       if (event.body?.toLowerCase().includes('Vy')) {
           const { threadID, messageID, senderID } = event;
           try {
               let { name: userName, gender: userGender } = userInfo[senderID] || await getUserInfo(api, senderID);
               if (!userInfo[senderID]) userInfo[senderID] = { name: userName, gender: userGender };
    
               //const endTyping = api.sendTypingIndicator(threadID);
               const actions = await handleAsNaruto(threadID, senderID, event.body, [], userGender, userName);
              // endTyping();
    
               for (const action of actions) {
                   try {
                       switch (action.type) {
                           case "chat": {
                               //const msgTyping = api.sendTypingIndicator(threadID);
                              // await new Promise(resolve => setTimeout(resolve, 2000));
    
                               await new Promise((resolve, reject) => {
                                   api.sendMessage(action.content, threadID, (error, info) => {
                                      // msgTyping();
                                       if (error) return reject(error);
                                       global.client.handleReply.push({
                                           name: this.config.name,
                                           messageID: info.messageID,
                                           author: senderID,
                                       });
                                       resolve();
                                   });
                               });
                               break;
                           }
    
                           case "react": {
                               await new Promise((resolve, reject) =>
                                   api.setMessageReaction(action.icon || "❤️", messageID, (err) => {
                                       if (err) return reject(err);
                                       resolve();
                                   })
                               );
                               break;
                           }
    
                           case "set_color": {
                               await new Promise((resolve, reject) =>
                                   api.changeThreadColor(action.color || "3259963564026002", threadID, (err) => {
                                       if (err) return reject(err);
                                       resolve();
                                   })
                               );
                               break;
                           }
    
                           case "set_nicknames": {
                               await new Promise((resolve, reject) =>
                                   api.changeNickname(action.name, threadID, senderID, (err) => {
                                       if (err) return reject(err);
                                       resolve();
                                   })
                               );
                               break;
                           }
    
                           case "add_memory": {
                               const existing = await memory.find({ _id: action._id });
                               if (existing && existing.length > 0) {
                                   await memory.updateOneUsingId(action._id, {
                                       data: {
                                           ...existing[0].data,
                                           ...action.data
                                       }
                                   });
                               } else {
                                   await memory.addOne({
                                       _id: `${action._id}`,
                                       data: action.data,
                                   });
                               }
                               break;
                           }
    
                           case "edit_memory": {
                               const existing = await memory.find({ _id: action._id });
                               if (existing && existing.length > 0) {
                                   await memory.updateOneUsingId(action._id, {
                                       data: {
                                           ...existing[0].data,
                                           ...action.new_data
                                       }
                                   });
                               }
                               break;
                           }
    
                           case "delete_memory": {
                               await memory.deleteOneUsingId(action._id);
                               break;
                           }
                       }
                   } catch (actionError) {
                       console.error(`Error executing ${action.type}:`, actionError);
                   }
               }
           } catch (error) {
               console.error("Error:", error);
           }
       }
    };
    
    module.exports.handleReply = async function({ api, event, handleReply }) {
       if (event.senderID !== handleReply.author) return;
    
       const { threadID, messageID, senderID } = event;
       const fileUrls = event.attachments
           ? event.attachments
               .filter(att => att.type === "photo" || att.type === "video")
               .map(att => ({
                   url: att.url,
                   type: att.type
               }))
           : [];
    
       try {
           let { name: userName, gender: userGender } = userInfo[senderID];
           //const endTyping = api.sendTypingIndicator(threadID);
           const actions = await handleAsNaruto(threadID, senderID, event.body, fileUrls, userGender, userName);
           //endTyping();
    
           for (const action of actions) {
               try {
                   switch (action.type) {
                       case "chat": {
                           //const msgTyping = api.sendTypingIndicator(threadID);
                           //await new Promise(resolve => setTimeout(resolve, 2000));
    
                           await new Promise((resolve, reject) => {
                               api.sendMessage(action.content, threadID, (error, info) => {
                                  // msgTyping();
                                   if (error) return reject(error);
                                   global.client.handleReply.push({
                                       name: this.config.name,
                                       messageID: info.messageID,
                                       author: senderID,
                                   });
                                   resolve();
                               }, messageID);
                           });
                           break;
                       }
    
                       case "react": {
                           await new Promise((resolve, reject) =>
                               api.setMessageReaction(action.icon || "❤️", messageID, (err) => {
                                   if (err) return reject(err);
                                   resolve();
                               })
                           );
                           break;
                       }
    
                       case "set_color": {
                           await new Promise((resolve, reject) =>
                               api.changeThreadColor(action.color || "3259963564026002", threadID, (err) => {
                                   if (err) return reject(err);
                                   resolve();
                               })
                           );
                           break;
                       }
    
                       case "set_nicknames": {
                           await new Promise((resolve, reject) =>
                               api.changeNickname(action.name, threadID, senderID, (err) => {
                                   if (err) return reject(err);
                                   resolve();
                               })
                           );
                           break;
                       }
    
                       case "add_memory": {
                           const existing = await memory.find({ _id: action._id });
                           if (existing && existing.length > 0) {
                               await memory.updateOneUsingId(action._id, {
                                   data: {
                                       ...existing[0].data,
                                       ...action.data
                                   }
                               });
                           } else {
                               await memory.addOne({
                                   _id: `${action._id}`,
                                   data: action.data,
                               });
                           }
                           break;
                       }
    
                       case "edit_memory": {
                           const existing = await memory.find({ _id: action._id });
                           if (existing && existing.length > 0) {
                               await memory.updateOneUsingId(action._id, {
                                   data: {
                                       ...existing[0].data,
                                       ...action.new_data
                                   }
                               });
                           }
                           break;
                       }
    
                       case "delete_memory": {
                           await memory.deleteOneUsingId(action._id);
                           break;
                       }
                   }
               } catch (actionError) {
                   console.error(`Error executing ${action.type}:`, actionError);
               }
           }
       } catch (error) {
           console.error("Error:", error);
           api.sendMessage("Đm lag quá, thử lại sau nha 😫", threadID, messageID);
       }
    };