/**
 * GET /api/surveillance/shipment-recording/stream?token=xxx
 *
 * Streams the cached commissioning recording with HTTP Range support so
 * the browser's <video> element can seek inside large files (100MB+).
 * The file lives under the OS temp dir and is removed by the cleanup
 * endpoint (or by the TTL fallback set in init).
 */

import { createReadStream } from 'node:fs'
import { stat } from 'node:fs/promises'
import { join } from 'node:path'
import { tmpdir } from 'node:os'

const CACHE_DIR_NAME = 'logship-surveillance'

function cacheDir(): string {
  return join(tmpdir(), CACHE_DIR_NAME)
}

function isLimitedRole(event: any): boolean {
  try {
    const raw = getCookie(event, 'logship_role')
    if (!raw) return false
    const role = JSON.parse(raw)
    const fm = role?.FrontendMenu
    const id = typeof fm === 'object' ? (fm?.id ?? fm?.identifier) : fm
    return String(id || '').toLowerCase() === 'c'
  } catch {
    return false
  }
}

function isSafeToken(token: string): boolean {
  return /^[a-f0-9]{32}$/.test(token)
}

export default defineEventHandler(async (event) => {
  if (isLimitedRole(event)) {
    throw createError({ statusCode: 403, statusMessage: 'Not allowed for this role.' })
  }

  const query = getQuery(event)
  const token = String(query.token || '')
  if (!isSafeToken(token)) {
    throw createError({ statusCode: 400, statusMessage: 'Invalid token.' })
  }

  const filePath = join(cacheDir(), `${token}.mp4`)
  let st
  try {
    st = await stat(filePath)
  } catch {
    throw createError({ statusCode: 404, statusMessage: 'Recording is no longer available.' })
  }

  const total = st.size
  const range = getRequestHeader(event, 'range')

  setResponseHeader(event, 'Accept-Ranges', 'bytes')
  setResponseHeader(event, 'Content-Type', 'video/mp4')
  setResponseHeader(event, 'Cache-Control', 'private, no-store')

  if (range) {
    // Only handle the simple `bytes=start-end` form (browsers send this).
    const match = /^bytes=(\d*)-(\d*)$/.exec(range.trim())
    if (!match) {
      setResponseStatus(event, 416)
      setResponseHeader(event, 'Content-Range', `bytes */${total}`)
      return ''
    }
    const start = match[1] ? parseInt(match[1], 10) : 0
    const end = match[2] ? parseInt(match[2], 10) : total - 1
    if (Number.isNaN(start) || Number.isNaN(end) || start > end || end >= total) {
      setResponseStatus(event, 416)
      setResponseHeader(event, 'Content-Range', `bytes */${total}`)
      return ''
    }
    setResponseStatus(event, 206)
    setResponseHeader(event, 'Content-Range', `bytes ${start}-${end}/${total}`)
    setResponseHeader(event, 'Content-Length', String(end - start + 1))
    return sendStream(event, createReadStream(filePath, { start, end }))
  }

  setResponseHeader(event, 'Content-Length', String(total))
  return sendStream(event, createReadStream(filePath))
})
