import { createRouter } from '@@/create-router';
import { getServerIntegration, upsertServerIntegration, getUserIntegration, deleteUserIntegration } from 'officerdb';
import { startDiscordBot, stopDiscordBot, isDiscordBotRunning, getDiscordBotUsername } from './discord/bot';
import { startTelegramBot, stopTelegramBot, isTelegramBotRunning, getTelegramBotUsername } from './telegram/bot';
import {
  startWhatsAppBot,
  stopWhatsAppBot,
  isWhatsAppBotRunning,
  getWhatsAppBotPhone,
  getWhatsAppQR,
  disconnectWhatsApp,
} from './whatsapp/bot';
import { generatePairingCode } from './pairing';

export const channelsRouter = createRouter();

// ── Admin: Discord config ──

channelsRouter.get('/discord/config', async (ctx) => {
  const integration = await getServerIntegration('discord');
  if (!integration) return ctx.json({ configured: false });

  const config = integration.config as Record<string, unknown>;
  const botToken = config.botToken as string | undefined;

  return ctx.json({
    configured: !!botToken,
    enabled: integration.enabled,
    botToken: botToken ? `${botToken.slice(0, 8)}...${botToken.slice(-4)}` : null,
    serverInvite: (config.serverInvite as string) ?? null,
    botHandle: (config.botHandle as string) ?? null,
  });
});

channelsRouter.put('/discord/config', async (ctx) => {
  const body = ctx.get('body') as Record<string, unknown>;
  const botToken = body.botToken as string | undefined;
  const enabled = body.enabled as boolean | undefined;
  const serverInvite = body.serverInvite as string | undefined;
  const botHandle = body.botHandle as string | undefined;

  if (!botToken && enabled === undefined && serverInvite === undefined && botHandle === undefined) {
    return ctx.json({ error: 'At least one field required' }, 400);
  }

  const existing = await getServerIntegration('discord');
  const existingConfig = (existing?.config ?? {}) as Record<string, unknown>;
  const newConfig = { ...existingConfig };
  if (botToken) newConfig.botToken = botToken;
  if (serverInvite !== undefined) newConfig.serverInvite = serverInvite;
  if (botHandle !== undefined) newConfig.botHandle = botHandle;

  const shouldRun = enabled ?? existing?.enabled ?? true;
  const token = (botToken ?? existingConfig.botToken) as string | undefined;

  // If a new token is provided, validate it by starting the bot before saving
  if (botToken && shouldRun) {
    try {
      await startDiscordBot(botToken);
    } catch (err) {
      console.error('[channels] Discord bot token validation failed:', err);
      return ctx.json({ error: 'Invalid bot token — connection failed' }, 400);
    }
  }

  await upsertServerIntegration('discord', newConfig, shouldRun);

  // Start/restart with existing token (already validated on initial save)
  if (!botToken && token && shouldRun) {
    try {
      await startDiscordBot(token);
    } catch (err) {
      console.error('[channels] Failed to start Discord bot:', err);
      return ctx.json({ success: true, botStarted: false, error: String(err) });
    }
  }

  if (!shouldRun) {
    await stopDiscordBot();
  }

  return ctx.json({ success: true, botStarted: token && shouldRun });
});

channelsRouter.get('/discord/status', async (ctx) => {
  const integration = await getServerIntegration('discord');
  const config = (integration?.config ?? {}) as Record<string, unknown>;

  return ctx.json({
    configured: !!config.botToken,
    enabled: integration?.enabled ?? false,
    running: isDiscordBotRunning(),
    botUsername: getDiscordBotUsername(),
    serverInvite: (config.serverInvite as string) ?? null,
    botHandle: (config.botHandle as string) ?? null,
  });
});

// ── User: Discord pairing ──

channelsRouter.post('/discord/pair', async (ctx) => {
  const user = ctx.get('user');
  const code = generatePairingCode(user.id, user.email, 'discord');
  return ctx.json({ code, expiresIn: 600 });
});

channelsRouter.get('/discord/connection', async (ctx) => {
  const user = ctx.get('user');
  const integration = await getUserIntegration(user.id, 'discord');
  if (!integration) return ctx.json({ linked: false });

  const config = integration.config as Record<string, unknown>;
  return ctx.json({
    linked: true,
    discordId: config.discordId,
  });
});

channelsRouter.delete('/discord/connection', async (ctx) => {
  const user = ctx.get('user');
  const deleted = await deleteUserIntegration(user.id, 'discord');
  return ctx.json({ success: deleted });
});

// ── Admin: Telegram config ──

channelsRouter.get('/telegram/config', async (ctx) => {
  const integration = await getServerIntegration('telegram');
  if (!integration) return ctx.json({ configured: false });

  const config = integration.config as Record<string, unknown>;
  const botToken = config.botToken as string | undefined;

  return ctx.json({
    configured: !!botToken,
    enabled: integration.enabled,
    botToken: botToken ? `${botToken.slice(0, 8)}...${botToken.slice(-4)}` : null,
    serverInvite: (config.serverInvite as string) ?? null,
    botHandle: (config.botHandle as string) ?? null,
  });
});

channelsRouter.put('/telegram/config', async (ctx) => {
  const body = ctx.get('body') as Record<string, unknown>;
  const botToken = body.botToken as string | undefined;
  const enabled = body.enabled as boolean | undefined;
  const serverInvite = body.serverInvite as string | undefined;
  const botHandle = body.botHandle as string | undefined;

  if (!botToken && enabled === undefined && serverInvite === undefined && botHandle === undefined) {
    return ctx.json({ error: 'At least one field required' }, 400);
  }

  const existing = await getServerIntegration('telegram');
  const existingConfig = (existing?.config ?? {}) as Record<string, unknown>;
  const newConfig = { ...existingConfig };
  if (botToken) newConfig.botToken = botToken;
  if (serverInvite !== undefined) newConfig.serverInvite = serverInvite;
  if (botHandle !== undefined) newConfig.botHandle = botHandle;

  const shouldRun = enabled ?? existing?.enabled ?? true;
  const token = (botToken ?? existingConfig.botToken) as string | undefined;

  // If a new token is provided, validate it by starting the bot before saving
  if (botToken && shouldRun) {
    try {
      await startTelegramBot(botToken);
    } catch (err) {
      console.error('[channels] Telegram bot token validation failed:', err);
      return ctx.json({ error: 'Invalid bot token — connection failed' }, 400);
    }
  }

  await upsertServerIntegration('telegram', newConfig, shouldRun);

  // Start/restart with existing token (already validated on initial save)
  if (!botToken && token && shouldRun) {
    try {
      await startTelegramBot(token);
    } catch (err) {
      console.error('[channels] Failed to start Telegram bot:', err);
      return ctx.json({ success: true, botStarted: false, error: String(err) });
    }
  }

  if (!shouldRun) {
    await stopTelegramBot();
  }

  return ctx.json({ success: true, botStarted: token && shouldRun });
});

channelsRouter.get('/telegram/status', async (ctx) => {
  const integration = await getServerIntegration('telegram');
  const config = (integration?.config ?? {}) as Record<string, unknown>;

  return ctx.json({
    configured: !!config.botToken,
    enabled: integration?.enabled ?? false,
    running: isTelegramBotRunning(),
    botUsername: getTelegramBotUsername(),
    serverInvite: (config.serverInvite as string) ?? null,
    botHandle: (config.botHandle as string) ?? null,
  });
});

// ── User: Telegram pairing ──

channelsRouter.post('/telegram/pair', async (ctx) => {
  const user = ctx.get('user');
  const code = generatePairingCode(user.id, user.email, 'telegram');
  return ctx.json({ code, expiresIn: 600 });
});

channelsRouter.get('/telegram/connection', async (ctx) => {
  const user = ctx.get('user');
  const integration = await getUserIntegration(user.id, 'telegram');
  if (!integration) return ctx.json({ linked: false });

  const config = integration.config as Record<string, unknown>;
  return ctx.json({
    linked: true,
    telegramId: config.telegramId,
  });
});

channelsRouter.delete('/telegram/connection', async (ctx) => {
  const user = ctx.get('user');
  const deleted = await deleteUserIntegration(user.id, 'telegram');
  return ctx.json({ success: deleted });
});

// ── Admin: WhatsApp config ──

channelsRouter.get('/whatsapp/config', async (ctx) => {
  const integration = await getServerIntegration('whatsapp');

  return ctx.json({
    configured: integration?.enabled ?? false,
    enabled: integration?.enabled ?? false,
    running: isWhatsAppBotRunning(),
    phone: getWhatsAppBotPhone(),
  });
});

channelsRouter.put('/whatsapp/config', async (ctx) => {
  const body = ctx.get('body') as Record<string, unknown>;
  const enabled = body.enabled as boolean | undefined;

  if (enabled === true) {
    await upsertServerIntegration('whatsapp', {}, true);
    // Don't await — initialization is slow (launches Chromium) and QR events
    // are delivered via SSE. Return immediately so the client can connect SSE.
    startWhatsAppBot().catch((err) => {
      console.error('[channels] Failed to start WhatsApp bot:', err);
    });
    return ctx.json({ success: true, botStarted: false });
  }

  if (enabled === false) {
    await disconnectWhatsApp();
    return ctx.json({ success: true, botStarted: false });
  }

  return ctx.json({ error: 'enabled field required' }, 400);
});

channelsRouter.get('/whatsapp/status', async (ctx) => {
  const integration = await getServerIntegration('whatsapp');

  return ctx.json({
    configured: integration?.enabled ?? false,
    enabled: integration?.enabled ?? false,
    running: isWhatsAppBotRunning(),
    phone: getWhatsAppBotPhone(),
  });
});

channelsRouter.get('/whatsapp/qr', async (ctx) => {
  const qr = getWhatsAppQR();
  return ctx.json({
    qr,
    running: isWhatsAppBotRunning(),
    phone: getWhatsAppBotPhone(),
  });
});

// ── User: WhatsApp pairing ──

channelsRouter.post('/whatsapp/pair', async (ctx) => {
  const user = ctx.get('user');
  const code = generatePairingCode(user.id, user.email, 'whatsapp');
  return ctx.json({ code, expiresIn: 600 });
});

channelsRouter.get('/whatsapp/connection', async (ctx) => {
  const user = ctx.get('user');
  const integration = await getUserIntegration(user.id, 'whatsapp');
  if (!integration) return ctx.json({ linked: false });

  const config = integration.config as Record<string, unknown>;
  return ctx.json({
    linked: true,
    whatsappId: config.whatsappId,
  });
});

channelsRouter.delete('/whatsapp/connection', async (ctx) => {
  const user = ctx.get('user');
  const deleted = await deleteUserIntegration(user.id, 'whatsapp');
  return ctx.json({ success: deleted });
});
