import path from "path"
import fs from "fs"
import RemoteUpload from "@services/remoteUpload"

import ChunkFileUpload from "@shared-classes/ChunkFileUpload"

const availableProviders = ["b2", "standard"]

export default {
	useContext: ["cache", "limits"],
	middlewares: ["withAuthentication"],
	fn: async (req, res) => {
		const uploadId = `${req.headers["uploader-file-id"]}_${Date.now()}`

		const tmpPath = path.resolve(
			this.default.contexts.cache.constructor.cachePath,
			req.auth.session.user_id,
		)

		const limits = {
			maxFileSize:
				parseInt(this.default.contexts.limits.maxFileSizeInMB) *
				1024 *
				1024,
			maxChunkSize:
				parseInt(this.default.contexts.limits.maxChunkSizeInMB) *
				1024 *
				1024,
			useCompression: true,
			useProvider: "standard",
		}

		// const user = await req.auth.user()

		// if (user.roles.includes("admin")) {
		// 	// maxFileSize for admins 100GB
		// 	limits.maxFileSize = 100 * 1024 * 1024 * 1024

		// 	// optional compression for admins
		// 	limits.useCompression = req.headers["use-compression"] ?? false

		// 	limits.useProvider = req.headers["provider-type"] ?? "b2"
		// }

		// check if provider is valid
		if (!availableProviders.includes(limits.useProvider)) {
			throw new OperationError(400, "Invalid provider")
		}

		let build = await ChunkFileUpload(req, {
			tmpDir: tmpPath,
			...limits,
		}).catch((err) => {
			throw new OperationError(err.code, err.message)
		})

		if (typeof build === "function") {
			try {
				build = await build()

				if (req.headers["transmux"] || limits.useCompression === true) {
					// add a background task
					const job = await global.queues.createJob(
						"remote_upload",
						{
							filePath: build.filePath,
							parentDir: req.auth.session.user_id,
							service: limits.useProvider,
							useCompression: limits.useCompression,
							transmux: req.headers["transmux"] ?? false,
							transmuxOptions: req.headers["transmux-options"],
							cachePath: tmpPath,
						},
						{
							useSSE: true,
						},
					)

					const sseChannelId = job.sseChannelId

					return {
						uploadId: uploadId,
						sseChannelId: sseChannelId,
						eventChannelURL: `https://${req.get("host")}/upload/sse_events/${sseChannelId}`,
					}
				} else {
					const result = await RemoteUpload({
						source: build.filePath,
						parentDir: req.auth.session.user_id,
						service: limits.useProvider,
						useCompression: limits.useCompression,
						cachePath: tmpPath,
					})

					return result
				}
			} catch (error) {
				await fs.promises
					.rm(tmpPath, { recursive: true, force: true })
					.catch(() => {
						return false
					})

				throw new OperationError(
					error.code ?? 500,
					error.message ?? "Failed to upload file",
				)
			}
		}

		return {
			ok: 1,
			chunkNumber: req.headers["uploader-chunk-number"],
		}
	},
}