---
import type { ObjectId } from "mongodb";
import { Users } from "../../../../lib/db/mongodb";
import { getUserById, getUserByNickOrEmail } from "../../../../lib/db/users";
import validateAccessToken from "../../../../lib/utils/validateAccessToken";
import { hash, verify } from 'argon2';

if(Astro.request.method === "PATCH") {
    const response = await validateAccessToken(Astro.request);
    if(response instanceof Response) return response;
    
    const { path } = Astro.params;

    const body = await Astro.request.json();

    if(!body || !body['password']) return new Response(
        JSON.stringify({
            code: 400,
            message: "Bad Request"
        }), { status: 400 }
    );

    const user = await getUserById(response.user as ObjectId);
    if(!user) return new Response(
        JSON.stringify({
            code: 404,
            message: "Not Found"
        }), { status: 404 }
    );

    if(!(await verify(user.password, body['password']))) return new Response(
        JSON.stringify({
            code: 401,
            message: "Unauthorized"
        }), { status: 401 }
    );

    switch(path) {
        case 'username':
            if(!body['newUsername']) return new Response(
                JSON.stringify({
                    code: 400,
                    message: "Bad Request"
                }), { status: 400 }
            );

            if(await getUserByNickOrEmail(body['newUsername'])) return new Response(
                JSON.stringify({
                    code: 409,
                    message: "Conflict"
                }), { status: 409 }
            );

            (await Users()).updateOne({ _id: user._id }, { $set: { username: body['newUsername'] } })
            return new Response(
                JSON.stringify({
                    code: 200,
                    message: "OK"
                })
            );
        case 'email':
            if(!body['newEmail']) return new Response(
                JSON.stringify({
                    code: 400,
                    message: "Bad Request"
                }), { status: 400 }
            );

            if(await getUserByNickOrEmail(body['newEmail'])) return new Response(
                JSON.stringify({
                    code: 409,
                    message: "Conflict"
                }), { status: 409 }
            );

            (await Users()).updateOne({ _id: user._id }, { $set: { email: body['newEmail'] } })
            return new Response(
                JSON.stringify({
                    code: 200,
                    message: "OK"
                })
            );
        case 'password':
            if(!body['newPassword']) return new Response(
                JSON.stringify({
                    code: 400,
                    message: "Bad Request"
                }), { status: 400 }
            );

            const newPassword = await hash(body['newPassword']);

            (await Users()).updateOne({ _id: user._id }, { $set: { password: newPassword } }) 
            return new Response(
                JSON.stringify({
                    code: 200,
                    message: "OK"
                })
            );
        default:
            return new Response(
                JSON.stringify({
                    code: 400,
                    message: "Bad Request"
                }), { status: 400 }
            );
    }
} else {
    return new Response(
        JSON.stringify({
            code: 405,
            message: "Method Not Allowed"
        }), { status: 405 }
    );
}
---