// @ts-check

const assert = require("assert")
const fs = require("fs")
const {join} = require("path")
const h3 = require("h3")
const mimeTypes = require("mime-types")
const {defineEventHandler, defaultContentType, getRequestHeader, setResponseHeader, handleCacheHeaders, serveStatic} = h3
const icons = require("@stackoverflow/stacks-icons")
const DiscordTypes = require("discord-api-types/v10")
const dUtils = require("../discord/utils")
const reg = require("../matrix/read-registration")

const {sync, discord, as, select, from} = require("../passthrough")
/** @type {import("./pug-sync")} */
const pugSync = sync.require("./pug-sync")
/** @type {import("../matrix/utils")} */
const mUtils = sync.require("../matrix/utils")
const {id} = require("../../addbot")

// Pug

pugSync.addGlobals({id, h3, discord, select, from, DiscordTypes, dUtils, mUtils, icons, reg: reg.reg})

// Files

function compressResponse(event, response) {
	if (!getRequestHeader(event, "accept-encoding")?.includes("gzip")) return
	/* c8 ignore next */
	if (typeof response.body !== "string") return
	const stream = new Response(response.body).body
	assert(stream)
	setResponseHeader(event, "content-encoding", "gzip")
	response.body = stream.pipeThrough(new CompressionStream("gzip"))
}

as.router.get("/static/stacks.min.css", defineEventHandler({
	onBeforeResponse: compressResponse,
	handler: async event => {
		handleCacheHeaders(event, {maxAge: 86400})
		defaultContentType(event, "text/css")
		return fs.promises.readFile(require.resolve("@stackoverflow/stacks/dist/css/stacks.css"), "utf-8")
	}
}))

as.router.get("/static/htmx.js", defineEventHandler({
	onBeforeResponse: compressResponse,
	handler: async event => {
		handleCacheHeaders(event, {maxAge: 86400})
		defaultContentType(event, "text/javascript")
		return fs.promises.readFile(require.resolve("htmx.org/dist/htmx.js"), "utf-8")
	}
}))

as.router.get("/download/file/poll-star-avatar.png", defineEventHandler(event => {
	handleCacheHeaders(event, {maxAge: 86400})
	return fs.promises.readFile(join(__dirname, "../../docs/img/poll-star-avatar.png"))
}))

// Custom files

const publicDir = "custom-webroot"

/**
 * @param {h3.H3Event} event
 * @param {boolean} fallthrough
 */
function tryStatic(event, fallthrough) {
	return serveStatic(event, {
		indexNames: ["/index.html", "/index.pug"],
		fallthrough,
		getMeta: async id => {
			// Check
			const stats = await fs.promises.stat(join(publicDir, id)).catch(() => {});
			if (!stats || !stats.isFile()) {
				return
			}
			// Pug
			if (id.match(/\.pug$/)) {
				defaultContentType(event, "text/html; charset=utf-8")
				return {}
			}
			// Everything else
			else {
				const mime = mimeTypes.lookup(id)
				if (typeof mime === "string") {
					if (mime.startsWith("text/")) {
						defaultContentType(event, mime + "; charset=utf-8") // usually wise
					} else {
						defaultContentType(event, mime)
					}
				}
				return {
					size: stats.size
				}
			}
		},
		getContents: id => {
			if (id.match(/\.pug$/)) {
				const path = join(publicDir, id)
				return pugSync.renderPath(event, path, {})
			} else {
				return fs.createReadStream(join(publicDir, id))
			}
		}
	})
}

as.router.get("/**", defineEventHandler(event => {
	return tryStatic(event, false)
}))

as.router.get("/", defineEventHandler(async event => {
	return (await tryStatic(event, true)) || pugSync.render(event, "home.pug", {})
}))

as.router.get("/icon.png", defineEventHandler(async event => {
	const s = await tryStatic(event, true)
	if (s) return s
	handleCacheHeaders(event, {maxAge: 86400})
	return fs.promises.readFile(join(__dirname, "../../docs/img/icon.png"))
}))

// Routes

pugSync.createRoute(as.router, "/ok", "ok.pug")

sync.require("./routes/agi")
sync.require("./routes/download-matrix")
sync.require("./routes/download-discord")
sync.require("./routes/guild-settings")
sync.require("./routes/guild")
sync.require("./routes/info")
sync.require("./routes/link")
sync.require("./routes/log-in-with-matrix")
sync.require("./routes/oauth")
sync.require("./routes/password")
