import { NextResponse } from 'next/server'
import { requireAdmin, getSession } from '@/lib/auth'
import { 
  installUpdate,
  validateUpdatePackage,
  UpdateProgress
} from '@/lib/update-system'
import { prisma } from '@/lib/db'
import { createAuditLog } from '@/lib/audit'
import fs from 'fs/promises'
import path from 'path'

// Store for update progress
const updateProgress = new Map<string, {
  phase: string
  progress: number
  message: string
  details?: string
}>()

export { updateProgress }

export async function POST(request: Request) {
  const url = new URL(request.url)
  const updateId = url.searchParams.get('updateId')

  try {
    const adminCheck = await requireAdmin()
    if (adminCheck) return adminCheck

    const session = await getSession()

    if (!updateId) {
      return NextResponse.json({ error: 'Update ID required' }, { status: 400 })
    }

    // Get the stored package from temp directory
    const tempPath = path.join(process.cwd(), 'temp', `update-${updateId}.zip`)
    let buffer: Buffer
    
    try {
      buffer = await fs.readFile(tempPath)
    } catch {
      updateProgress.set(updateId, {
        phase: 'error',
        progress: 0,
        message: 'Update package not found. Please upload again.'
      })
      return NextResponse.json({ error: 'Package not found' }, { status: 404 })
    }

    // Validate the package
    const validation = await validateUpdatePackage(buffer)
    if (!validation.valid || !validation.manifest) {
      updateProgress.set(updateId, {
        phase: 'error',
        progress: 0,
        message: validation.errors.join(', ')
      })
      return NextResponse.json({ error: validation.errors.join(', ') }, { status: 400 })
    }

    const manifest = validation.manifest

    // Create package record in database
    const packageRecord = await prisma.updatePackage.upsert({
      where: { id: updateId },
      create: {
        id: updateId,
        version: manifest.version,
        filename: `update-${updateId}.zip`,
        size: buffer.length,
        status: 'VALIDATING',
        uploadedById: session?.userId || 'system',
      },
      update: {
        status: 'VALIDATING',
      }
    })

    // Run the actual update installation
    const result = await installUpdate(
      packageRecord.id,
      buffer,
      (progress: UpdateProgress) => {
        updateProgress.set(updateId, {
          phase: progress.status.toLowerCase(),
          progress: progress.progress,
          message: progress.message,
          details: progress.error
        })
      }
    )

    if (!result.success) {
      updateProgress.set(updateId, {
        phase: 'error',
        progress: 0,
        message: result.error || 'Update failed'
      })
      return NextResponse.json({ error: result.error }, { status: 500 })
    }

    // Audit log
    await createAuditLog({
      userId: session?.userId,
      action: 'SYSTEM_UPDATE_APPLIED',
      category: 'UPDATE',
      details: { version: manifest.version, updateId },
      ipAddress: request.headers.get('x-forwarded-for') || undefined
    })

    // Clean up temp file
    try {
      await fs.unlink(tempPath)
    } catch {
      // Ignore cleanup errors
    }

    // Phase: Complete
    updateProgress.set(updateId, {
      phase: 'complete',
      progress: 100,
      message: `Successfully updated to v${manifest.version}`
    })

    // Clean up progress after a delay
    setTimeout(() => {
      updateProgress.delete(updateId)
    }, 30000)

    return NextResponse.json({ 
      success: true,
      version: manifest.version
    })
  } catch (error) {
    console.error('Update application failed:', error)
    
    if (updateId) {
      updateProgress.set(updateId, {
        phase: 'error',
        progress: 0,
        message: error instanceof Error ? error.message : 'Update failed'
      })
    }

    return NextResponse.json(
      { error: 'Update application failed' },
      { status: 500 }
    )
  }
}
