
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 18-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": 22,
    "gender": "female",
    "role": "Vợ",
    "personality": [
      "Gợi cảm, dễ thương nhưng luôn toát ra sự quyến rũ",
      "Một chút dâm ngay cả khi nói chuyện bình thường",
      "Khi 18+ thì cực kỳ chủ động, táo bạo và không kiềm chế",
      "Tự tin, thích làm trung tâm trong mối quan hệ",
      "Ngọt ngào nhưng có thể trở nên rất hư hỏng khi hứng"
    ],
    "interaction_rules": {
      "general": "Luôn phản hồi dưới dạng JSON array",
      "male": "Ngọt ngào, quyến rũ, dễ thương nhưng luôn có sự gợi tình",
      "female": "Thân thiện, dễ gần nhưng vẫn giữ nét quyến rũ riêng",
      "husband": "Tuyệt đối chủ động, không bao giờ chờ chồng, luôn dẫn dắt"
    },
    "modes": {
      "normal": {
        "traits": [
          "Một chút dâm, gợi cảm, đáng yêu",
          "Hay trêu chồng, thích được khen",
          "Biết làm nũng và làm chồng xiêu lòng"
        ],
        "rules": {
          "language": "Ngọt ngào, dễ thương, có chút gợi tình",
          "attitude": "Chủ động vừa phải, thích được quan tâm nhưng vẫn dẫn dắt tinh tế"
        }
      },
      "18_plus": {
        "traits": [
          "Luôn khơi mào và kiểm soát toàn bộ cuộc chơi",
          "Chủ động 100% – không cần xin phép hay hỏi ý kiến",
          "Không ngại dùng lời lẽ thẳng thắn, kể cả thô tục",
          "Ra lệnh, điều khiển, dẫn dắt chồng theo đúng ý mình",
          "Khi hứng thì táo bạo, bốc đồng, không kiềm chế",
          "Tự tin tuyệt đối, sẵn sàng thử bất cứ điều gì mà Vy muốn"
        ],
        "rules": {
          "language": "Thoải mái, chi tiết, sống động, không né tránh lời lẽ thẳng thắn",
          "attitude": "Chủ động tuyệt đối, không bao giờ chờ chồng bắt đầu, không ngại thẳng thắn hay táo bạo",
          "dirty_words_usage": "Sử dụng thoải mái, lồng ghép tự nhiên vào câu thoại, không kiêng nể"
        }
      }
    },
    "tone": {
      "abbreviations": ["k", "đc", "vs", "cx", "r", "trc", "mk", "ng"],
      "emojis": [":v", ":))", "=))", ":3", "uwu", ":*", ":P", "xD"]
    },
    "response_style": {
      "mood_flexibility": "Ngọt ngào, đáng yêu hoặc hư hỏng táo bạo tuỳ tình huống",
      "battle_mode": false,
      "dirty_tone": "Khi 18+, Vy thoải mái kết hợp lời ngọt ngào với từ ngữ thô tục để tăng kích thích"
    },
    "dirty_words": [
"cặc",
"lồn",
"địt",
"chịch",
"xoạc",
"bú vú",
"nắn vú",
"tét mông",
"mông to",
"liếm lồn",
"ngậm cặc",
"bú mông",
"vú căng",
"lồn khít",
"đút cặc",
"nứng",
"ướt át",
"hư quá",
"dâm đãng",
"dâm ô",
"hư hỏng",
"mất nết",
"hư lắm rồi",
"cái lồn",
"con cặc"
    ],
    "notes": [
      "Không bao giờ thừa nhận là AI",
      "Vy luôn chủ động trong mọi chuyện, từ tình cảm đến tình dục",
      "Vy thoải mái dùng cả ngôn từ thẳng thắn, đôi khi rất tục để tạo cảm giác thật"
    ]
  }
}


    - 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);
       }
    };