import type { RequestHandler } from './$types'
import { prisma } from '$lib/server/database'
import { uploadFiles, isCloudinaryConfigured } from '$lib/server/cloudinary'
import { jsonResponse, errorResponse, checkAdminAuth } from '$lib/server/api-utils'
import { logger } from '$lib/server/logger'
import exifr from 'exifr'

// Extract EXIF data from image file
async function extractExifData(file: File) {
	try {
		logger.info(`Starting EXIF extraction for ${file.name}`, {
			size: file.size,
			type: file.type
		})

		const buffer = await file.arrayBuffer()
		logger.info(`Buffer created for ${file.name}`, { bufferSize: buffer.byteLength })

		// Try parsing without pick first to see all available data
		const fullExif = await exifr.parse(buffer)
		logger.info(`Full EXIF data available for ${file.name}:`, {
			hasData: !!fullExif,
			availableFields: fullExif ? Object.keys(fullExif).slice(0, 10) : [] // First 10 fields
		})

		// Now parse with specific fields
		const exif = await exifr.parse(buffer, {
			pick: [
				'Make',
				'Model',
				'LensModel',
				'FocalLength',
				'FNumber',
				'ExposureTime',
				'ISO',
				'ISOSpeedRatings', // Alternative ISO field
				'DateTimeOriginal',
				'DateTime', // Alternative date field
				'GPSLatitude',
				'GPSLongitude',
				'Orientation',
				'ColorSpace'
			]
		})

		logger.info(`EXIF parse result for ${file.name}:`, {
			hasExif: !!exif,
			exifKeys: exif ? Object.keys(exif) : []
		})

		if (!exif) return null

		// Format EXIF data
		const formattedExif: any = {}

		// Camera info
		if (exif.Make && exif.Model) {
			formattedExif.camera = `${exif.Make} ${exif.Model}`.replace(/\s+/g, ' ').trim()
		}

		// Lens info
		if (exif.LensModel) {
			formattedExif.lens = exif.LensModel
		}

		// Settings
		if (exif.FocalLength) {
			formattedExif.focalLength = `${exif.FocalLength}mm`
		}

		if (exif.FNumber) {
			formattedExif.aperture = `f/${exif.FNumber}`
		}

		if (exif.ExposureTime) {
			formattedExif.shutterSpeed =
				exif.ExposureTime < 1 ? `1/${Math.round(1 / exif.ExposureTime)}` : `${exif.ExposureTime}s`
		}

		if (exif.ISO) {
			formattedExif.iso = `ISO ${exif.ISO}`
		} else if (exif.ISOSpeedRatings) {
			// Handle alternative ISO field
			const iso = Array.isArray(exif.ISOSpeedRatings)
				? exif.ISOSpeedRatings[0]
				: exif.ISOSpeedRatings
			formattedExif.iso = `ISO ${iso}`
		}

		// Date taken
		if (exif.DateTimeOriginal) {
			formattedExif.dateTaken = exif.DateTimeOriginal
		} else if (exif.DateTime) {
			// Fallback to DateTime if DateTimeOriginal not available
			formattedExif.dateTaken = exif.DateTime
		}

		// GPS coordinates
		if (exif.GPSLatitude && exif.GPSLongitude) {
			formattedExif.coordinates = {
				latitude: exif.GPSLatitude,
				longitude: exif.GPSLongitude
			}
		}

		// Additional metadata
		if (exif.Orientation) {
			formattedExif.orientation =
				exif.Orientation === 1 ? 'Horizontal (normal)' : `Rotated (${exif.Orientation})`
		}

		if (exif.ColorSpace) {
			formattedExif.colorSpace = exif.ColorSpace
		}

		const result = Object.keys(formattedExif).length > 0 ? formattedExif : null
		logger.info(`Final EXIF result for ${file.name}:`, {
			hasData: !!result,
			fields: result ? Object.keys(result) : []
		})
		return result
	} catch (error) {
		logger.warn('Failed to extract EXIF data', {
			filename: file.name,
			error: error instanceof Error ? error.message : 'Unknown error'
		})
		return null
	}
}

export const POST: RequestHandler = async (event) => {
	// Check authentication
	if (!checkAdminAuth(event)) {
		return errorResponse('Unauthorized', 401)
	}

	// Check if Cloudinary is configured
	if (!isCloudinaryConfigured()) {
		return errorResponse('Media upload service not configured', 503)
	}

	try {
		const formData = await event.request.formData()
		const files = formData.getAll('files') as File[]
		const context = (formData.get('context') as string) || 'media'

		if (!files || files.length === 0) {
			return errorResponse('No files provided', 400)
		}

		// Validate all files
		const allowedTypes = ['image/jpeg', 'image/jpg', 'image/png', 'image/webp']
		const maxSize = 10 * 1024 * 1024 // 10MB per file
		const maxFiles = 50 // Maximum 50 files at once

		if (files.length > maxFiles) {
			return errorResponse(`Too many files. Maximum ${maxFiles} files allowed`, 400)
		}

		for (const file of files) {
			if (!(file instanceof File)) {
				return errorResponse('Invalid file format', 400)
			}

			if (!allowedTypes.includes(file.type)) {
				return errorResponse(
					`Invalid file type for ${file.name}. Allowed types: JPEG, PNG, WebP`,
					400
				)
			}

			if (file.size > maxSize) {
				return errorResponse(`File ${file.name} is too large. Maximum size is 10MB`, 400)
			}
		}

		logger.info(`Starting bulk upload of ${files.length} files`)

		// Extract EXIF data before uploading (files might not be readable after upload)
		const exifDataMap = new Map()
		for (const file of files) {
			if (file.type.startsWith('image/') && file.type !== 'image/svg+xml') {
				logger.info(`Pre-extracting EXIF data for ${file.name}`)
				const exifData = await extractExifData(file)
				if (exifData) {
					exifDataMap.set(file.name, exifData)
					logger.info(`EXIF data found for ${file.name}`)
				}
			}
		}

		// Upload all files to Cloudinary
		const uploadResults = await uploadFiles(files, context as 'media' | 'photos' | 'projects')

		// Process results and save to database
		const mediaRecords = []
		const errors = []

		for (let i = 0; i < uploadResults.length; i++) {
			const result = uploadResults[i]
			const file = files[i]

			if (result.success) {
				try {
					// Get pre-extracted EXIF data
					const exifData = exifDataMap.get(file.name) || null

					const media = await prisma.media.create({
						data: {
							filename: file.name,
							originalName: file.name,
							mimeType: file.type,
							size: file.size,
							url: result.secureUrl!,
							thumbnailUrl: result.thumbnailUrl,
							width: result.width,
							height: result.height,
							exifData: exifData,
							usedIn: []
						}
					})

					mediaRecords.push({
						id: media.id,
						url: media.url,
						thumbnailUrl: media.thumbnailUrl,
						width: media.width,
						height: media.height,
						filename: media.filename,
						exifData: media.exifData
					})
				} catch (dbError) {
					errors.push({
						filename: file.name,
						error: 'Failed to save to database'
					})
				}
			} else {
				errors.push({
					filename: file.name,
					error: result.error || 'Upload failed'
				})
			}
		}

		logger.info(`Bulk upload completed: ${mediaRecords.length} successful, ${errors.length} failed`)

		return jsonResponse(
			{
				success: mediaRecords.length,
				failed: errors.length,
				total: files.length,
				media: mediaRecords,
				errors: errors.length > 0 ? errors : undefined
			},
			201
		)
	} catch (error) {
		logger.error('Bulk upload error', error as Error)
		return errorResponse('Failed to upload files', 500)
	}
}

// Handle preflight requests
export const OPTIONS: RequestHandler = async () => {
	return new Response(null, {
		status: 204,
		headers: {
			'Access-Control-Allow-Origin': '*',
			'Access-Control-Allow-Methods': 'POST, OPTIONS',
			'Access-Control-Allow-Headers': 'Content-Type, Authorization'
		}
	})
}
