import { Router, json, type Request, type Response, type NextFunction } from "express";
import { connection, seed } from "..";

interface User {
    id: number,
    name: string,
    password: string,
    admin: 0|1,
    token: string
}

export interface RequestWithUser extends Request {
    user?: User;
}

export async function forceAuthorization(req: RequestWithUser, res: Response, next: NextFunction) {
    if(!req.headers.authorization) {
        res.status(400).json({
            error: "No authorization header found."
        })

        return;
    };

    const userQuery = await connection.query("SELECT * FROM users WHERE token = ?;", [ req.headers.authorization ]);
    const userResult = userQuery[0] as User[]
    if(userResult.length == 0) {
        res.status(400).json({
            error: "Token is invalid."
        })
        return;
    }
    
    req.user = userResult[0];
    next();
}
const router = Router();

router.post("/login", json(), async (req, res) => {
    const body = req.body;
    if(!body.name) { res.status(400).json({
        error: "No username set."
    }); return }
    if(!body.password) { res.status(400).json({
        error: "No password set."
    }); return }

    const userQuery = await connection.query("SELECT * FROM users WHERE name = ?;", [ body.name ]);
    const userResult = userQuery[0] as User[]
    if(userResult.length == 0) {
        res.status(400).json({
            error: "Password or username is invalid."
        }); return
    }
    
    const user = userResult[0]

    if(!await Bun.password.verify(seed + body.password, user.password)) {
        res.status(400).json({
            error: "Password or username is invalid."
        }); return
    }

    res.json({
        token: user.token
    }); 
    return;
})

router.get("/user/:id", forceAuthorization, async (req, res) => {
    const queryConnection = await connection.query("SELECT * FROM users WHERE id = ?;", [req.params.id])
    const user = (queryConnection[0] as User[])?.[0]
    res.json({
        id: user.id,
        name: user.name,
        admin: user.admin
    })
})

router.get("/me", forceAuthorization, async (req: RequestWithUser, res) => {
    res.json({
        id: req.user?.id,
        name: req.user?.name,
        admin: req.user?.admin
    })
})

router.post("/register", json(), async (req, res) => {
    const body = req.body;
    if(!body.name) { res.status(400).json({
        error: "No username set."
    }); return }
    if(typeof body.name != "string") { res.status(400).json({
        error: "Username is not a string."
    }); return }
    if(!body.password) { res.status(400).json({
        error: "No password set."
    }); return }
    if(typeof body.password != "string") { res.status(400).json({
        error: "Password is not a string."
    }); return }
    if( body.password.length <= 2) { res.status(400).json({
        error: "Password has to be a minimum of 3."
    }); return }
    const userQuery = await connection.query("SELECT * FROM users WHERE name = ?;", [ body.name ]);
    const userResult = userQuery[0] as User[]
    if(userResult.length != 0) {
        res.status(400).json({
            error: "Username is already registered."
        }); return
    }

    const password = await Bun.password.hash(seed + body.password)
    const token = crypto.randomUUID().replaceAll("-", "")+crypto.randomUUID().replaceAll("-", "");

    await connection.query(
        "INSERT INTO `users` (`id`, `name`, `password`, `admin`, `token`) VALUES (NULL, ?, ?, '0', ?);",
        [ body.name, password, token ]
    )
    res.status(201).end();
})

export default  router;