import { Router } from 'express'
import { z } from 'zod'
import { env } from '../config/env.js'
import { asyncHandler } from '../middleware/asyncHandler.js'
import { requireAuth } from '../middleware/auth.js'
import { validateBody } from '../middleware/validate.js'
import { meetingCodeSchema } from '../lib/meetingCode.js'
import { validationError } from '../lib/errors.js'
import * as meetingService from '../services/meetingService.js'

const createSchema = z.object({
  title: z.string().trim().max(120).optional(),
})

export const meetingRouter = Router()

meetingRouter.use(requireAuth)

meetingRouter.post(
  '/',
  validateBody(createSchema),
  asyncHandler(async (req, res) => {
    const meeting = await meetingService.createMeeting(req.identity!, req.body.title)
    res.status(201).json({ meeting: meetingService.toMeetingDto(meeting, req.identity) })
  }),
)

meetingRouter.get(
  '/:code',
  asyncHandler(async (req, res) => {
    const code = String(req.params.code || '').toLowerCase()
    if (!meetingCodeSchema.test(code)) throw validationError('Invalid meeting code')
    const meeting = await meetingService.getMeetingByCode(code)
    res.json({
      meeting: meetingService.toMeetingDto(meeting, req.identity),
      iceServers: iceServers(),
    })
  }),
)

meetingRouter.get(
  '/:code/messages',
  asyncHandler(async (req, res) => {
    const code = String(req.params.code || '').toLowerCase()
    if (!meetingCodeSchema.test(code)) throw validationError('Invalid meeting code')
    const meeting = await meetingService.getMeetingByCode(code)
    const messages = await meetingService.listMessages(meeting._id)
    res.json({ messages })
  }),
)

const iceServers = () => {
  const servers: Array<Record<string, string | string[]>> = [{ urls: env.STUN_URL }]
  if (env.TURN_URL && env.TURN_USERNAME && env.TURN_CREDENTIAL) {
    servers.push({
      urls: env.TURN_URL,
      username: env.TURN_USERNAME,
      credential: env.TURN_CREDENTIAL,
    })
  }
  return servers
}
