import { Response, Request } from 'express';
import { AuthenticatedRequest } from '../middlewares/auth';
import { prisma } from '../index';
import { createError, asyncHandler } from '../middlewares/errorHandler';
import { BotAccessService } from '../services/botAccessService';
import { elevenLabsService } from '../services/elevenLabsService';
import {
  createBotWithFileSchema,
  updateBotSchema,
  paginationSchema,
  uuidParamSchema,
  CreateBotWithFileInput,
  UpdateBotInput,
  PaginationInput,
  UuidParamInput,
} from '../utils/validation';
import { getImagePath, getFullImagePath } from '../middlewares/upload';
import fs from 'fs';
import logger from '../utils/logger';

// Get all bots with pagination and filtering
export const getAllBots = asyncHandler(async (req: AuthenticatedRequest, res: Response) => {
  const startTime = Date.now();
  
  logger.info('🔍 getAllBots called', {
    userId: req.user?.id,
    userRole: req.user?.role,
    query: req.query,
    userAgent: req.get('User-Agent'),
    origin: req.get('Origin'),
    ip: req.ip
  });
  
  // Validate query parameters
  const paginationData: PaginationInput = paginationSchema.parse(req.query);
  
  const { page, limit } = paginationData;
  const skip = (page - 1) * limit;
  
  logger.info('📊 Pagination parameters', { 
    page, 
    limit, 
    skip,
    userId: req.user?.id 
  });
  
  // Get bots with pagination
  logger.info('🗄️ Querying database for bots', {
    skip,
    take: limit,
    userId: req.user?.id,
    userRole: req.user?.role
  });
  
  // Build where clause based on user role
  logger.info('🔍 User info for filtering', {
    hasUser: !!req.user,
    userRole: req.user?.role,
    userId: req.user?.id,
    isTeacher: req.user?.role === 'TEACHER'
  });
  
  let whereClause: any = {};
  
  // Teachers and admins can see all bots (no filtering by creator)
  if (req.user?.role === 'TEACHER' || req.user?.role === 'ADMIN') {
    // No filtering - show all bots regardless of creator
    whereClause = {};
    logger.info('🔍 Teacher/Admin access - showing all bots', {
      userRole: req.user.role,
      userId: req.user.id
    });
  }
  
  logger.info('🔍 Bot query filter', {
    whereClause,
    userRole: req.user?.role,
    userId: req.user?.id
  });
  
  const [bots, totalCount] = await Promise.all([
    prisma.bot.findMany({
      where: whereClause,
      select: {
        id: true,
        name: true,
        topic: true,
        level: true,
        imageUrl: true,
        agentId: true,
        description: true,
        feedback: true,
        isActive: true,
        isTimerEnabled: true,
        maxUsageSeconds: true,
        createdAt: true,
        updatedAt: true,
        createdBy: true,
        creator: {
          select: {
            id: true,
            name: true,
            email: true,
          },
        },
        _count: {
          select: {
            accesses: true, // Count of student assignments
          },
        },
      },
      skip,
      take: limit,
      orderBy: { createdAt: 'desc' },
    }),
    prisma.bot.count({ where: whereClause }),
  ]);
  
  const totalPages = Math.ceil(totalCount / limit);
  
  logger.info('🤖 Bots retrieved from database', {
    count: bots.length,
    totalCount,
    page,
    limit,
    totalPages,
    botNames: bots.map(bot => bot.name),
    botIds: bots.map(bot => bot.id),
    userId: req.user?.id
  });
  
  const response = {
    success: true,
    data: {
      bots,
      pagination: {
        page,
        limit,
        totalCount,
        totalPages,
        hasNext: page < totalPages,
        hasPrev: page > 1,
      },
    },
  };
  
  const responseTime = Date.now() - startTime;
  
  logger.info('📤 Sending response', {
    responseBotCount: response.data.bots.length,
    responseBotNames: response.data.bots.map((bot: any) => bot.name),
    responseTime: `${responseTime}ms`,
    userId: req.user?.id
  });
  
  res.json(response);
});

// Get bot by ID
export const getBotById = asyncHandler(async (req: AuthenticatedRequest, res: Response) => {
  const startTime = Date.now();
  const { id }: UuidParamInput = uuidParamSchema.parse(req.params);
  
  logger.info('🔍 getBotById called', {
    botId: id,
    userId: req.user?.id,
    userRole: req.user?.role,
    ip: req.ip,
    userAgent: req.get('User-Agent')
  });

  logger.info('🗄️ Querying database for bot', {
    botId: id,
    userId: req.user?.id
  });
  
  const bot = await prisma.bot.findUnique({
    where: { id },
    select: {
      id: true,
      name: true,
      topic: true,
      level: true,
      imageUrl: true,
      agentId: true,
      description: true,
      feedback: true,
      isActive: true,
      isTimerEnabled: true,
      maxUsageSeconds: true,
      createdAt: true,
      updatedAt: true,
      // Include students with access
      accesses: {
        select: {
          student: {
            select: {
              id: true,
              name: true,
              email: true,
            },
          },
          grantedAt: true,
          granter: {
            select: {
              id: true,
              name: true,
              email: true,
            },
          },
        },
      },
      // Include recent conversations
      conversations: {
        select: {
          id: true,
          student: {
            select: {
              id: true,
              name: true,
              email: true,
            },
          },
          startedAt: true,
          endedAt: true,
          durationSeconds: true,
        },
        orderBy: { startedAt: 'desc' },
        take: 10, // Limit to recent conversations
      },
    },
  });
  
  if (!bot) {
    logger.warn('❌ Bot not found', {
      botId: id,
      userId: req.user?.id,
      ip: req.ip
    });
    throw createError('Bot not found', 404);
  }
  
  // Calculate durations from sessions for recent conversations
  if (bot.conversations && bot.conversations.length > 0) {
    const { ConversationService } = await import('../services/conversationService');
    const conversationIds = bot.conversations.map(c => c.id);
    const durationMap = await ConversationService.calculateDurationsForConversations(conversationIds);
    
    // Update durationSeconds for each conversation
    bot.conversations = bot.conversations.map(conv => ({
      ...conv,
      durationSeconds: durationMap.get(conv.id) || 0
    }));
  }
  
  const responseTime = Date.now() - startTime;
  
  logger.info('✅ Bot retrieved successfully', { 
    botId: id,
    botName: bot.name,
    topic: bot.topic,
    level: bot.level,
    isActive: bot.isActive,
    accessCount: bot.accesses.length,
    conversationCount: bot.conversations.length,
    responseTime: `${responseTime}ms`,
    userId: req.user?.id
  });
  
  res.json({
    success: true,
    data: { bot },
  });
});

// Create new bot (admin/teacher)
export const createBot = asyncHandler(async (req: AuthenticatedRequest, res: Response) => {
  const startTime = Date.now();
  
  logger.info('🤖 createBot called', {
    userId: req.user?.id,
    userRole: req.user?.role,
    requestBody: req.body,
    hasFile: !!req.file,
    ip: req.ip,
    userAgent: req.get('User-Agent')
  });

  // Handle file upload if present
  let imageUrl: string | null = '/assets/default-bot-image.svg'; // Default system image
  
  logger.info('🔍 File upload debug', {
    hasFile: !!req.file,
    fileField: req.file?.fieldname,
    fileName: req.file?.originalname,
    fileSize: req.file?.size,
    fileMimetype: req.file?.mimetype,
    bodyKeys: Object.keys(req.body || {}),
    contentType: req.get('Content-Type'),
    userId: req.user?.id
  });
  
  // Check if there's a file in the request body (for simple upload)
  const hasImageInBody = req.body && req.body.image;
  
  if (req.file) {
    imageUrl = getImagePath(req.file.filename);
    logger.info('📁 File uploaded successfully', {
      originalName: req.file.originalname,
      filename: req.file.filename,
      path: imageUrl,
      fullPath: getFullImagePath(req.file.filename),
      fileExists: fs.existsSync(getFullImagePath(req.file.filename)),
      userId: req.user?.id
    });
  } else if (hasImageInBody) {
    logger.info('📁 File detected in body but not processed by middleware', {
      bodyKeys: Object.keys(req.body),
      userId: req.user?.id
    });
    // For now, don't assign any image since file processing is not working
    logger.warn('⚠️ File upload middleware not working - no image will be assigned', {
      userId: req.user?.id
    });
  } else {
    logger.info('📁 No image provided - bot will be created without image', {
      userId: req.user?.id
    });
  }

  // Normalize timer fields before validation (support 0 = infinite)
  const rawCreateBody: any = { ...(req.body || {}) };
  const parsedCreateMs = rawCreateBody.maxUsageSeconds !== undefined ? Number(rawCreateBody.maxUsageSeconds) : undefined;
  if (parsedCreateMs !== undefined && !Number.isNaN(parsedCreateMs)) {
    rawCreateBody.maxUsageSeconds = parsedCreateMs;
    if (parsedCreateMs === 0) {
      rawCreateBody.isTimerEnabled = false;
    }
  }

  // Validate form data (without imageUrl since it's handled separately)
  const validatedData: CreateBotWithFileInput = createBotWithFileSchema.parse(rawCreateBody);
  const { name, topic, level, agentId, description, feedback, maxUsageSeconds, isTimerEnabled } = validatedData;
  
  logger.info('✅ Bot creation data validated', {
    name,
    topic,
    level,
    agentId,
    descriptionLength: description.length,
    feedbackLength: feedback?.length || 0,
    hasImageUrl: !!imageUrl,
    maxUsageSeconds,
    isTimerEnabled,
    userId: req.user?.id
  });
  
  // Check if bot with same name already exists
  logger.info('🔍 Checking for existing bot with same name', { name, userId: req.user?.id });
  
  const existingBot = await prisma.bot.findFirst({
    where: { name },
  });
  
  if (existingBot) {
    logger.warn('❌ Bot creation failed - name already exists', {
      name,
      existingBotId: existingBot.id,
      userId: req.user?.id,
      ip: req.ip
    });
    throw createError('Bot with this name already exists', 409);
  }
  
  logger.info('✅ Bot name is unique', { name, userId: req.user?.id });
  
  // Check if agent ID already exists in database (but don't block creation)
  logger.info('🔍 Checking for existing bot with same agent ID', { agentId, userId: req.user?.id });
  
  const existingAgentBot = await prisma.bot.findFirst({
    where: { agentId },
  });
  
  if (existingAgentBot) {
    logger.warn('⚠️ Agent ID already exists in database', {
      agentId,
      existingBotId: existingAgentBot.id,
      existingBotName: existingAgentBot.name,
      userId: req.user?.id
    });
    // Don't throw error, just log a warning - user can still create the bot
  }
  
  logger.info('✅ Agent ID check completed', { agentId, userId: req.user?.id });
  
  // Validate agent ID with ElevenLabs
  logger.info('🔗 Validating agent ID', { agentId, userId: req.user?.id });
  
  const isValidAgent = await elevenLabsService.validateAgentId(agentId);
  if (!isValidAgent) {
    logger.warn('❌ Bot creation failed - invalid agent ID', {
      agentId,
      userId: req.user?.id,
      ip: req.ip
    });
    throw createError('Invalid agent ID or agent not accessible', 400);
  }
  
  logger.info('✅ Agent ID validated', { agentId, userId: req.user?.id });
  
  // Create bot
  logger.info('📝 Creating bot in database', {
    name,
    topic,
    level,
    agentId,
    userId: req.user?.id
  });
  
  const bot = await prisma.bot.create({
    data: {
      name,
      topic,
      level,
      imageUrl,
      agentId,
      description,
      feedback,
      isActive: true,
      maxUsageSeconds: typeof maxUsageSeconds === 'number' ? (maxUsageSeconds === 0 ? null : maxUsageSeconds) : null,
      isTimerEnabled: !!isTimerEnabled && maxUsageSeconds !== 0,
      createdBy: req.user?.id,
    },
    select: {
      id: true,
      name: true,
      topic: true,
      level: true,
      imageUrl: true,
      agentId: true,
      description: true,
      feedback: true,
      isActive: true,
      maxUsageSeconds: true,
      isTimerEnabled: true,
      createdAt: true,
      updatedAt: true,
    },
  });
  
  const responseTime = Date.now() - startTime;
  
  logger.info('🎉 Bot created successfully', {
    botId: bot.id,
    name: bot.name,
    topic: bot.topic,
    level: bot.level,
    agentId: bot.agentId,
    responseTime: `${responseTime}ms`,
    createdBy: req.user?.id,
    ip: req.ip
  });
  
  res.status(201).json({
    success: true,
    message: 'Bot created successfully',
    data: { bot },
  });
});

// Update bot (admin/teacher)
export const updateBot = asyncHandler(async (req: AuthenticatedRequest, res: Response) => {
  const startTime = Date.now();
  const { id }: UuidParamInput = uuidParamSchema.parse(req.params);
  
  logger.info('✏️ updateBot called', {
    botId: id,
    userId: req.user?.id,
    userRole: req.user?.role,
    requestBody: req.body,
    ip: req.ip,
    userAgent: req.get('User-Agent')
  });

  logger.info('🔍 Raw request body:', {
    body: req.body,
    bodyType: typeof req.body,
    bodyKeys: Object.keys(req.body || {}),
    timerFields: {
      isTimerEnabled: req.body?.isTimerEnabled,
      maxUsageSeconds: req.body?.maxUsageSeconds,
      maxUsageSecondsType: typeof req.body?.maxUsageSeconds
    }
  });

  // Normalize timer fields before validation (support 0 = infinite)
  const rawUpdateBody: any = { ...(req.body || {}) };
  const parsedUpdateMs = rawUpdateBody.maxUsageSeconds !== undefined ? Number(rawUpdateBody.maxUsageSeconds) : undefined;
  if (parsedUpdateMs !== undefined && !Number.isNaN(parsedUpdateMs)) {
    rawUpdateBody.maxUsageSeconds = parsedUpdateMs;
    if (parsedUpdateMs === 0) {
      rawUpdateBody.isTimerEnabled = false;
    }
  }

  const validatedData: UpdateBotInput = updateBotSchema.parse(rawUpdateBody);
  const { name, topic, level, imageUrl, agentId, description, feedback, isActive, isTimerEnabled, maxUsageSeconds } = validatedData;

  // If multer stored a file, prefer that as the new image
  let finalImageUrl = imageUrl;
  if ((req as any).file?.filename) {
    const filename = (req as any).file.filename as string;
    finalImageUrl = getImagePath(filename);
    logger.info('🖼️ Using uploaded image for update', { botId: id, filename, finalImageUrl });
  }
  
  logger.info('✅ Bot update data validated', {
    botId: id,
    updateFields: Object.keys(validatedData),
    validatedData,
    userId: req.user?.id
  });

  // Check if bot exists
  logger.info('🔍 Checking if bot exists', { botId: id, userId: req.user?.id });
  
  const existingBot = await prisma.bot.findUnique({
    where: { id },
  });

  if (!existingBot) {
    logger.warn('❌ Bot update failed - bot not found', {
      botId: id,
      userId: req.user?.id,
      ip: req.ip
    });
    throw createError('Bot not found', 404);
  }

  logger.info('✅ Bot found', {
    botId: id,
    botName: existingBot.name,
    userId: req.user?.id
  });

  // Check for name conflicts if name is being updated
  if (name && name !== existingBot.name) {
    logger.info('🔍 Checking for name conflicts', { 
      newName: name, 
      oldName: existingBot.name,
      userId: req.user?.id 
    });
    
    const nameConflict = await prisma.bot.findFirst({
      where: { 
        name,
        NOT: { id }
      },
    });

    if (nameConflict) {
      logger.warn('❌ Bot update failed - name conflict', {
        botId: id,
        newName: name,
        conflictingBotId: nameConflict.id,
        userId: req.user?.id,
        ip: req.ip
      });
      throw createError('Bot with this name already exists', 409);
    }
  }

  // Check for agent ID conflicts if agent ID is being updated (warn only, do not block)
  if (agentId && agentId !== existingBot.agentId) {
    logger.info('🔍 Checking for agent ID conflicts', { 
      newAgentId: agentId, 
      oldAgentId: existingBot.agentId,
      userId: req.user?.id 
    });
    
    const agentIdConflict = await prisma.bot.findFirst({
      where: { 
        agentId,
        NOT: { id }
      },
    });

    if (agentIdConflict) {
      // Only warn; allow duplicate agent IDs
      logger.warn('⚠️ Agent ID already in use by another bot, proceeding by request', {
        botId: id,
        newAgentId: agentId,
        conflictingBotId: agentIdConflict.id,
        conflictingBotName: agentIdConflict.name,
        userId: req.user?.id,
        ip: req.ip
      });
    }

    // Validate new agent ID with ElevenLabs
    logger.info('🔗 Validating new agent ID with ElevenLabs', { 
      agentId, 
      userId: req.user?.id 
    });
    
    const isValidAgent = await elevenLabsService.validateAgentId(agentId);
    if (!isValidAgent) {
      logger.warn('❌ Bot update failed - invalid agent ID', {
        botId: id,
        agentId,
        userId: req.user?.id,
        ip: req.ip
      });
      throw createError('Invalid agent ID or agent not accessible', 400);
    }
    
    logger.info('✅ New agent ID validated with ElevenLabs', { agentId, userId: req.user?.id });
  }

  // Update bot
  logger.info('📝 Updating bot in database', {
    botId: id,
    updateFields: Object.keys(validatedData),
    timerFields: {
      isTimerEnabled: validatedData.isTimerEnabled,
      maxUsageSeconds: validatedData.maxUsageSeconds
    },
    userId: req.user?.id
  });
  
  const bot = await prisma.bot.update({
    where: { id },
    data: {
      name,
      topic,
      level,
      imageUrl: finalImageUrl,
      agentId,
      description,
      feedback,
      isActive,
      isTimerEnabled: typeof validatedData.isTimerEnabled === 'boolean'
        ? (validatedData.isTimerEnabled && (validatedData.maxUsageSeconds ?? existingBot.maxUsageSeconds ?? 0) !== 0)
        : existingBot.isTimerEnabled,
      maxUsageSeconds: typeof validatedData.maxUsageSeconds === 'number'
        ? (validatedData.maxUsageSeconds === 0 ? null : validatedData.maxUsageSeconds)
        : existingBot.maxUsageSeconds,
    },
    select: {
      id: true,
      name: true,
      topic: true,
      level: true,
      imageUrl: true,
      agentId: true,
      description: true,
      feedback: true,
      isActive: true,
      isTimerEnabled: true,
      maxUsageSeconds: true,
      createdAt: true,
      updatedAt: true,
    },
  });

  const responseTime = Date.now() - startTime;
  
  logger.info('🎉 Bot updated successfully', {
    botId: bot.id,
    name: bot.name,
    topic: bot.topic,
    level: bot.level,
    agentId: bot.agentId,
    isActive: bot.isActive,
    responseTime: `${responseTime}ms`,
    updatedBy: req.user?.id,
    ip: req.ip
  });

  res.json({
    success: true,
    message: 'Bot updated successfully',
    data: { bot },
  });
});

// Delete bot (admin only)
export const deleteBot = asyncHandler(async (req: AuthenticatedRequest, res: Response) => {
  const startTime = Date.now();
  const { id }: UuidParamInput = uuidParamSchema.parse(req.params);
  
  logger.info('🗑️ deleteBot called', {
    botId: id,
    userId: req.user?.id,
    userRole: req.user?.role,
    ip: req.ip,
    userAgent: req.get('User-Agent')
  });

  // Check if bot exists
  logger.info('🔍 Checking if bot exists', { botId: id, userId: req.user?.id });
  
  const existingBot = await prisma.bot.findUnique({
    where: { id },
    include: {
      _count: {
        select: {
          accesses: true,
          conversations: true,
        },
      },
    },
  });

  if (!existingBot) {
    logger.warn('❌ Bot deletion failed - bot not found', {
      botId: id,
      userId: req.user?.id,
      ip: req.ip
    });
    throw createError('Bot not found', 404);
  }

  logger.info('✅ Bot found for deletion', {
    botId: id,
    botName: existingBot.name,
    accessCount: existingBot._count.accesses,
    conversationCount: existingBot._count.conversations,
    userId: req.user?.id
  });

  // Log dependencies that will be deleted in cascade
  if (existingBot._count.accesses > 0) {
    logger.info('⚠️ Bot has active assignments that will be deleted in cascade', {
      botId: id,
      botName: existingBot.name,
      accessCount: existingBot._count.accesses,
      userId: req.user?.id
    });
  }

  if (existingBot._count.conversations > 0) {
    logger.info('⚠️ Bot has conversations that will be deleted in cascade', {
      botId: id,
      botName: existingBot.name,
      conversationCount: existingBot._count.conversations,
      userId: req.user?.id
    });
  }

  // Delete bot
  logger.info('🗑️ Deleting bot from database', {
    botId: id,
    botName: existingBot.name,
    userId: req.user?.id
  });
  
  await prisma.bot.delete({
    where: { id },
  });

  const responseTime = Date.now() - startTime;
  
  logger.info('🎉 Bot deleted successfully', {
    botId: id,
    botName: existingBot.name,
    topic: existingBot.topic,
    level: existingBot.level,
    agentId: existingBot.agentId,
    responseTime: `${responseTime}ms`,
    deletedBy: req.user?.id,
    ip: req.ip
  });

  // Prepare response message based on what was deleted
  let message = 'Bot deleted successfully';
  if (existingBot._count.accesses > 0 || existingBot._count.conversations > 0) {
    const deletedItems = [];
    if (existingBot._count.accesses > 0) {
      deletedItems.push(`${existingBot._count.accesses} assignment(s)`);
    }
    if (existingBot._count.conversations > 0) {
      deletedItems.push(`${existingBot._count.conversations} conversation(s)`);
    }
    message = `Bot deleted successfully. Also deleted: ${deletedItems.join(', ')}.`;
  }

  res.json({
    success: true,
    message,
  });
});

// Get user's accessible bots
export const getUserBots = asyncHandler(async (req: AuthenticatedRequest, res: Response) => {
  const startTime = Date.now();
  
  logger.info('🔍 getUserBots called', {
    userId: req.user?.id,
    userRole: req.user?.role,
    ip: req.ip,
    userAgent: req.get('User-Agent')
  });

  if (!req.user) {
    logger.warn('❌ getUserBots failed - no authenticated user', {
      ip: req.ip,
      userAgent: req.get('User-Agent')
    });
    throw createError('Authentication required', 401);
  }

  logger.info('🔍 Getting accessible bots for user', {
    userId: req.user.id,
    userRole: req.user.role
  });
  
  const bots = await BotAccessService.getUserAccessibleBots(req.user.id, req.user.role);

  const responseTime = Date.now() - startTime;
  
  logger.info('✅ User accessible bots retrieved', {
    userId: req.user.id,
    userRole: req.user.role,
    botCount: bots.length,
    botNames: bots.map(bot => bot.name),
    responseTime: `${responseTime}ms`,
    ip: req.ip
  });

  res.json({
    success: true,
    data: { bots },
  });
});

// Get bot by name with access check (authenticated users)
export const getBotByName = asyncHandler(async (req: AuthenticatedRequest, res: Response) => {
  const startTime = Date.now();
  const { botName } = req.params;
  
  logger.info('🔍 getBotByName called', {
    botName,
    userId: req.user?.id,
    userRole: req.user?.role,
    ip: req.ip,
    userAgent: req.get('User-Agent')
  });

  if (!req.user) {
    logger.warn('❌ getBotByName failed - no authenticated user', {
      botName,
      ip: req.ip,
      userAgent: req.get('User-Agent')
    });
    throw createError('Authentication required', 401);
  }

  logger.info('🔍 Getting bot by name with access check', {
    botName,
    userId: req.user.id,
    userRole: req.user.role
  });
  
  const bot = await BotAccessService.getBotByNameWithAccess(req.user.id, botName, req.user.role);

  if (!bot) {
    logger.warn('❌ Bot not found or access denied', {
      botName,
      userId: req.user.id,
      userRole: req.user.role,
      ip: req.ip
    });
    throw createError('Bot not found or access denied', 404);
  }

  const responseTime = Date.now() - startTime;
  
  logger.info('✅ Bot retrieved by name', {
    botName,
    botId: bot.id,
    topic: bot.topic,
    level: bot.level,
    hasAccess: bot.hasAccess,
    userId: req.user.id,
    userRole: req.user.role,
    responseTime: `${responseTime}ms`,
    ip: req.ip
  });

  res.json({
    success: true,
    data: { bot },
  });
});

// Get bot by name (public endpoint for chat)
export const getBotByNamePublic = asyncHandler(async (req: Request, res: Response) => {
  const startTime = Date.now();
  const { botName } = req.params;
  
  logger.info('🔍 getBotByNamePublic called', {
    botName,
    ip: req.ip,
    userAgent: req.get('User-Agent')
  });

  logger.info('🔍 Getting bot by name (public)', {
    botName
  });
  
  const bot = await prisma.bot.findFirst({
    where: { 
      name: botName,
      isActive: true
    }
  });

  if (!bot) {
    logger.warn('❌ Bot not found', {
      botName,
      ip: req.ip
    });
    throw createError('Bot not found', 404);
  }

  const responseTime = Date.now() - startTime;
  
  logger.info('✅ Bot retrieved by name (public)', {
    botName,
    botId: bot.id,
    topic: bot.topic,
    level: bot.level,
    responseTime: `${responseTime}ms`,
    ip: req.ip
  });

  res.json({
    success: true,
    data: { bot },
  });
});

// Get all used agent IDs (for frontend validation)
export const getUsedAgentIds = asyncHandler(async (req: AuthenticatedRequest, res: Response) => {
  const startTime = Date.now();
  
  logger.info('🔍 getUsedAgentIds called', {
    userId: req.user?.id,
    userRole: req.user?.role,
    ip: req.ip
  });

  const bots = await prisma.bot.findMany({
    select: {
      id: true,
      agentId: true,
      name: true,
    },
    orderBy: { name: 'asc' },
  });

  const usedAgentIds = bots.map(bot => ({
    botId: bot.id,
    agentId: bot.agentId,
    botName: bot.name,
  }));

  const responseTime = Date.now() - startTime;
  
  logger.info('✅ Used agent IDs retrieved', {
    count: usedAgentIds.length,
    responseTime: `${responseTime}ms`,
    userId: req.user?.id
  });

  res.json({
    success: true,
    data: { usedAgentIds },
  });
});

// Toggle bot activation with connection validation
export const toggleBotActivation = asyncHandler(async (req: AuthenticatedRequest, res: Response) => {
  const startTime = Date.now();
  const { id }: UuidParamInput = uuidParamSchema.parse(req.params);
  
  logger.info('🔄 toggleBotActivation called', {
    botId: id,
    userId: req.user?.id,
    userRole: req.user?.role,
    ip: req.ip,
    userAgent: req.get('User-Agent')
  });

  // Check if bot exists
  logger.info('🔍 Checking if bot exists', { botId: id, userId: req.user?.id });
  
  const existingBot = await prisma.bot.findUnique({
    where: { id },
    select: {
      id: true,
      name: true,
      agentId: true,
      isActive: true,
    },
  });

  if (!existingBot) {
    logger.warn('❌ Bot activation failed - bot not found', {
      botId: id,
      userId: req.user?.id,
      ip: req.ip
    });
    throw createError('Bot not found', 404);
  }

  logger.info('✅ Bot found', {
    botId: id,
    botName: existingBot.name,
    currentStatus: existingBot.isActive ? 'active' : 'inactive',
    userId: req.user?.id
  });

  // If trying to activate the bot, validate connection first
  if (!existingBot.isActive) {
    logger.info('🔗 Bot is inactive - validating connection before activation', {
      botId: id,
      botName: existingBot.name,
      agentId: existingBot.agentId,
      userId: req.user?.id
    });

    if (!existingBot.agentId) {
      logger.warn('❌ Bot activation failed - no agent ID configured', {
        botId: id,
        botName: existingBot.name,
        userId: req.user?.id
      });
      throw createError('Bot does not have an Agent ID configured', 400);
    }

    // Validate agent ID with ElevenLabs
    logger.info('🔗 Validating agent ID with ElevenLabs', { 
      botId: id,
      agentId: existingBot.agentId, 
      userId: req.user?.id 
    });
    
    const isValidAgent = await elevenLabsService.validateAgentId(existingBot.agentId);
    if (!isValidAgent) {
      logger.warn('❌ Bot activation failed - invalid agent ID or connection error', {
        botId: id,
        botName: existingBot.name,
        agentId: existingBot.agentId,
        userId: req.user?.id,
        ip: req.ip
      });
      throw createError('Cannot activate bot: Connection error with ElevenLabs or invalid Agent ID', 400);
    }
    
    logger.info('✅ Agent ID validated successfully - proceeding with activation', {
      botId: id,
      agentId: existingBot.agentId, 
      userId: req.user?.id 
    });
  }

  // Toggle bot activation
  const newStatus = !existingBot.isActive;
  logger.info('🔄 Toggling bot activation status', {
    botId: id,
    botName: existingBot.name,
    oldStatus: existingBot.isActive ? 'active' : 'inactive',
    newStatus: newStatus ? 'active' : 'inactive',
    userId: req.user?.id
  });
  
  const updatedBot = await prisma.bot.update({
    where: { id },
    data: { isActive: newStatus },
    select: {
      id: true,
      name: true,
      topic: true,
      level: true,
      imageUrl: true,
      agentId: true,
      description: true,
      feedback: true,
      isActive: true,
      isTimerEnabled: true,
      maxUsageSeconds: true,
      createdAt: true,
      updatedAt: true,
    },
  });

  const responseTime = Date.now() - startTime;
  
  logger.info('🎉 Bot activation status toggled successfully', {
    botId: updatedBot.id,
    name: updatedBot.name,
    newStatus: updatedBot.isActive ? 'active' : 'inactive',
    responseTime: `${responseTime}ms`,
    updatedBy: req.user?.id,
    ip: req.ip
  });

  const actionMessage = updatedBot.isActive ? 'Bot activated successfully' : 'Bot deactivated successfully';

  res.json({
    success: true,
    message: actionMessage,
    data: { bot: updatedBot },
  });
});

