import { App } from "@tinyhttp/app";
import { cors } from "@tinyhttp/cors";
import { cookieParser } from "@tinyhttp/cookie-parser";
import dotenv from "dotenv";
import { inspect } from "util";
import admin from "./routes/admin.js";
import alliance from "./routes/alliance.js";
import auth from "./routes/auth.js";
import favoriteLocation from "./routes/favorite-location.js";
import leaderboard from "./routes/leaderboard.js";
import me from "./routes/me.js";
import moderator from "./routes/moderator.js";
import pixel from "./routes/pixel.js";
import store from "./routes/store.js";
import { setupSiteContentRoutes } from "./routes/site-content.js";
import { addPrismaToRequest } from "./config/database.js";
import fs from "fs/promises";
import path from "path";
import { fileURLToPath } from "url";

dotenv.config();

const app = new App({
	noMatchHandler: async (_req, res) => {
		const html = await fs.readFile("./frontend/404.html", "utf-8");
		return res.status(404)
			.setHeader("Content-Type", "text/html")
			.send(html);
	}
});

app.use(cors());
app.use(cookieParser());
app.use((req, _res, next) => {
	let body = "";
	req.on("data", chunk => {
		body += chunk.toString();
	});
	req.on("end", () => {
		try {
			req.body = body ? JSON.parse(body) : {};
		} catch {
			req.body = {};
		}
		return next?.();
	});
});

// Logging
app.use((req, res, next) => {
	const inspectOptions = { colors: true, compact: true, breakLength: Number.POSITIVE_INFINITY };
	const startTime = Date.now();
	const requestId = req.get("x-forwarded-for");

	console.log(`[${requestId}] [${new Date()
		.toISOString()}] ${req.method} ${req.url}`);
	console.log(`[${requestId}] Headers:`, inspect(req.headers, inspectOptions));
	if (req.body && Object.keys(req.body).length > 0) {
		console.log(`[${requestId}] Body:`, inspect(req.body, inspectOptions));
	}

	const originalJson = res.json;
	res.json = function (data) {
		const duration = Date.now() - startTime;
		console.log(`[${requestId}] Response JSON (${res.statusCode}) [${duration}ms]:`, inspect(data, inspectOptions));
		return originalJson.call(this, data);
	};

	return next?.();
});

app.use(addPrismaToRequest);

// Static file serving middleware
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const frontendPath = path.join(__dirname, "..", "frontend");

app.use(async (req, res, next) => {
	// Skip API routes
	if (req.url?.startsWith("/api") || req.url?.startsWith("/auth")) {
		return next?.();
	}

	try {
		// Try to serve static file
		let filePath = path.join(frontendPath, req.url || "");
		let stats = await fs.stat(filePath);

		// If it's a directory, try to serve index.html
		if (stats.isDirectory()) {
			filePath = path.join(filePath, "index.html");
			stats = await fs.stat(filePath);
		}

		if (stats.isFile()) {
			const content = await fs.readFile(filePath);
			const ext = path.extname(filePath).toLowerCase();

			const mimeTypes: Record<string, string> = {
				".html": "text/html",
				".js": "application/javascript",
				".css": "text/css",
				".json": "application/json",
				".png": "image/png",
				".jpg": "image/jpeg",
				".jpeg": "image/jpeg",
				".svg": "image/svg+xml",
				".ico": "image/x-icon",
				".woff": "font/woff",
				".woff2": "font/woff2",
				".webmanifest": "application/manifest+json"
			};

			res.setHeader("Content-Type", mimeTypes[ext] || "application/octet-stream");
			return res.send(content);
		}
	} catch {
		// File not found, continue to next handler
	}

	return next?.();
});

admin(app);
alliance(app);
auth(app);
favoriteLocation(app);
leaderboard(app);
me(app);
moderator(app);
pixel(app);
store(app);
setupSiteContentRoutes(app);

const PORT = Number(process.env["PORT"]) || 3000;

app.listen(PORT, () => {
	console.log(`Server running on port ${PORT}`);
});
