import { spawn } from 'child_process'
import { existsSync, readdirSync, statSync } from 'fs'
import path from 'path'
import { prisma } from '@/lib/prisma'
import { buildYtdlpArgs } from '@/lib/ytdlp'
import { createToken } from '@/lib/token'
import { config } from '../config/app.config'

function resolveYtdlpBin(): string {
  const local = path.join(config.BIN_DIR, 'yt-dlp')
  return existsSync(local) ? local : 'yt-dlp'
}

export async function processDownload(downloadId: string): Promise<void> {
  const download = await prisma.download.findUnique({ where: { id: downloadId } })
  if (!download) return

  const args = buildYtdlpArgs({
    url: download.url,
    uuid: download.uuid,
    format: download.format,
    quality: download.quality,
    subtitles: download.subtitles,
    extraArgs: download.extraArgs,
  })

  let stderr = ''

  await new Promise<void>((resolve) => {
    const proc = spawn(resolveYtdlpBin(), args)
    proc.stderr.on('data', (chunk: Buffer) => { stderr += chunk.toString() })

    proc.on('close', async (code) => {
      if (code === 0) {
        const files = readdirSync(config.STORAGE_PATH).filter((f) =>
          f.startsWith(download.uuid)
        )
        const relFile = files[0] ?? null
        const filePath = relFile ? path.join(config.STORAGE_PATH, relFile) : null
        const fileSize = filePath ? BigInt(statSync(filePath).size) : null

        await prisma.download.update({
          where: { id: downloadId },
          data: {
            status: 'DONE',
            filePath,
            fileName: relFile,
            fileSize,
            completedAt: new Date(),
          },
        })
        await createToken(downloadId)
      } else {
        await prisma.download.update({
          where: { id: downloadId },
          data: {
            status: 'FAILED',
            errorMsg: stderr || `yt-dlp exited with code ${code}`,
            completedAt: new Date(),
          },
        })
      }
      resolve()
    })
  })
}
