// require("module-alias/register");

import dotenv from "dotenv";
import express, { Request, Response, NextFunction } from "express";
import "express-async-errors"; // needed for global error catching, reducing the try/catch all over the place
import cors from "cors";
import helmet from "helmet";
import os from "os";

// import fs from 'fs'

// const content = `\nAPI host: ${process.env.armory_db_host}\nAPI user: ${process.env.armory_db_user}\nAPI password: ${process.env.armory_db_password}`

// fs.writeFileSync('/var/www/html/armory/api/log.txt', content)

// import 'module-alias/register.js'
// import express from "express";
// import cors from "cors";
// import swaggerUi from "swagger-ui-express"
// import swaggerDocument from "./swagger.json"

// common routes

import cacheRouter from "~/routes/cache";
// import authRouter from "~/routes/auth";
import routeUsers from "~/routes/users";
import dashboardRouter from "~/routes/dashboard";
import lockRouter from "~/routes/lock";
import itemsRouter from "~/routes/item/items";
import itemSetsRouter from "~/routes/item/sets";
import itemBundleRouter from "~/routes/item/bundle";
import itemBundlesRouter from "~/routes/item/bundles";
import suitsRouter from "~/routes/suit/index";
// import suitsItemsRouter from "~/routes/suit/items";
import itemGroupsRouter from "~/routes/item/groups";
import itemSubGroupsRouter from "~/routes/item/subGroups";
import itemCategoriesRouter from "~/routes/item/categories";
import itemSubCategoriesRouter from "~/routes/item/subCategories";
import sourcesRouter from "~/routes/sources";
import statusRouter from "~/routes/status";
import makersRouter from "~/routes/makers";
import makersByCategoryRouter from "~/routes/makersByCategory";
import photosRouter from "~/routes/photos";
import financialsRouter from "~/routes/financials";

import libraryRouter from "~/routes/library";

import { getBasePhotoPath } from "~/functions/isLinuxServer";

// japanese weapons
// import japaneseWeaponSwordRouter from "~/routes/japanese/weapon/sword";

// european weapons
// import europeanWeaponSwordRouter from "~/routes/medieval/weapon/sword";

// japanese armor
import japaneseArmorKabutoRouter from "~/routes/japanese/armor/kabuto";
import japaneseArmorMempoRouter from "~/routes/japanese/armor/mempo";
import japaneseArmorDoRouter from "~/routes/japanese/armor/do";
import japaneseArmorSodeRouter from "~/routes/japanese/armor/sode";
import japaneseArmorKoteRouter from "~/routes/japanese/armor/kote";
import japaneseArmorHaidateRouter from "~/routes/japanese/armor/haidate";
import japaneseArmorSuneateRouter from "~/routes/japanese/armor/suneate";

// core
import coreRouter from "~/routes/core";

import weaponsRouter from "~/routes/weapons";
import armorRouter from "~/routes/armor";
import clothingRouter from "~/routes/clothing";
import decorRouter from "~/routes/decor";

import getToken from "~/functions/getToken";

// medieval weapons

// medieval armor

// reports
import reportsRouter from "~/routes/reports";

// wishlist
import wishlistRouter from "~/routes/wishlist";
import "~/functions/cache";

// general settings for API server
// const app = express();
// const port = process.env.armory_api_host || 3001;

// import getToken from "./auth/getToken";
// import urlWhitelist from "./auth/urlWhitelist";

// TODO: use checkToken() to enforce paths that require authorization / login
// TODO: use checkToken() to enforce paths that require authorization / login
// TODO: use checkToken() to enforce paths that require authorization / login
// TODO: use checkToken() to enforce paths that require authorization / login
// TODO: use checkToken() to enforce paths that require authorization / login
// TODO: use checkToken() to enforce paths that require authorization / login
// TODO: use checkToken() to enforce paths that require authorization / login
// TODO: use checkToken() to enforce paths that require authorization / login
// TODO: use checkToken() to enforce paths that require authorization / login
// TODO: use checkToken() to enforce paths that require authorization / login
// TODO: use checkToken() to enforce paths that require authorization / login
// TODO: use checkToken() to enforce paths that require authorization / login
// TODO: use checkToken() to enforce paths that require authorization / login
// TODO: use checkToken() to enforce paths that require authorization / login
// TODO: use checkToken() to enforce paths that require authorization / login
// TODO: use checkToken() to enforce paths that require authorization / login
// TODO: use checkToken() to enforce paths that require authorization / login
// TODO: use checkToken() to enforce paths that require authorization / login
// TODO: use checkToken() to enforce paths that require authorization / login
// TODO: use checkToken() to enforce paths that require authorization / login
// TODO: use checkToken() to enforce paths that require authorization / login
// TODO: use checkToken() to enforce paths that require authorization / login
// TODO: use checkToken() to enforce paths that require authorization / login

// import routeCategories from "./routes/categories";
// import routeIngredients from "./routes/ingredients";
// import routeIngredientTypes from "./routes/ingredientTypes";
// import routeQuantities from "./routes/quantities";
// import routeRecipes from "./routes/recipes";
// import routeRecipesIngredients from "./routes/recipes/ingredients";
// import routeRecipesInstructions from "./routes/recipes/instructions";

dotenv.config({ path: require("find-config")(".env") });
// dotenv.config();

// console.log("\n\ndotenv:::::", dotenv.config(), "\n\n");

if (!process.env.PORT) {
	process.exit(1);
}

const PORT: number = parseInt(process.env.PORT as string, 10);

const app = express();

const hostname = os.hostname();

app.use(helmet());

app.use(cors());
app.use(helmet.crossOriginResourcePolicy({ policy: "cross-origin" }));

app.use(express.json());

// make token available globally on all routes
app.use("*", function (_req: Request, _res: Response, next: NextFunction) {
	const method = _req.method.toUpperCase();
	const path = _req.baseUrl.toUpperCase().replace("/API", "");
	const noTokenNeeded =
		(method === "POST" && path === "/USERS") ||
		(method === "GET" && path.indexOf("/LIBRARY") === 0) ||
		(method === "GET" && path === "/WISHLIST/PUBLIC") ||
		path.indexOf(".JPG") > 0 ||
		path.indexOf(".JPEG") > 0 ||
		path.indexOf(".PNG") > 0 ||
		path.indexOf(".GIF") > 0;

	// console.log("QUERY::::", _req);

	if (hostname === "office") {
		console.log(`${_req?.method} ${_req.baseUrl}${_req.url}`);
		// console.log(`${_req?.method} ${_req.baseUrl}`);

		if (_req?.params?.length > 0) {
			console.log(`\n  >> PARAMS: `, _req.params);
		}

		if (_req?.query?.length > 0) {
			console.log(`\n  >> QUERY:`, _req.query, `\n`);
		}
	}

	// if (noTokenNeeded === false) {
	// 	try {
	// 		getToken(_req, _res);

	// 		if (_req.user === null) {
	// 			next();
	// 		}
	// 	} catch (err) {
	// 		console.log("GLOBAL ERROR CATCHER!!!!", err);
	// 	}
	// }

	next();
});

app.use(
	express.urlencoded({
		extended: true,
	}),
);

// landing page / heartbeat check
app.get("/", (_req: Request, res: Response) => {
	res.json({ message: "ok" });
});

// custom routes
app.use("/api/clearCache", cacheRouter);

// app.use("/api/auth", authRouter);
app.use("/api/users", routeUsers);
app.use("/api/dashboard", dashboardRouter);
app.use("/api/lock", lockRouter);

app.use("/api/items", itemsRouter);
app.use("/api/itemSets", itemSetsRouter);
app.use("/api/itemBundles", itemBundlesRouter);
app.use("/api/suits", suitsRouter);
// app.use("/api/suits/:fullsuitID/items", suitsItemsRouter);
app.use("/api/itemBundle", itemBundleRouter);
app.use("/api/itemGroups", itemGroupsRouter);
app.use("/api/itemSubGroups", itemSubGroupsRouter);
app.use("/api/itemCategories", itemCategoriesRouter);
app.use("/api/itemSubCategories", itemSubCategoriesRouter);
app.use("/api/sources", sourcesRouter);
app.use("/api/status", statusRouter);
app.use("/api/makers", makersRouter);
app.use("/api/makersByCategory", makersByCategoryRouter);
app.use("/api/photos", photosRouter);
app.use("/api/financials", financialsRouter);

app.use("/api/library", libraryRouter);

// one controller to rule them all!
// or at least most of the ones for item stuff
app.use("/api/core", coreRouter);

// japanese weapons
// app.use("/api/japanese/weapon/sword", japaneseWeaponSwordRouter);

// japanese armor
app.use("/api/items", japaneseArmorKabutoRouter);
app.use("/api/items", japaneseArmorMempoRouter);
app.use("/api/items", japaneseArmorDoRouter);
app.use("/api/items", japaneseArmorSodeRouter);
app.use("/api/items", japaneseArmorKoteRouter);
app.use("/api/items", japaneseArmorHaidateRouter);
app.use("/api/items", japaneseArmorSuneateRouter);

app.use("/api/weapons", weaponsRouter);
app.use("/api/armor", armorRouter);
app.use("/api/clothing", clothingRouter);
app.use("/api/decor", decorRouter);

// medieval weapons
// app.use("/api/medieval/weapon/sword", europeanWeaponSwordRouter);

// medieval armor

// reports
app.use("/api/reports", reportsRouter);

// wishlist
app.use("/api/wishlist", wishlistRouter);

app.use("/api/photos", express.static(getBasePhotoPath()));

const errorHandling = (err, req: Request, res: Response, next: NextFunction) => {
	console.log(err);

	res.status(500).json({
		msg: err,
		success: false,
	});
};

// app.use(errorHandling);

// console logging for development
// THIS SHOULD CATCH ALL ROUTES IT DOES NOT FIND A MATCH FOR
app.use((req: Request, _res: Response, next: NextFunction) => {
	if (req.url.indexOf(".jpg") === -1) {
		console.log("\n>> MISSING ROUTE:\n\n   url:", req.url, "\n   method:", req.method, "\n   body:", req.body, "\n");
	}
	next();

	return;
});

// listen for requests
app.listen(PORT, () => {
	console.log(`API listening at http://localhost:${PORT}\n\n`);
});
