import { promises as fs } from 'fs'
import { join, resolve, sep, isAbsolute } from 'path'
import { createReadStream } from 'fs'

export default defineEventHandler(async (event) => {
  let filename = getRouterParam(event, 'filename')
  
  if (!filename) {
    throw createError({
      statusCode: 400,
      statusMessage: 'Filename is required'
    })
  }
  
  // Log incoming request
  const headers = getHeaders(event)
  const realIP = headers['x-real-ip'] || headers['x-forwarded-for'] || 'unknown'
  console.log(`[MUSIC API] Request from ${realIP} for file: ${filename}`)
  
  // Decode the filename
  try {
    filename = decodeURIComponent(filename)
  } catch (error) {
    console.error('Error decoding filename:', error)
    // If decoding fails, use original filename
  }
  
  try {
    const config = useRuntimeConfig()
    
    // Determine the music directory path
    let musicDir: string
    if (process.env.MUSIC_DIR) {
      // Resolve env to absolute
      musicDir = isAbsolute(process.env.MUSIC_DIR) ? process.env.MUSIC_DIR : resolve(process.cwd(), process.env.MUSIC_DIR)
    } else {
      // Fallback to public/music
      const defaultPublicPath = config.public?.musicPath || '/music'
      const publicRel = defaultPublicPath.replace(/^\//, '')
      musicDir = resolve(process.cwd(), 'public', publicRel)
    }
    
    // Resolve the full file path
    const filePath = resolve(musicDir, filename)
    
    // Security check: ensure the file is within the music directory
    // Normalize both paths and add separator to ensure exact directory match
    const normalizedMusicDir = musicDir.endsWith(sep) ? musicDir : musicDir + sep
    
    if (!filePath.startsWith(normalizedMusicDir)) {
      throw createError({
        statusCode: 403,
        statusMessage: 'Access denied'
      })
    }
    
    // Check if file exists
    try {
      await fs.access(filePath)
    } catch (error) {
      throw createError({
        statusCode: 404,
        statusMessage: 'File not found'
      })
    }
    
    // Get file stats
    const stats = await fs.stat(filePath)
    
    // Set appropriate headers
    const headers = getHeaders(event)
    
    // Handle range requests for audio streaming
    const range = headers.range
    
    if (range) {
      const parts = range.replace(/bytes=/, "").split("-")
      const start = parseInt(parts[0], 10)
      const end = parts[1] ? parseInt(parts[1], 10) : stats.size - 1
      const chunksize = (end - start) + 1
      
      setHeader(event, 'Content-Range', `bytes ${start}-${end}/${stats.size}`)
      setHeader(event, 'Accept-Ranges', 'bytes')
      setHeader(event, 'Content-Length', chunksize.toString())
      setResponseStatus(event, 206)
      
      return sendStream(event, createReadStream(filePath, { start, end }))
    } else {
      // Send entire file
      setHeader(event, 'Content-Length', stats.size.toString())
      setHeader(event, 'Accept-Ranges', 'bytes')
      
      // Set content type based on file extension
      const ext = filename.toLowerCase().split('.').pop()
      const contentTypes = {
        'mp3': 'audio/mpeg',
        'wav': 'audio/wav',
        'flac': 'audio/flac',
        'm4a': 'audio/mp4',
        'ogg': 'audio/ogg',
        'aac': 'audio/aac'
      }
      
      setHeader(event, 'Content-Type', contentTypes[ext] || 'audio/mpeg')
      
      return sendStream(event, createReadStream(filePath))
    }
  } catch (error) {
    if (error.statusCode) {
      throw error
    }
    
    console.error('Error serving music file:', error)
    throw createError({
      statusCode: 500,
      statusMessage: 'Failed to serve music file'
    })
  }
})
