/**
 * Resources:
 * https://stackoverflow.com/questions/76131891/what-is-the-best-method-for-socket-io-authentication
 */
import {Application, Request, Response} from 'express';
import UserService from '../services/UserService';
import jwt from "jsonwebtoken";
import config from "./Config";
import {loginAccountSchema, registerAccountSchema} from "./ZodTypes";
import path from "path";
import { TAsset } from './Types'
import fs from 'fs'

async function addHttpRoutes(app: Application) {
    app.get('/assets', (req: Request, res: Response) => {
        let assets: TAsset[] = [];
        const tiles = listTiles();
        tiles.forEach(tile => {
            assets.push({key: tile, value: '/tiles/' + tile, group: 'tiles', type: 'link'});
        });

        const objects = listObjects();
        objects.forEach(object => {
            assets.push({key: object, value: '/objects/' + object, group: 'objects', type: 'link'});
        });

        res.json(assets);
    });
    app.get('/assets/:type/:file', (req: Request, res: Response) => {
        const assetName = req.params.file;

        // if (!isValidAsset(assetName)) {
        //     return res.status(400).send('Invalid asset name');
        // }

        const options = {
            root: path.join(process.cwd(), 'public', req.params.type),
        };

        res.sendFile(assetName, options, (err) => {
            if (err) {
                console.error('Error sending file:', err);
                res.status(500).send('Error downloading the asset');
            }
        });
    });

    app.post('/login', async (req: Request, res: Response) => {
        const { username, password } = req.body;

        try {
            loginAccountSchema.parse({ username, password });
        } catch (error: any) {
            return res.status(400).json({ message: error.errors[0].message });
        }

        const userService = new UserService();
        const user = await userService.login(username, password);

        if (user) { //test
            const token = jwt.sign({ id: user.id }, config.JWT_SECRET, { expiresIn: '1h' });
            return res.status(200).json({ token });
        }

        return res.status(400).json({ message: 'Failed to login' });
    });

    app.post('/register', async (req: Request, res: Response) => {
        const { username, password } = req.body;

        try {
            registerAccountSchema.parse({ username, password });
        } catch (error: any) {
            return res.status(400).json({ message: error.errors[0].message });
        }

        const userService = new UserService();
        const user = await userService.register(username, password);

        if (user) {
            const token = jwt.sign({ id: user.id }, config.JWT_SECRET, { expiresIn: '1h' });
            return res.status(200).json({ token });
        }

        return res.status(400).json({ message: 'Failed to register user' });
    });

    console.log('[✅] Web routes added');
}

export { addHttpRoutes };

function listTiles(): string[] {
    // get root path
    const folder = path.join(process.cwd(), 'public', 'tiles');

    // list the files in the folder
    let tiles: string[] = [];

    try {
        const files = fs.readdirSync(folder);

        files.forEach(file => {
            tiles.push(file.replace('.png', ''));
        });
    } catch (err) {
        console.log(err);
    }

    console.log(tiles);

    return tiles;
}

function listObjects(): string[] {
    // get root path
    const folder = path.join(process.cwd(), 'public', 'objects');

    // list the files in the folder
    let objects: string[] = [];

    try {
        const files = fs.readdirSync(folder);

        files.forEach(file => {
            objects.push(file.replace('.png', ''));
        });
    } catch (err) {
        console.log(err);
    }

    console.log(objects);

    return objects;
}