import type { Express, Request, Response } from "express";
import { createServer, type Server } from "http";
import { setupAuth, hashPassword } from "./auth"; // Add hashPassword import
import { storage } from "./storage";
import multer from "multer";
import path from "path";
import express from 'express';
import { type Sale } from "@shared/schema"; // Add Sale type import

// We won't try to create uploads directory here since it's already handled in index.ts
// The directory handling is better done in the server startup code

// Set up multer for file uploads with detailed logging
const upload = multer({
	storage: multer.diskStorage({
		destination: (req, file, cb) => {
			console.log("📁 Processing file upload, destination: './uploads/'");
			cb(null, './uploads/');
		},
		filename: (req, file, cb) => {
			const isHeadquartersLogo = req.originalUrl === "/api/headquarters/logo";

			if (isHeadquartersLogo) {
				const newFilename = "dei-logo.jpg";
				console.log(`🏢 Fixed filename for headquarters logo: ${newFilename}`);
				cb(null, newFilename);
			} else {
				const newFilename = Date.now() + path.extname(file.originalname);
				console.log(`🆕 Generated filename: ${newFilename}`);
				cb(null, newFilename);
			}
		}
	}),
	fileFilter: (req, file, cb) => {
		const allowedTypes = ['image/jpeg', 'image/png'];
		console.log(`🧪 Checking file type: ${file.mimetype} (${file.originalname})`);
		if (allowedTypes.includes(file.mimetype)) {
			console.log("✅ File type is allowed");
			cb(null, true);
		} else {
			console.error(`⛔ Rejected file type: ${file.mimetype}`);
			cb(new Error(`Unsupported file type: ${file.mimetype}`));
		}
	},
	limits: {
		fileSize: 5 * 1024 * 1024 // 5MB
	}
});


async function requireAuth(req: Request, res: Response, next: Function) {
	if (!req.isAuthenticated()) {
		return res.status(401).json({ message: "Unauthorized" });
	}

	// Check if user's subsidiary is still active
	if (req.user?.subsidiaryId) {
		const subsidiary = await storage.getSubsidiary(req.user.subsidiaryId);
		if (!subsidiary || !subsidiary.status) {
			console.log(`Access denied for user ${req.user.username}: subsidiary is inactive`);
			return res.status(403).json({
				message: "Access denied. Your subsidiary account has been deactivated. Please contact your administrator."
			});
		}
	}

	next();
}

function requireMHCAdmin(req: Request, res: Response, next: Function) {
	if (!req.isAuthenticated() || req.user.role !== "mhc_admin") {
		return res.status(403).json({ message: "Forbidden" });
	}
	next();
}

function requireMHCAdminOrSupervisor(req: Request, res: Response, next: Function) {
	if (!req.isAuthenticated() || (req.user.role !== "mhc_admin" && req.user.role !== "supervisor")) {
		return res.status(403).json({ message: "Forbidden" });
	}
	next();
}

function requireSubsidiaryAccess(req: Request, res: Response, next: Function) {
	if (!req.isAuthenticated()) {
		return res.status(401).json({ message: "Unauthorized" });
	}

	const subsidiaryId = parseInt(req.params.subsidiaryId || req.params.id);
	if (
		req.user?.role !== "mhc_admin" &&
		req.user?.role !== "supervisor" &&
		req.user?.subsidiaryId !== subsidiaryId
	) {
		return res.status(403).json({ message: "Forbidden" });
	}
	next();
}

export function registerRoutes(app: Express): Server {
	setupAuth(app);

	// Ensure uploads directory exists
	app.use(express.static('uploads'));
	app.use(express.json()); //added to handle json body


	// Authentificated User Information Fetching 

	app.get('/api/me', (req, res) => {
		if (!req.isAuthenticated()) {
			return res.status(401).json({ message: "Unauthorized" })
		}
		res.json(req.user);
	})


	// Subsidiary Management
	app.get("/api/subsidiaries", requireAuth, async (req, res) => {
		// If the user is an MHC admin or supervisor, return all subsidiaries
		if (req.user?.role === "mhc_admin" || req.user?.role === "supervisor") {
			const subsidiaries = await storage.listSubsidiaries();
			return res.json(subsidiaries);
		}

		// If not an admin, return only the subsidiary the user belongs to
		if (req.user?.subsidiaryId) {
			const subsidiary = await storage.getSubsidiary(req.user.subsidiaryId);
			return res.json(subsidiary ? [subsidiary] : []);
		}

		// If user has no subsidiary ID, return empty array
		return res.json([]);
	});


	app.post("/api/subsidiaries", requireMHCAdminOrSupervisor, upload.single('logo'), async (req, res) => {
		try {
			console.log("📩 POST /api/subsidiaries triggered");
			console.log("📎 Uploaded file:", req.file);

			const subsidiaryData = {
				name: req.body.name,
				taxId: req.body.taxId,
				email: req.body.email,
				phoneNumber: req.body.phoneNumber,
				address: req.body.address,
				city: req.body.city,
				country: req.body.country,
				status: req.body.status === 'true',
				logo: req.file ? `/uploads/${req.file.filename}` : undefined
			};

			console.log("📦 Parsed subsidiaryData:", subsidiaryData);

			const subsidiary = await storage.createSubsidiary(subsidiaryData);

			await storage.createActivityLog({
				userId: req.user!.id,
				action: "CREATE_SUBSIDIARY",
				details: `Created subsidiary: ${subsidiary.name}`,
				subsidiaryId: subsidiary.id,
			});

			res.status(201).json(subsidiary);
		} catch (error: any) {
			console.error("❌ Error during subsidiary creation:", error.message);
			res.status(400).json({ error: error.message });
		}
	});


	app.patch("/api/subsidiaries/:id", requireAuth, upload.single('logo'), async (req, res) => {
		try {
			const id = parseInt(req.params.id);

			console.log("PATCH request for subsidiary ID:", id);
			console.log("User info:", req.user);

			// Check if the user has access to this subsidiary
			const userRole = req.user?.role;
			const userSubsidiaryId = req.user?.subsidiaryId;

			const isAdmin = userRole === 'mhc_admin';
			const isSupervisor = userRole === 'supervisor';
			const isSubsidiaryAdmin = userRole === 'subsidiary_admin' && userSubsidiaryId === id;

			console.log("User role:", userRole);
			console.log("User subsidiary ID:", userSubsidiaryId);
			console.log("Is admin:", isAdmin);
			console.log("Is supervisor:", isSupervisor);
			console.log("Is subsidiary admin:", isSubsidiaryAdmin);

			if (!isAdmin && !isSupervisor && !isSubsidiaryAdmin) {
				return res.status(403).json({ message: 'Unauthorized to update this subsidiary' });
			}

			// Direct access to file since multer middleware already processed it
			console.log("Multer middleware processed the request");
			console.log("Request body:", req.body);
			console.log("File:", req.file);

			const updateData: any = {};

			// Extract fields from request body
			if (req.body.name) updateData.name = req.body.name;
			if (req.body.taxId) updateData.taxId = req.body.taxId;
			if (req.body.email) updateData.email = req.body.email;
			if (req.body.phoneNumber) updateData.phoneNumber = req.body.phoneNumber;
			if (req.body.address) updateData.address = req.body.address;
			if (req.body.city) updateData.city = req.body.city;
			if (req.body.country) updateData.country = req.body.country;
			if (req.body.receiptSlogan) updateData.receiptSlogan = req.body.receiptSlogan;
			// Only MHC admin can change subsidiary status
			if (typeof req.body.status !== 'undefined' && userRole === 'mhc_admin') {
				updateData.status = req.body.status === 'true' || req.body.status === true;
			}

			// If a logo file was uploaded, add its path
			if (req.file) {
				updateData.logo = `/uploads/${req.file.filename}`;
				console.log("Logo file uploaded, path:", updateData.logo);
			}
			console.log("Update data to be sent to database:", updateData);

			// Update the subsidiary in the database
			const subsidiary = await storage.updateSubsidiary(id, updateData);
			console.log("Updated subsidiary:", subsidiary);

			// Log activity
			await storage.createActivityLog({
				userId: req.user!.id,
				action: "UPDATE_SUBSIDIARY",
				details: `Updated subsidiary: ${subsidiary.name}`,
				subsidiaryId: subsidiary.id,
			});

			// Return the updated subsidiary data
			res.json(subsidiary);
		} catch (error: any) {
			console.error("Error updating subsidiary:", error);
			res.status(400).json({ message: error.message });
		}
	});

	// Add this after the existing subsidiary routes
	app.get("/api/subsidiaries/:id", requireSubsidiaryAccess, async (req, res) => {
		const subsidiary = await storage.getSubsidiary(parseInt(req.params.id));
		if (!subsidiary) {
			return res.status(404).json({ message: "Subsidiary not found" });
		}
		res.json(subsidiary);
	});

	// Inventory Management
	app.get(
		"/api/subsidiaries/:subsidiaryId/inventory",
		requireSubsidiaryAccess,
		async (req, res) => {
			const inventory = await storage.listInventoryBySubsidiary(
				parseInt(req.params.subsidiaryId),
			);
			res.json(inventory);
		},
	);

	app.post(
		"/api/subsidiaries/:subsidiaryId/inventory",
		requireSubsidiaryAccess,
		async (req, res) => {
			try {
				const inventory = await storage.createInventory({
					...req.body,
					subsidiaryId: parseInt(req.params.subsidiaryId),
				});

				// Log the activity
				await storage.createActivityLog({
					userId: req.user!.id,
					action: "CREATE_INVENTORY",
					details: `Created inventory item: ${inventory.name} with quantity ${inventory.quantity}`,
					subsidiaryId: parseInt(req.params.subsidiaryId),
				});

				res.status(201).json(inventory);
			} catch (error: any) {
				res.status(400).json({ error: error.message });
			}
		},
	);

	app.patch(
		"/api/subsidiaries/:subsidiaryId/inventory/:id",
		requireSubsidiaryAccess,
		async (req, res) => {
			try {
				const oldInventory = await storage.getInventory(parseInt(req.params.id));
				const inventory = await storage.updateInventory(
					parseInt(req.params.id),
					req.body,
				);

				// Log the activity
				await storage.createActivityLog({
					userId: req.user!.id,
					action: "UPDATE_INVENTORY",
					details: `Updated inventory item: ${inventory.name} - Quantity changed from ${oldInventory?.quantity || 0} to ${inventory.quantity}`,
					subsidiaryId: parseInt(req.params.subsidiaryId),
				});

				res.json(inventory);
			} catch (error: any) {
				res.status(400).json({ error: error.message });
			}
		},
	);

	app.delete(
		"/api/subsidiaries/:subsidiaryId/inventory/:id",
		requireSubsidiaryAccess,
		async (req, res) => {
			try {
				// Supervisors cannot delete inventory items
				if (req.user?.role === "supervisor") {
					return res.status(403).json({ message: "Supervisors cannot delete inventory items" });
				}

				const inventory = await storage.getInventory(parseInt(req.params.id));
				await storage.deleteInventory(parseInt(req.params.id));

				// Log the activity
				await storage.createActivityLog({
					userId: req.user!.id,
					action: "DELETE_INVENTORY",
					details: `Deleted inventory item: ${inventory?.name}`,
					subsidiaryId: parseInt(req.params.subsidiaryId),
				});

				res.sendStatus(204);
			} catch (error: any) {
				res.status(400).json({ error: error.message });
			}
		},
	);

	// Sales Management
	app.post(
		"/api/subsidiaries/:subsidiaryId/sales",
		requireSubsidiaryAccess,
		async (req, res) => {
			try {
				console.log("Sales request body:", req.body);

				const subsidiaryId = parseInt(req.params.subsidiaryId);
				const userId = req.user!.id;

				const {
					itemId,
					quantity,
					salePrice,
					clientName,
					nifNumber,
					ninNumber,
					...rest
				} = req.body;

				// ✅ Server-side validation: require either clientName or nifNumber
				if ((!clientName || clientName.trim() === "") && (!nifNumber || nifNumber.trim() === "")) {
					return res.status(400).json({
						error: "Client name or NIF number must be provided.",
					});
				}

				const saleData = {
					...rest,
					itemId: parseInt(itemId),
					quantity: parseInt(quantity),
					salePrice: parseFloat(salePrice),
					subsidiaryId,
					userId,
					clientName,
					nifNumber,
					ninNumber,
				};

				console.log("Processed sale data:", saleData);

				const sale = await storage.createSale(saleData);

				await storage.createActivityLog({
					userId,
					action: "CREATE_SALE",
					details: `Created sale: ${sale.quantity} items at $${sale.salePrice}`,
					subsidiaryId,
				});

				res.status(201).json(sale);
			} catch (error: any) {
				console.error("Sale creation error:", error);
				res.status(400).json({ error: error.message });
			}
		}
	);




	app.get(
		"/api/subsidiaries/:subsidiaryId/sales",
		requireSubsidiaryAccess,
		async (req, res) => {
			try {
				const subsidiaryId = parseInt(req.params.subsidiaryId);
				const { startDate, endDate } = req.query;

				let sales;

				// ✅ If date range is provided, use it
				if (startDate && endDate) {
					console.log(`Filtering sales by date range: ${startDate} to ${endDate}`);
					const startDateTime = new Date(startDate as string);
					const endDateTime = new Date(endDate as string);

					// Validate dates
					if (isNaN(startDateTime.getTime()) || isNaN(endDateTime.getTime())) {
						return res.status(400).json({
							error: "Invalid date format. Use ISO format (YYYY-MM-DDTHH:mm:ss.sssZ)",
						});
					}

					sales = await storage.listSalesByDateRange(
						subsidiaryId,
						startDateTime,
						endDateTime
					);
				} else {
					// ✅ No date range: show only today's sales
					const today = new Date();
					today.setHours(0, 0, 0, 0);

					const tomorrow = new Date(today);
					tomorrow.setDate(today.getDate() + 1);




					sales = await storage.listSalesByDateRange(
						subsidiaryId,
						today,
						tomorrow
					);
				}

				// Enrich sales with item and seller info
				const salesWithItemDetails = await Promise.all(
					sales.map(async (sale) => {
						const item = await storage.getInventory(sale.itemId);
						const seller = await storage.getUser(sale.userId);
						return {
							...sale,
							itemName: item?.name || "Unknown Item",
							itemSku: item?.sku || "",
							itemCategory: item?.category || "",
							sellerName: seller?.username || "Unknown",
						};
					})
				);

				res.json(salesWithItemDetails);
			} catch (error: any) {
				console.error("Error fetching sales:", error);
				res.status(500).json({ error: error.message });
			}
		}
	);


	// Receipt search endpoint
	app.get("/api/subsidiaries/:subsidiaryId/sales/search", requireSubsidiaryAccess, async (req, res) => {
		try {
			const subsidiaryId = parseInt(req.params.subsidiaryId);
			const receiptNumber = req.query.receiptNumber as string;

			if (!receiptNumber) {
				return res.status(400).json({ error: "Receipt number is required" });
			}

			// Parse receipt number by removing leading zeros and converting to integer
			// This handles both formatted (00000002) and raw (2) inputs
			const saleId = parseInt(receiptNumber.replace(/^0+/, '') || '0');

			if (isNaN(saleId)) {
				return res.status(400).json({ error: "Invalid receipt number format" });
			}

			// Get the sale by ID for the current subsidiary
			const sales = await storage.listSalesBySubsidiary(subsidiaryId);
			const sale = sales.find(s => s.id === saleId);

			if (!sale) {
				return res.status(404).json({ error: "Receipt not found" });
			}

			res.json(sale);
		} catch (error: any) {
			res.status(500).json({ error: error.message });
		}
	});

	// Delete sale/receipt - only for subsidiary_admin
	app.delete(
		"/api/subsidiaries/:subsidiaryId/sales/:saleId",
		requireSubsidiaryAccess,
		async (req, res) => {
			try {
				// Check if user is subsidiary admin
				if (req.user.role !== "supervisor" && req.user.role !== "mhc_admin") {
					return res.status(403).json({ error: "Only supervisors or MHC admins can delete sales" });
				}


				const subsidiaryId = parseInt(req.params.subsidiaryId);
				const saleId = parseInt(req.params.saleId);

				// Get all sales for this subsidiary 
				const subsidiarySales = await storage.listSalesBySubsidiary(subsidiaryId);

				// Find the specific sale to check it belongs to this subsidiary
				const sale = subsidiarySales.find(s => s.id === saleId);

				if (!sale) {
					return res.status(404).json({ error: `Sale with ID ${saleId} not found` });
				}

				// Delete the sale (this method already includes activity logging and inventory restoration)
				await storage.deleteSale(saleId);

				res.status(200).json({ message: "Sale deleted successfully" });
			} catch (error: any) {
				console.error("Error deleting sale:", error);
				res.status(500).json({ error: error.message });
			}
		}
	);

	// Add after existing sales routes
	app.get("/api/sales", requireMHCAdminOrSupervisor, async (req, res) => {
		const subsidiaries = await storage.listSubsidiaries();
		let allSales: Sale[] = [];

		// Gather sales from all subsidiaries
		for (const subsidiary of subsidiaries) {
			const subsidiarySales = await storage.listSalesBySubsidiary(subsidiary.id);
			allSales = [...allSales, ...subsidiarySales];
		}

		res.json(allSales);
	});

	app.get("/api/sales/donut", requireMHCAdminOrSupervisor, async (req, res) => {
		const subsidiaries = await storage.listSubsidiaries();
		const results = [];

		for (const subsidiary of subsidiaries) {
			const sales = await storage.listSalesBySubsidiary(subsidiary.id);

			const total = sales.reduce((sum, sale) => sum + sale.salePrice, 0);
			const count = sales.length;

			results.push({
				name: subsidiary.name,
				count,
				total,
			});
		}

		res.json(results);
	});



	// Add route to get total inventory count
	app.get("/api/inventory/total", requireMHCAdminOrSupervisor, async (req, res) => {
		const subsidiaries = await storage.listSubsidiaries();
		let totalProducts = 0;

		// Count inventory items across all subsidiaries
		for (const subsidiary of subsidiaries) {
			const subsidiaryInventory = await storage.listInventoryBySubsidiary(subsidiary.id);
			totalProducts += subsidiaryInventory.length;
		}

		res.json({ totalProducts });
	});

	// Delete subsidiary route - only for MHC admin
	app.delete("/api/subsidiaries/:id", requireMHCAdmin, async (req, res) => {
		try {
			const id = parseInt(req.params.id);

			// Get subsidiary info for logging before deletion
			const subsidiary = await storage.getSubsidiary(id);
			if (!subsidiary) {
				return res.status(404).json({ error: "Subsidiary not found" });
			}

			// Check if subsidiary has any users
			const subsidiaryUsers = await storage.listUsersBySubsidiary(id);
			if (subsidiaryUsers.length > 0) {
				return res.status(400).json({
					error: `Cannot delete subsidiary "${subsidiary.name}". There are ${subsidiaryUsers.length} user(s) still associated with this office. Please reassign or remove all users before deleting the subsidiary.`
				});
			}

			// Check if subsidiary has any sales/transactions
			const subsidiarySales = await storage.listSalesBySubsidiary(id);
			if (subsidiarySales.length > 0) {
				return res.status(400).json({
					error: `Cannot delete subsidiary "${subsidiary.name}". There are ${subsidiarySales.length} transaction(s) recorded for this office. Subsidiaries with transaction history cannot be deleted for audit purposes.`
				});
			}

			// Check if subsidiary has any inventory items
			const subsidiaryInventory = await storage.listInventoryBySubsidiary(id);
			if (subsidiaryInventory.length > 0) {
				return res.status(400).json({
					error: `Cannot delete subsidiary "${subsidiary.name}". There are ${subsidiaryInventory.length} inventory item(s) still in this office. Please remove all inventory items before deleting the subsidiary.`
				});
			}

			// If no activity, proceed with deletion
			await storage.deleteSubsidiary(id);

			// Log the activity
			await storage.createActivityLog({
				userId: req.user!.id,
				action: "DELETE_SUBSIDIARY",
				details: JSON.stringify({
					subsidiaryName: subsidiary.name,
					subsidiaryId: id,
					taxId: subsidiary.taxId,
					email: subsidiary.email,
					phoneNumber: subsidiary.phoneNumber,
					address: subsidiary.address,
					city: subsidiary.city,
					country: subsidiary.country,
					deletionReason: "No activity (users, transactions, or inventory) found",
					deletedAt: new Date().toISOString()
				}),
			});

			res.sendStatus(204);
		} catch (error: any) {
			console.error("Error deleting subsidiary:", error);
			res.status(400).json({ error: error.message });
		}
	});

	// User Management for Subsidiaries
	app.get(
		"/api/subsidiaries/:subsidiaryId/users",
		requireSubsidiaryAccess,
		async (req, res) => {
			// Allow any user with subsidiary access to view users 
			// This includes MHC admins, subsidiary admins, and staff members of the subsidiary
			const subsidiaryId = parseInt(req.params.subsidiaryId);
			const users = await storage.listUsersBySubsidiary(subsidiaryId);
			res.json(users);
		}
	);

	app.post(
		"/api/subsidiaries/:subsidiaryId/users",
		requireSubsidiaryAccess,
		async (req, res) => {
			if (req.user?.role !== "subsidiary_admin") {
				return res.status(403).json({ message: "Only subsidiary admins can create users" });
			}

			const subsidiaryId = parseInt(req.params.subsidiaryId);

			// Verify the subsidiary admin is creating a user for their own subsidiary
			if (req.user.subsidiaryId !== subsidiaryId) {
				return res.status(403).json({ message: "Can only create users for your own subsidiary" });
			}

			try {
				// Check if username already exists
				const existingUser = await storage.getUserByUsername(req.body.username);
				if (existingUser) {
					return res.status(400).json({ error: "Username already exists" });
				}

				const hashedPassword = await hashPassword(req.body.password);
				const user = await storage.createUser({
					username: req.body.username,
					password: hashedPassword,
					subsidiaryId,
					role: "staff", // Always create as staff for subsidiary admins
				});

				// Log the activity
				await storage.createActivityLog({
					userId: req.user.id,
					action: "CREATE_USER",
					details: `Created user: ${user.username}`,
					subsidiaryId: subsidiaryId,
				});

				res.status(201).json(user);
			} catch (error: any) {
				res.status(400).json({ error: error.message });
			}
		}
	);

	// Add these routes after the existing user management routes
	app.patch(
		"/api/subsidiaries/:subsidiaryId/users/:userId",
		requireSubsidiaryAccess,
		async (req, res) => {
			if (req.user?.role !== "subsidiary_admin") {
				return res.status(403).json({ message: "Only subsidiary admins can modify users" });
			}

			const subsidiaryId = parseInt(req.params.subsidiaryId);
			const userId = parseInt(req.params.userId);

			try {
				// Verify user belongs to this subsidiary
				const user = await storage.getUser(userId);
				if (!user || user.subsidiaryId !== subsidiaryId) {
					return res.status(404).json({ message: "User not found" });
				}

				// If password is being updated, hash it
				const updates = { ...req.body };
				if (updates.password) {
					updates.password = await hashPassword(updates.password);
				}

				const updatedUser = await storage.updateUser(userId, updates);
				res.json(updatedUser);
			} catch (error: any) {
				res.status(400).json({ error: error.message });
			}
		}
	);

	app.delete(
		"/api/subsidiaries/:subsidiaryId/users/:userId",
		requireSubsidiaryAccess,
		async (req, res) => {
			if (req.user?.role !== "subsidiary_admin") {
				return res.status(403).json({ message: "Only subsidiary admins can delete users" });
			}

			const subsidiaryId = parseInt(req.params.subsidiaryId);
			const userId = parseInt(req.params.userId);

			try {
				// Verify user belongs to this subsidiary
				const user = await storage.getUser(userId);
				if (!user || user.subsidiaryId !== subsidiaryId) {
					return res.status(404).json({ message: "User not found" });
				}

				await storage.deleteUser(userId);
				res.sendStatus(204);
			} catch (error: any) {
				res.status(400).json({ error: error.message });
			}
		}
	);

	// Activity Logs
	app.get("/api/activity-logs", requireAuth, async (req, res) => {
		// Only pass a subsidiaryId if the user is not an MHC admin or supervisor and has a subsidiaryId
		const subsidiaryId = (req.user?.role === "mhc_admin" || req.user?.role === "supervisor") ?
			undefined :
			(req.user?.subsidiaryId || undefined);

		const logs = await storage.listActivityLogs(subsidiaryId);
		res.json(logs);
	});

	// Add endpoint for creating activity logs for a subsidiary
	app.post("/api/subsidiaries/:subsidiaryId/activity-logs", requireSubsidiaryAccess, async (req, res) => {
		try {
			const subsidiaryId = parseInt(req.params.subsidiaryId);

			// Create the activity log
			// Ensure timestamp is a Date object
			const timestamp = req.body.timestamp ? new Date(req.body.timestamp) : new Date();

			const logData = {
				...req.body,
				subsidiaryId,
				timestamp, // Use the Date object version
			};


			const log = await storage.createActivityLog(logData);
			res.json(log);
		} catch (error: any) {
			console.error("Error creating activity log:", error);
			res.status(400).json({ error: error.message });
		}
	});

	// Add this route after the existing user management routes
	app.get("/api/users", requireMHCAdminOrSupervisor, async (req, res) => {
		try {
			const users = await storage.listUsers();

			// If the user is a supervisor, filter to only show subsidiary_admin and staff
			if (req.user?.role === "supervisor") {
				const filteredUsers = users.filter(user =>
					user.role === "subsidiary_admin" || user.role === "staff"
				);
				return res.json(filteredUsers);
			}

			// MHC admins can see all users
			res.json(users);
		} catch (error: any) {
			res.status(400).json({ error: error.message });
		}
	});

	// Create subsidiary admin by MHC admin or supervisor (with restrictions)
	app.post("/api/users", requireMHCAdminOrSupervisor, async (req, res) => {
		try {
			// Check if username already exists
			const existingUser = await storage.getUserByUsername(req.body.username);
			if (existingUser) {
				return res.status(400).json({ error: "Username already exists" });
			}

			// Validate subsidiary exists if assigning to one
			if (req.body.subsidiaryId) {
				const subsidiary = await storage.getSubsidiary(req.body.subsidiaryId);
				if (!subsidiary) {
					return res.status(400).json({ error: "Subsidiary not found" });
				}
			}

			// Supervisors cannot create other supervisors or MHC admins
			const requestedRole = req.body.role || "subsidiary_admin";
			if (req.user?.role === "supervisor") {
				if (requestedRole === "supervisor" || requestedRole === "mhc_admin") {
					return res.status(403).json({ error: "Supervisors cannot create supervisor or MHC admin accounts" });
				}
				// Ensure supervisors can only create subsidiary_admin and staff roles
				if (requestedRole !== "subsidiary_admin" && requestedRole !== "staff") {
					return res.status(403).json({ error: "Supervisors can only create subsidiary_admin and staff accounts" });
				}
			}

			const hashedPassword = await hashPassword(req.body.password);

			// Auto-assign DEA Headquarter for supervisor role
			let assignedSubsidiaryId = req.body.subsidiaryId || null;
			if (requestedRole === "supervisor") {
				const subsidiaries = await storage.listSubsidiaries();
				const deaHeadquarter = subsidiaries.find(sub => sub.name === "DEA Headquarter");
				if (deaHeadquarter) {
					assignedSubsidiaryId = deaHeadquarter.id;
				}
			}

			const user = await storage.createUser({
				username: req.body.username,
				password: hashedPassword,
				role: requestedRole,
				subsidiaryId: assignedSubsidiaryId,
			});

			// Log the activity
			await storage.createActivityLog({
				userId: req.user!.id,
				action: "CREATE_USER",
				details: `Created user: ${user.username} with role: ${user.role}`,
				subsidiaryId: req.body.subsidiaryId || undefined,
			});

			res.status(201).json(user);
		} catch (error: any) {
			res.status(400).json({ error: error.message });
		}
	});

	// Update user by MHC admin or supervisor (with restrictions)
	app.patch("/api/users/:userId", requireMHCAdminOrSupervisor, async (req, res) => {
		try {
			const userId = parseInt(req.params.userId);

			// Get existing user
			const existingUser = await storage.getUser(userId);
			if (!existingUser) {
				return res.status(404).json({ error: "User not found" });
			}

			// Supervisors cannot modify supervisor or mhc_admin users at all
			if (req.user?.role === "supervisor" && (existingUser.role === "supervisor" || existingUser.role === "mhc_admin")) {
				return res.status(403).json({ error: "Supervisors cannot modify supervisor or MHC admin accounts" });
			}

			// Check if new username already exists (if changing username)
			if (req.body.username && req.body.username !== existingUser.username) {
				const userWithSameUsername = await storage.getUserByUsername(req.body.username);
				if (userWithSameUsername) {
					return res.status(400).json({ error: "Username already exists" });
				}
			}

			// Validate subsidiary exists if assigning to one
			if (req.body.subsidiaryId) {
				const subsidiary = await storage.getSubsidiary(req.body.subsidiaryId);
				if (!subsidiary) {
					return res.status(400).json({ error: "Subsidiary not found" });
				}
			}

			// Prepare update data with supervisor restrictions
			const updates: any = {};
			if (req.body.username) updates.username = req.body.username;

			// Role updates
			if (req.body.role) {
				if (req.user?.role === "supervisor") {
					// Supervisors can only update subsidiary_admin and staff roles
					if (req.body.role !== "subsidiary_admin" && req.body.role !== "staff") {
						return res.status(403).json({ error: "Supervisors can only update users to subsidiary_admin or staff roles" });
					}
				}
				updates.role = req.body.role;
			}

			// Handle subsidiary assignment with auto-assignment for supervisor role
			if (req.body.subsidiaryId !== undefined) {
				updates.subsidiaryId = req.body.subsidiaryId;
			}

			// Auto-assign DEA Headquarter for supervisor role
			if (updates.role === "supervisor") {
				const subsidiaries = await storage.listSubsidiaries();
				const deaHeadquarter = subsidiaries.find(sub => sub.name === "DEA Headquarter");
				if (deaHeadquarter) {
					updates.subsidiaryId = deaHeadquarter.id;
				}
			}

			// Status updates (only MHC admins can update status)
			if (req.body.status !== undefined) {
				if (req.user?.role !== "mhc_admin") {
					return res.status(403).json({ error: "Only MHC administrators can update user status" });
				}
				updates.status = req.body.status;
			}

			// Hash password if provided
			if (req.body.password) {
				updates.password = await hashPassword(req.body.password);
			}

			const updatedUser = await storage.updateUser(userId, updates);

			// Log the activity
			await storage.createActivityLog({
				userId: req.user!.id,
				action: "UPDATE_USER",
				details: `Updated user: ${updatedUser.username}`,
				subsidiaryId: updatedUser.subsidiaryId || undefined,
			});

			res.json(updatedUser);
		} catch (error: any) {
			res.status(400).json({ error: error.message });
		}
	});

	// Delete user by MHC admin only (supervisors cannot delete users)
	app.delete("/api/users/:userId", requireMHCAdmin, async (req, res) => {
		try {
			const userId = parseInt(req.params.userId);

			// Get user to be deleted for logging
			const userToDelete = await storage.getUser(userId);
			if (!userToDelete) {
				return res.status(404).json({ error: "User not found" });
			}

			// Prevent self-deletion
			if (userId === req.user!.id) {
				return res.status(400).json({ error: "Cannot delete your own account" });
			}

			await storage.deleteUser(userId);

			// Log the activity
			await storage.createActivityLog({
				userId: req.user!.id,
				action: "DELETE_USER",
				details: `Deleted user: ${userToDelete.username}`,
				subsidiaryId: userToDelete.subsidiaryId || undefined,
			});

			res.sendStatus(204);
		} catch (error: any) {
			res.status(400).json({ error: error.message });
		}
	});

	// Global Settings Endpoints
	app.get("/api/global-settings/:key", requireAuth, async (req, res) => {
		try {
			const { key } = req.params;
			const setting = await storage.getGlobalSetting(key);
			if (setting) {
				res.json(setting);
			} else {
				res.status(404).json({ message: "Setting not found" });
			}
		} catch (error: any) {
			res.status(400).json({ error: error.message });
		}
	});

	app.post("/api/global-settings", requireMHCAdmin, async (req, res) => {
		try {
			const { key, value, description } = req.body;
			const setting = await storage.upsertGlobalSetting({ key, value, description });
			res.json(setting);
		} catch (error: any) {
			res.status(400).json({ error: error.message });
		}
	});

	// DIE Headquarters Logo Upload
	app.post("/api/headquarters/logo", requireMHCAdmin, upload.single('logo'), async (req, res) => {
		try {
			if (!req.file) {
				return res.status(400).json({ message: "No file uploaded" });
			}

			const logoPath = `/uploads/${req.file.filename}`;
			const setting = await storage.upsertGlobalSetting({
				key: "headquarters_logo",
				value: logoPath,
				description: "DIE Headquarters Logo"
			});

			// Log the activity
			await storage.createActivityLog({
				userId: req.user!.id,
				action: "UPDATE_HEADQUARTERS_LOGO",
				details: `Updated DIE Headquarters logo`,
			});

			res.json({
				success: true,
				message: "Logo uploaded successfully",
				logoPath: logoPath
			});
		} catch (error: any) {
			console.error("Error uploading headquarters logo:", error);
			res.status(400).json({ error: error.message });
		}
	});


	app.get("/api/reports/:type", requireMHCAdminOrSupervisor, async (req, res) => {
		const { type } = req.params;
		const { format = 'json', timeRange, startDate, endDate } = req.query;

		try {
			let data;
			const now = new Date();
			let startDateTime = new Date();

			// Calculate start date based on parameters
			if (startDate && endDate) {
				// Custom date range
				const start = new Date(startDate as string);
				start.setHours(0, 0, 0, 0);

				const end = new Date(endDate as string);
				end.setHours(23, 59, 59, 999);

				startDateTime = start;
				now.setTime(end.getTime());
			} else {
				// Predefined ranges
				switch (timeRange) {
					case 'day':
						// Set start date to beginning of today
						startDateTime.setHours(0, 0, 0, 0);
						break;
					case 'week':
						startDateTime.setDate(now.getDate() - 7);
						break;
					case 'month':
						startDateTime.setMonth(now.getMonth() - 1);
						break;
					case 'year':
						startDateTime.setFullYear(now.getFullYear() - 1);
						break;
					default:
						startDateTime.setMonth(now.getMonth() - 1); // Default to last month
				}
				// Set end date to end of current day
				now.setHours(23, 59, 59, 999);
			}

			// Gather data based on report type
			switch (type) {
				case 'sales': {
					// Get all subsidiaries and their sales
					const subsidiaries = await storage.listSubsidiaries();
					let allSales: Sale[] = [];
					const users = await storage.listUsers();

					// Get all inventory items from all subsidiaries
					let allInventory: any[] = [];
					for (const subsidiary of subsidiaries) {
						const subsidiaryInventory = await storage.listInventoryBySubsidiary(subsidiary.id);
						allInventory = [...allInventory, ...subsidiaryInventory];
					}

					for (const subsidiary of subsidiaries) {
						const subsidiarySales = await storage.listSalesBySubsidiary(subsidiary.id);
						allSales = [...allSales, ...subsidiarySales];
					}

					// Filter by date and format data
					data = allSales
						.filter(sale => {
							const saleDate = new Date(sale.timestamp);
							return saleDate >= startDateTime && saleDate <= now;
						})
						.map(sale => {
							const subsidiary = subsidiaries.find(s => s.id === sale.subsidiaryId);
							const user = users.find(u => u.id === sale.userId);
							const item = allInventory.find(i => i.id === sale.itemId);

							// Format customer name
							let customerName = 'N/A';
							if (sale.clientName || sale.clientLastName) {
								const firstName = sale.clientName || '';
								const lastName = sale.clientLastName || '';
								customerName = `${firstName} ${lastName}`.trim();
							}

							return {
								Date: new Date(sale.timestamp).toLocaleDateString(),
								'Subsidiary': subsidiary?.name || 'Unknown',
								'Sold By': user?.username || 'Unknown',
								'Customer': customerName,
								'Quantity': sale.quantity,
								'Item Name': item?.name || 'Unknown Item',
								'Sale Price': `$${sale.salePrice.toFixed(2)}`,
								'Total': `$${(sale.quantity * sale.salePrice).toFixed(2)}`
							};
						});
					break;
				}
				case 'inventory': {
					// Get current inventory status for all subsidiaries
					const subsidiaries = await storage.listSubsidiaries();
					const inventoryPromises = subsidiaries.map(async subsidiary => {
						const items = await storage.listInventoryBySubsidiary(subsidiary.id);
						return items.map(item => ({
							'Subsidiary': subsidiary.name,
							'Product Name': item.name,
							'SKU': item.sku,
							'Quantity': item.quantity,
							'Sale Price': `$${item.salePrice.toFixed(2)}`,
							'Total Value': `${(item.quantity * item.salePrice).toFixed(2)}`
						}));
					});

					data = (await Promise.all(inventoryPromises)).flat();
					break;
				}
				case 'activity': {
					// Get activity logs with user and subsidiary details
					const logs = await storage.listActivityLogs();
					const subsidiaries = await storage.listSubsidiaries();
					const users = await storage.listUsers();

					data = logs
						.filter(log => {
							const logDate = new Date(log.timestamp);
							return logDate >= startDateTime && logDate <= now;
						})
						.map(log => {
							const subsidiary = subsidiaries.find(s => s.id === log.subsidiaryId);
							const user = users.find(u => u.id === log.userId);
							return {
								Date: new Date(log.timestamp).toLocaleDateString(),
								'Subsidiary': subsidiary?.name || 'MHC',
								'User': user?.username || 'System',
								'Action': log.action,
								'Details': log.details
							};
						});
					break;
				}
				default:
					return res.status(400).json({ message: "Invalid report type" });
			}

			// Format and send response based on requested format
			if (format === 'csv') {
				const csv = convertToCSV(data);
				res.header('Content-Type', 'text/csv');
				res.attachment(`${type}-report-${timeRange || 'custom'}.csv`);
				return res.send(csv);
			} else if (format === 'pdf') {
				// Create an HTML document that looks like a PDF report
				const html = `
					<!DOCTYPE html>
					<html>
					<head>
						<meta charset="UTF-8">
						<title>${type.charAt(0).toUpperCase() + type.slice(1)} Report</title>
						<style>
							body {
								font-family: Arial, sans-serif;
								line-height: 1.6;
								margin: 40px;
							}
							.header {
								text-align: center;
								margin-bottom: 30px;
							}
							.report-title {
								font-size: 24px;
								font-weight: bold;
								margin-bottom: 10px;
							}
							.metadata {
								color: #666;
								margin-bottom: 20px;
							}
							table {
								width: 100%;
								border-collapse: collapse;
								margin-top: 20px;
							}
							th, td {
								border: 1px solid #ddd;
								padding: 12px;
								text-align: left;
							}
							th {
								background-color: #f5f5f5;
							}
							.summary {
								margin: 20px 0;
								padding: 15px;
								background: #f9f9f9;
								border-radius: 4px;
							}
							@media print {
								body { margin: 0; }
								.header { margin-top: 0; }
							}
						</style>
					</head>
					<body>
						<div class="header">
							<div class="report-title">${type.charAt(0).toUpperCase() + type.slice(1)} Report</div>
							<div class="metadata">
								Generated on ${new Date().toLocaleDateString()}<br>
								Time Range: ${timeRange === 'custom'
						? `${startDateTime.toLocaleDateString()} to ${now.toLocaleDateString()}`
						: timeRange === 'day' ? 'Today'
							: timeRange === 'week' ? 'Last Week'
								: timeRange === 'month' ? 'Last Month'
									: timeRange === 'year' ? 'Last Year' : timeRange}
							</div>
						</div>

						<div class="summary">
							<strong>Summary:</strong><br>
							Total Records: ${data.length}<br>
							Date Range: ${startDateTime.toLocaleDateString()} - ${now.toLocaleDateString()}
						</div>

						<table>
							<thead>
								<tr>
									${Object.keys(data[0] || {}).map(header => `<th>${header}</th>`).join('')}
								</tr>
							</thead>
							<tbody>
								${data.map(row => `
									<tr>
										${Object.values(row).map(value => `<td>${value}</td>`).join('')}
									</tr>
								`).join('')}
							</tbody>
						</table>
					</body>
					</html>
				`;

				res.header('Content-Type', 'text/html');
				res.attachment(`${type}-report-${timeRange || 'custom'}.html`);
				return res.send(html);

			} else {
				// JSON format for preview
				res.json(data);
			}
		} catch (error: any) {
			res.status(500).json({ message: error.message });
		}
	});

	// Helper function to convert data to CSV format
	function convertToCSV(data: any[]) {
		if (data.length === 0) return '';

		const headers = Object.keys(data[0]);
		const rows = data.map(obj =>
			headers.map(header => {
				const value = obj[header];
				// Handle values that might contain commas
				return typeof value === 'string' && value.includes(',')
					? `"${value}"`
					: value;
			})
		);

		return [
			headers.join(','),
			...rows.map(row => row.join(','))
		].join('\n');
	}

	// Database Configuration API
	app.get("/api/config/database", requireMHCAdmin, (req, res) => {
		try {
			// Read from the configuration file directly using import
			import('../db.config.mjs')
				.then(config => {
					// Send the config to the client
					res.json({
						engine: config.default.engine,
						postgresql: {
							host: config.default.postgresql.host,
							port: String(config.default.postgresql.port),
							database: config.default.postgresql.database,
							user: config.default.postgresql.user,
						},
						mysql: {
							host: config.default.mysql.host,
							port: String(config.default.mysql.port),
							database: config.default.mysql.database,
							user: config.default.mysql.user,
						}
					});
				})
				.catch(err => {
					console.error("Error importing database config:", err);
					res.status(500).json({ message: "Failed to import database configuration", error: err.message });
				});
		} catch (error: any) {
			console.error("Error in database config endpoint:", error);
			res.status(500).json({ message: "Failed to read database configuration", error: error.message });
		}
	});

	app.post("/api/config/database", requireMHCAdmin, (req, res) => {
		try {
			const { engine, postgresql, mysql } = req.body;

			// Validate engine type
			if (engine !== 'postgresql' && engine !== 'mysql') {
				return res.status(400).json({ message: "Invalid database engine. Must be 'postgresql' or 'mysql'" });
			}

			// Update the configuration file with a complete replacement
			const fs = require('fs');
			const path = require('path');
			const configPath = path.resolve(process.cwd(), 'db.config.mjs');

			// Create a new config file content
			const newConfig = `// Database Configuration
// Change 'engine' to switch between 'postgresql' or 'mysql'

export default {
  engine: '${engine}', // Options: 'postgresql' or 'mysql'
  
  // MySQL-specific configuration (used when engine is 'mysql')
  mysql: {
    host: process.env.MYSQL_HOST || '${mysql?.host || 'localhost'}',
    port: parseInt(process.env.MYSQL_PORT || '${mysql?.port || '3306'}'),
    user: process.env.MYSQL_USER || '${mysql?.user || 'root'}',
    password: process.env.MYSQL_PASSWORD || '',
    database: process.env.MYSQL_DATABASE || '${mysql?.database || 'subsidiary_management'}',
  },
  
  // PostgreSQL-specific configuration (used when engine is 'postgresql')
  // This will use DATABASE_URL if available, otherwise fall back to individual settings
  postgresql: {
    // These are used if DATABASE_URL is not available
    host: process.env.PGHOST || '${postgresql?.host || 'localhost'}',
    port: parseInt(process.env.PGPORT || '${postgresql?.port || '5432'}'),
    user: process.env.PGUSER || '${postgresql?.user || 'postgres'}',
    password: process.env.PGPASSWORD || '',
    database: process.env.PGDATABASE || '${postgresql?.database || 'postgres'}',
  }
};`;

			fs.writeFileSync(configPath, newConfig);

			// Log the change for diagnostics
			console.log(`Database configuration updated to engine: ${engine}`);

			res.json({
				message: "Database configuration updated successfully",
				note: "Server restart required for changes to take effect",
				engine
			});
		} catch (error: any) {
			console.error("Error updating database config:", error);
			res.status(500).json({ message: "Failed to update database configuration", error: error.message });
		}
	});

	const httpServer = createServer(app);
	return httpServer;
}
