import { expandGlob } from '$std/fs/mod.ts'
import { SessionHandlers } from ':src/session/mod.ts'
import { respondApi } from ':src/utils.ts'
import { BUILD_ID } from '$fresh/src/server/build_id.ts'
import { encodeBase64 } from '@std/encoding'

export type PrecacheResponse = { version: string; preCachedUrls: string[] }

async function getVersion() {
	const versionRaw = crypto.randomUUID() + BUILD_ID
	const versionBytes = new TextEncoder().encode(versionRaw)
	const versionHash = await crypto.subtle.digest('SHA-256', versionBytes)
	return encodeBase64(versionHash)
}

export const handler: SessionHandlers = {
	async GET() {
		try {
			const preCachedUrls: string[] = ['/', '/imports/markdown_css']
			const paths = ['/static/**', '/_fresh/static/**']
			const routes = '/routes/*/index.tsx'
			const version = await getVersion()

			//Pre-cache routes
			for await (const route of expandGlob(routes, { root: '.' })) {
				if (!route.isFile) continue
				//@ts-expect-error parentPath is missing from type definition
				preCachedUrls.push(strip(routes, route.parentPath))
			}

			// Pre-cache files
			for (const path of paths) {
				for await (const entry of expandGlob(path, { root: '.' })) {
					if (!entry.isFile) continue
					preCachedUrls.push(strip(path, entry.path))
				}
			}

			return respondApi<'success', PrecacheResponse>('success', {
				version,
				preCachedUrls,
			})
		} catch (error) {
			return respondApi('error', error)
		}
	},
}

function strip(root: string, path: string) {
	return path
		// Force unix/web separator
		.replaceAll('\\', '/')
		.replace(
			// Remove root slash and glob *
			root.slice(1).replaceAll('*', ''),
			'/',
		)
}
