import { Router, type Request, type Response, type NextFunction } from 'express';
import { timingSafeEqual } from 'node:crypto';
import { z } from 'zod';
import rateLimit from 'express-rate-limit';
import RedisStore from 'rate-limit-redis';
import { redis } from '../../config/redis';
import { env } from '../../config/env';
import { validate } from '../../middleware/validate';
import { prisma } from '../../config/database';
import { rocketchatClient } from '../../services/rocketchat.client';
import { siteSettingsService } from '../settings/settings.service';
import { logger } from '../../utils/logger';

const router = Router();

const bridgeRateLimit = rateLimit({
  windowMs: 60_000,
  max: 60,
  standardHeaders: true,
  legacyHeaders: false,
  store: new RedisStore({
    sendCommand: (command: string, ...args: string[]) =>
      redis.call(command, ...args) as Promise<any>,
    prefix: 'rl:bridge-rc:',
  }),
  message: {
    error: { message: 'Bridge rate limit exceeded', code: 'BRIDGE_RATE_LIMIT' },
  },
});

function requireBridgeSecret(req: Request, res: Response, next: NextFunction) {
  if (!env.JSN_BRIDGE_SECRET) {
    return res.status(503).json({ error: 'BRIDGE_DISABLED' });
  }
  const header = req.get('authorization') ?? '';
  const expected = `Bearer ${env.JSN_BRIDGE_SECRET}`;
  const headerBuf = Buffer.from(header);
  const expectedBuf = Buffer.from(expected);
  if (
    headerBuf.length !== expectedBuf.length ||
    !timingSafeEqual(headerBuf, expectedBuf)
  ) {
    return res.status(401).json({ error: 'UNAUTHORIZED' });
  }
  next();
}

const chatTokenSchema = z.object({ email: z.string().email() });

router.post(
  '/bridge/auth',
  bridgeRateLimit,
  requireBridgeSecret,
  validate(chatTokenSchema),
  async (req, res, next) => {
    try {
      const settings = await siteSettingsService.get();
      if (!settings.enableChat) {
        return res.json({ enabled: false });
      }

      const email = (req.body.email as string).trim().toLowerCase();
      const user = await prisma.user.findUnique({
        where: { email },
        select: { id: true, rocketChatUserId: true },
      });
      if (!user) {
        return res.status(404).json({ error: 'NO_CMLITE_USER' });
      }
      if (!user.rocketChatUserId) {
        // RC provisioning may have failed earlier (cmlite up before RC was)
        // or the user predates the identity bridge. Either way, no chat for
        // this user until they're re-provisioned. Fail soft.
        logger.info('chat-token bridge: no rocketChatUserId', { userId: user.id });
        return res.json({ enabled: false });
      }

      const token = await rocketchatClient.createUserToken(user.rocketChatUserId);
      return res.json({
        enabled: true,
        rcUrl: env.ROCKETCHAT_URL,
        userId: token.userId,
        authToken: token.authToken,
      });
    } catch (err) {
      next(err);
    }
  },
);

export { router as rocketchatBridgeRouter };
