import * as grpc from '@grpc/grpc-js';
import { kordProto } from '@kord/grpc-contracts';
import { logger } from './logger';

export interface BotInstance {
  broadcastEval?: (fn: any, options?: any) => Promise<any[]>;
  guilds?: {
    cache: {
      get: (id: string) => any;
    }
  };
}

export function startGrpcServer(bot: BotInstance, port: string = '0.0.0.0:50051') {
  const server = new grpc.Server();

  server.addService((kordProto as any).BotDashboardService.service, {
    Ping: (call: any, callback: any) => {
      logger.info('gRPC: Received Ping request');
      callback(null, { reply: `Pong to ${call.request.message}` });
    },
    GetGuildChannels: async (call: any, callback: any) => {
      const guildId = call.request.guildId;
      try {
        let channels = [];
        
        if (bot.broadcastEval) {
          // Sharded mode
          const results = await bot.broadcastEval(
            (c: any, context: any) => {
              const guild = c.guilds.cache.get(context.guildId);
              if (!guild) return null;
              return guild.channels.cache.map((ch: any) => ({ 
                id: ch.id, 
                name: ch.name, 
                type: `${ch.type}` 
              }));
            },
            { context: { guildId } }
          );
          channels = results.find(res => res !== null) || [];
        } else if (bot.guilds) {
          // Standalone mode
          const guild = bot.guilds.cache.get(guildId);
          if (guild) {
            channels = guild.channels.cache.map((ch: any) => ({
              id: ch.id,
              name: ch.name,
              type: `${ch.type}`
            }));
          }
        }

        callback(null, { channels });
      } catch (error: any) {
        logger.error('gRPC Error in GetGuildChannels:', error);
        callback({ code: grpc.status.INTERNAL, details: error.message });
      }
    }
  });

  server.bindAsync(port, grpc.ServerCredentials.createInsecure(), (err, boundPort) => {
    if (err) {
      logger.error(`Failed to bind gRPC server: ${err.message}`);
      return;
    }
    logger.info(`gRPC Proxy Server running on port ${boundPort}`);
  });

  return server;
}
