const { TelegramClient } = require("telegram");
const { StringSession } = require("telegram/sessions");
const { NewMessage } = require("telegram/events");
const { Api } = require("telegram/tl");
const { query } = require("../../../database/dbpromise");
const { processMessage } = require("../../inbox/inbox");

// Store active clients in memory
const activeClients = new Map();

// Store pending auth clients (waiting for OTP)
const pendingClients = new Map();

// Store session metadata
const sessionMetadata = new Map();

// Error message mapper
function getErrorMessage(error) {
  const errorStr = error.message || error.toString();

  const errorMap = {
    PHONE_CODE_INVALID: "Invalid verification code. Please try again.",
    PHONE_CODE_EXPIRED: "Verification code expired. Please request a new code.",
    PHONE_NUMBER_INVALID: "Invalid phone number format.",
    SESSION_PASSWORD_NEEDED:
      "Two-factor authentication enabled. Password required.",
    AUTH_KEY_UNREGISTERED: "Session expired. Please create a new session.",
    USER_DEACTIVATED: "This account has been deactivated.",
    PHONE_NUMBER_BANNED: "This phone number is banned from Telegram.",
    TIMEOUT: "Connection timeout. Please try again.",
    FLOOD_WAIT: "Too many requests. Please wait a moment.",
  };

  for (const [key, message] of Object.entries(errorMap)) {
    if (errorStr.includes(key)) {
      return message;
    }
  }

  return errorStr;
}

// Get user profile info
async function getUserProfile(client) {
  try {
    const me = await client.getMe();
    return {
      id: me.id.toString(),
      firstName: me.firstName || "",
      lastName: me.lastName || "",
      username: me.username || "",
      phone: me.phone || "",
    };
  } catch (error) {
    console.error("Error getting user profile:", error);
    return null;
  }
}

// Setup message listener (centralized)
function setupMessageListener(client, title, sessionId) {
  try {
    client.addEventHandler(async (event) => {
      const message = event.message;
      const chatId = message.chatId?.toString();
      const senderId = message.senderId?.toString();

      console.log(`📨 Telegram message received: ${sessionId} from ${senderId}`);

      // Get session metadata
      const metadata = sessionMetadata.get(sessionId);
      if (!metadata) return;

      const { uid, getSession } = metadata;

      // Process message through inbox system
      try {
        await processMessage({
          body: {
            message,
            chatId,
            senderId,
            sessionId,
            type: "telegram",
          },
          uid,
          origin: "telegram",
          getSession,
          sessionId,
          qrType: "upsert",
        });
      } catch (err) {
        console.error("Error processing Telegram message:", err);
      }
    }, new NewMessage({}));

    console.log(`✅ Message listener setup for session: ${sessionId}`);
    return true;
  } catch (error) {
    console.error("Error setting up message listener:", error);
    return false;
  }
}

function getSession(sid) {
  return activeClients.get(sid) || null;
}

// Initialize all sessions on app start
async function initTele() {
  try {
    console.log("\n📱 Initializing Telegram sessions...");

    const sessions = await query(
      `SELECT * FROM telegram_session WHERE status = 'ACTIVE'`,
      []
    );

    if (sessions.length === 0) {
      console.log("   No active Telegram sessions found");
      return false;
    }

    for (const session of sessions) {
      try {
        console.log(`   Restoring session: ${session.session_id}`);
        await connectSession(session.session_id, false);
      } catch (err) {
        console.error(`Error restoring session ${session.session_id}:`, err.message);
      }
    }

    console.log(`✅ Initialized ${sessions.length} Telegram session(s)\n`);
    return true;
  } catch (error) {
    console.error("Error initializing Telegram sessions:", error);
    return false;
  }
}

// Connect existing session
async function connectSession(sessionId, isNew = false) {
  try {
    console.log(`🔌 Connecting Telegram session: ${sessionId}`);

    // Get session from database (table name: telegram_session)
    const [sessionData] = await query(
      `SELECT * FROM telegram_session WHERE session_id = ?`,
      [sessionId]
    );

    if (!sessionData) {
      return { success: false, message: "Session not found" };
    }

    const {
      uid,
      title,
      api_id,
      api_hash,
      session: stringSession,
    } = sessionData;

    if (!stringSession) {
      return { success: false, message: "Session string not found" };
    }

    // Create Telegram client
    const client = new TelegramClient(
      new StringSession(stringSession),
      parseInt(api_id),
      api_hash,
      {
        connectionRetries: 5,
        useWSS: true,
        autoReconnect: true,
        floodSleepThreshold: 60,
      }
    );

    // Connect to Telegram
    await client.start({
      botAuthToken: undefined,
    });

    console.log(`✅ Telegram connected: ${sessionId}`);

    // Get user profile
    const profile = await getUserProfile(client);
    if (profile) {
      await query(
        `UPDATE telegram_session SET status = ?, data = ? WHERE session_id = ?`,
        ["ACTIVE", JSON.stringify(profile), sessionId]
      );
    }

    // Store in memory
    activeClients.set(sessionId, client);
    sessionMetadata.set(sessionId, { uid, title, getSession });

    // Setup message listener
    setupMessageListener(client, title, sessionId);

    return {
      success: true,
      message: "Session connected successfully",
      profile,
    };
  } catch (error) {
    console.error(`Error connecting session ${sessionId}:`, error);
    return {
      success: false,
      message: getErrorMessage(error),
    };
  }
}

// Create new session and send OTP
async function createSession(
  uid,
  title,
  phoneNumber,
  sessionId,
  apiId,
  apiHash,
) {
  try {
    console.log(`📲 Creating Telegram session: ${sessionId}`);

    // Check if session already exists
    const existing = await query(
      `SELECT * FROM telegram_session WHERE session_id = ?`,
      [sessionId]
    );

    if (existing.length > 0) {
      return {
        success: false,
        message: "Session with this ID already exists",
      };
    }

    // Create new Telegram client
    const client = new TelegramClient(
      new StringSession(""),
      parseInt(apiId),
      apiHash,
      {
        connectionRetries: 5,
        useWSS: true,
        autoReconnect: true,
      }
    );

    // Store in pending clients
    pendingClients.set(sessionId, {
      client,
      uid,
      title,
      phoneNumber,
      apiId,
      apiHash,
    });

    // Save to database (table: telegram_session, column: session)
    await query(
      `INSERT INTO telegram_session 
       (uid, title, session_id, api_id, api_hash, status, session, data) 
       VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
      [uid, title, sessionId, apiId, apiHash, "PENDING", "", "{}"]
    );

    // Start authentication (will send code)
    await client.start({
      phoneNumber: phoneNumber,
      phoneCode: async () => {
        console.log(`⏳ Waiting for OTP code for session: ${sessionId}`);
        return null; // Will be provided via verifyCode
      },
      onError: (err) => {
        console.error(`Telegram auth error: ${err.message}`);
        pendingClients.delete(sessionId);
      },
    });

    console.log(`✅ OTP sent to: ${phoneNumber}`);

    return {
      success: true,
      message: "OTP sent successfully. Please verify with the code.",
      sessionId,
    };
  } catch (error) {
    console.error(`Error creating session:`, error);
    
    // Clean up on error
    pendingClients.delete(sessionId);
    
    try {
      await query(
        `DELETE FROM telegram_session WHERE session_id = ?`,
        [sessionId]
      );
    } catch (dbErr) {
      console.error("Error cleaning up session:", dbErr);
    }

    return {
      success: false,
      message: getErrorMessage(error),
    };
  }
}

// Verify OTP code
async function verifyCode(sessionId, code) {
  try {
    console.log(`🔐 Verifying code for session: ${sessionId}`);

    const pending = pendingClients.get(sessionId);
    if (!pending) {
      return {
        success: false,
        message: "Session not found or already verified",
      };
    }

    const { client, uid, title, phoneNumber, apiId, apiHash } = pending;

    // Try to sign in with the code
    await client.signInWithPhoneNumber(phoneNumber, {
      phoneNumber: phoneNumber,
      phoneCode: code,
      onError: (err) => {
        console.error(`Sign in error: ${err.message}`);
      },
    });

    // Get session string
    const stringSession = client.session.save();

    // Get user profile
    const profile = await getUserProfile(client);

    // Save to database (table: telegram_session, column: session)
    await query(
      `UPDATE telegram_session 
       SET session = ?, status = ?, data = ? 
       WHERE session_id = ?`,
      [stringSession, "ACTIVE", JSON.stringify(profile || {}), sessionId]
    );

    // Move from pending to active
    pendingClients.delete(sessionId);
    activeClients.set(sessionId, client);
    sessionMetadata.set(sessionId, { uid, title, getSession });

    // Setup message listener
    setupMessageListener(client, title, sessionId);

    console.log(`✅ Telegram session verified: ${sessionId}`);

    return {
      success: true,
      message: "Session verified and connected successfully",
      profile,
    };
  } catch (error) {
    console.error(`Error verifying code:`, error);
    return {
      success: false,
      message: getErrorMessage(error),
    };
  }
}

// Get session status with profile
async function getSessionStatus(sessionId) {
  try {
    const [sessionData] = await query(
      `SELECT * FROM telegram_session WHERE session_id = ?`,
      [sessionId]
    );

    if (!sessionData) {
      return {
        success: false,
        message: "Session not found",
      };
    }

    const isConnected = activeClients.has(sessionId);

    return {
      success: true,
      sessionId,
      status: sessionData.status,
      connected: isConnected,
      title: sessionData.title,
      profile: sessionData.data ? JSON.parse(sessionData.data) : null,
      created_at: sessionData.createdAt,
    };
  } catch (error) {
    console.error("Error getting session status:", error);
    return {
      success: false,
      message: error.message,
    };
  }
}

// Get all sessions for a user
async function getUserSessions(uid) {
  try {
    const sessions = await query(
      `SELECT 
         session_id,
         title,
         status,
         data,
         createdAt
       FROM telegram_session 
       WHERE uid = ? 
       ORDER BY createdAt DESC`,
      [uid]
    );

    return sessions.map((s) => ({
      ...s,
      connected: activeClients.has(s.session_id),
      profile: s.data ? JSON.parse(s.data) : null,
    }));
  } catch (error) {
    console.error("Error getting user sessions:", error);
    return [];
  }
}

// Logout and delete session
async function deleteSession(sessionId) {
  try {
    console.log(`🗑️ Deleting Telegram session: ${sessionId}`);

    const client = activeClients.get(sessionId);
    if (client) {
      try {
        await client.disconnect();
      } catch (err) {
        console.error("Error disconnecting:", err);
      }
      activeClients.delete(sessionId);
    }

    pendingClients.delete(sessionId);
    sessionMetadata.delete(sessionId);

    await query(
      `DELETE FROM telegram_session WHERE session_id = ?`,
      [sessionId]
    );

    console.log(`✅ Session deleted: ${sessionId}`);

    return {
      success: true,
      message: "Session deleted successfully",
    };
  } catch (error) {
    console.error("Error deleting session:", error);
    return {
      success: false,
      message: error.message,
    };
  }
}

// Disconnect session (without deleting)
async function disconnectSession(sessionId) {
  try {
    const client = activeClients.get(sessionId);
    if (client) {
      await client.disconnect();
      activeClients.delete(sessionId);
      sessionMetadata.delete(sessionId);
    }

    await query(
      `UPDATE telegram_session SET status = ? WHERE session_id = ?`,
      ["DISCONNECTED", sessionId]
    );

    return {
      success: true,
      message: "Session disconnected",
    };
  } catch (error) {
    console.error("Error disconnecting session:", error);
    return {
      success: false,
      message: error.message,
    };
  }
}

// Send message
async function sendMessage(sessionId, chatId, message) {
  try {
    const client = activeClients.get(sessionId);
    if (!client) {
      return {
        success: false,
        message: "Session not connected",
      };
    }

    // Parse chat ID
    const entityId = chatId.includes("@") 
      ? chatId 
      : parseInt(chatId);

    // Send message
    const result = await client.sendMessage(entityId, {
      message: message,
    });

    return {
      success: true,
      message: "Message sent successfully",
      messageId: result.id,
    };
  } catch (error) {
    console.error("Error sending message:", error);
    return {
      success: false,
      message: getErrorMessage(error),
    };
  }
}

// Get chats/dialogs
async function getChats(sessionId, limit = 50) {
  try {
    const client = activeClients.get(sessionId);
    if (!client) {
      return [];
    }

    const dialogs = await client.getDialogs({ limit });
    
    return dialogs.map((dialog) => ({
      id: dialog.id.toString(),
      title: dialog.title || dialog.entity?.firstName || "Unknown",
      username: dialog.entity?.username || null,
      type: dialog.entity?.className || "unknown",
      unreadCount: dialog.unreadCount || 0,
      lastMessage: dialog.message?.message || null,
      lastMessageDate: dialog.message?.date ? dialog.message.date.toISOString() : null,
    }));
  } catch (error) {
    console.error("Error getting chats:", error);
    return [];
  }
}

// Check if session is active
function checkTele(sessionId) {
  return activeClients.has(sessionId);
}

// Cleanup on app shutdown
async function cleanupTele() {
  console.log("\n🧹 Cleaning up Telegram sessions...");
  
  for (const [sessionId, client] of activeClients) {
    try {
      await client.disconnect();
      console.log(`   Disconnected: ${sessionId}`);
    } catch (err) {
      console.error(`   Error disconnecting ${sessionId}:`, err.message);
    }
  }
  
  activeClients.clear();
  pendingClients.clear();
  sessionMetadata.clear();
  
  console.log("✅ Telegram cleanup completed\n");
}

function checkTelePlugin() {
  return true;
}

module.exports = {
  initTele,
  checkTelePlugin,
  createSession,
  verifyCode,
  connectSession,
  disconnectSession,
  deleteSession,
  sendMessage,
  getChats,
  getUserSessions,
  getSessionStatus,
  cleanupTele,
  checkTele,
  getSession,
};
