import express from "express";
import internalWireguardFs from "../internal/wireguard-fs.js";
import db from "../db.js";

const router = express.Router({
	caseSensitive: true,
	strict: true,
	mergeParams: true,
});

/**
 * Authenticate WireGuard client by tunnel remote socket IP
 */
const authenticateWgClientIp = async (req, res, next) => {
    let clientIp = req.headers["x-forwarded-for"] || req.socket.remoteAddress || req.ip;
    if (clientIp) {
        if (clientIp.includes("::ffff:")) {
            clientIp = clientIp.split("::ffff:")[1];
        }
        clientIp = clientIp.split(',')[0].trim();
    }
    
    if (!clientIp) {
        return res.status(401).json({ error: { message: "Unknown remote IP address" } });
    }
    
    try {
        const knex = db();
        const client = await knex("wg_client").where("ipv4_address", clientIp).first();
        if (!client) {
            return res.status(401).json({ error: { message: `Unauthorized: IP ${clientIp} does not match any registered WireGuard Client in the Hub Database` } });
        }
        
        req.wgClient = client;
        next();
    } catch (err) {
        next(err);
    }
};

router.use(authenticateWgClientIp);

/**
 * GET /api/wg-public/me
 * Returns connection metrics and identity details dynamically mapped to this IP
 */
router.get("/me", async (req, res, next) => {
    try {
		const totalStorageBytes = await internalWireguardFs.getClientStorageUsage(req.wgClient.ipv4_address);
        res.status(200).json({
            id: req.wgClient.id,
            name: req.wgClient.name,
            ipv4_address: req.wgClient.ipv4_address,
            enabled: !!req.wgClient.enabled,
            rx_limit: req.wgClient.rx_limit,
            tx_limit: req.wgClient.tx_limit,
            storage_limit_mb: req.wgClient.storage_limit_mb,
            transfer_rx: req.wgClient.transfer_rx,
            transfer_tx: req.wgClient.transfer_tx,
			storage_usage_bytes: totalStorageBytes
        });
    } catch (err) {
        next(err);
    }
});

/**
 * GET /api/wg-public/files
 * Fetch encrypted files directory securely
 */
router.get("/files", async (req, res, next) => {
	try {
		const files = await internalWireguardFs.listFiles(req.wgClient.ipv4_address);
		res.status(200).json(files);
	} catch (err) {
		if (err.code === "ENOENT") return res.status(200).json([]);
		next(err);
	}
});

/**
 * POST /api/wg-public/files
 * Upload directly into backend AES storage limits
 */
router.post("/files", async (req, res, next) => {
	try {
		if (!req.files || !req.files.file) {
			return res.status(400).json({ error: { message: "No file provided" } });
		}
		const file = req.files.file;
		
		if (req.wgClient.storage_limit_mb > 0) {
			const existingStorage = await internalWireguardFs.getClientStorageUsage(req.wgClient.ipv4_address);
			if (existingStorage + file.size > req.wgClient.storage_limit_mb * 1024 * 1024) {
				return res.status(413).json({ error: { message: "Storage Quota Exceeded limits assigned by Administrator" } });
			}
		}

		await internalWireguardFs.uploadFile(req.wgClient.ipv4_address, req.wgClient.pre_shared_key, file.name, file.data);
		res.status(200).json({ success: true, message: "File encrypted and saved safely via your Wireguard IP Auth!" });
	} catch (err) {
		next(err);
	}
});

/**
 * GET /api/wg-public/files/:filename
 * Decrypt stream
 */
router.get("/files/:filename", async (req, res, next) => {
	try {
		const filename = req.params.filename;
		await internalWireguardFs.downloadFile(req.wgClient.ipv4_address, req.wgClient.pre_shared_key, filename, res);
	} catch (err) {
		next(err);
	}
});

/**
 * PATCH /api/wg-public/files/:filename
 * Rename an encrypted file
 */
router.patch("/files/:filename", async (req, res, next) => {
	try {
		const oldName = req.params.filename;
		const newName = req.body?.name?.trim();
		if (!newName) {
			return res.status(400).json({ error: { message: "New file name is required" } });
		}
		await internalWireguardFs.renameFile(req.wgClient.ipv4_address, oldName, newName);
		res.status(200).json({ success: true, message: "File renamed successfully" });
	} catch (err) {
		next(err);
	}
});

/**
 * DELETE /api/wg-public/files/:filename
 */
router.delete("/files/:filename", async (req, res, next) => {
	try {
		const filename = req.params.filename;
		await internalWireguardFs.deleteFile(req.wgClient.ipv4_address, filename);
		res.status(200).json({ success: true, message: "Destroyed safely" });
	} catch (err) {
		next(err);
	}
});

export default router;
