---
import NavBar from '../components/NavBar.astro';
import Layout from '../layouts/Layout.astro';

import { createUser } from '../lib/db/users';

import { AstroCookieSetOptions } from 'astro';
import { ObjectId } from 'mongodb';
import config from '../../config.json';
import { getAllGalaxies } from '../lib/db/galaxies';
import { createPlanet } from '../lib/db/planets';
import { addSystemToSector } from '../lib/db/sectors';
import { addPlanetToSystem, createSystem } from '../lib/db/systems';
import DBPlanet from '../types/db/DBPlanet';
import DBSystem from '../types/db/DBSystem';
import locationManager from '../lib/classes/managers/LocationManager';
import SystemManager, { System } from '../lib/classes/managers/SystemManager';
import User from '../lib/classes/User';
import ResearchManager from '../lib/classes/managers/ResearchManager';

let error = "";

if(Astro.request.method === "POST") {
    const data = await Astro.request.formData();
    const username = data.get("username") as string | "";
    const email = data.get("email") as string | "";
    const password = data.get("password") as string | "";
    const password2 = data.get("password2") as string | "";

    if(username === "") error = "username is required";
    if(username.match(/^[a-zA-Z0-9]{3,20}$/) === null) error = "username must be between 3 and 20 characters long and can only contain letters and numbers";
    if(email === "") error = "email is required";
    if(email.match(/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/) === null) error = "email is invalid";
    if(password === "") error = "password is required";
    if(password2 === "") error = "password2 is required";
    if(password.length < 8 || password.length > 50) error = "password must be between 8 and 50 characters long";
    if(password !== password2) error = "passwords must match";

    if(error === "") {
        const userId = new ObjectId();
        const planetId = new ObjectId();

        const user = await createUser(userId, username, email, password, planetId);

        const userObject = new User(user._id, user.username, user.email, user.createdAt, user.updatedAt, user.lastLogin);

        const sessionTime = config.SESSION_TIME_MINUTES * 60;

        const galaxyIndex = Math.floor(Math.random() * 4);
        const sectorIndex = Math.floor(Math.random() * 8);
        const galaxies = await getAllGalaxies();
        const sectorId = galaxies[galaxyIndex].sectors[sectorIndex];
        const sector = locationManager.getSector(sectorId);
        if(!sector) throw new Error("FATAL: Sector was not found in location manager.");

        const systemData: DBSystem = {
            _id: new ObjectId(),
            name: `${username}'s home system`,
            ownedBy: user._id,
            planets: [],
            structures: [],
            resources: [],
            ships: [],
            defenses: [],
            asteroids: []
        }

        const planetData: DBPlanet = {
            _id: new ObjectId(),
            name: `${username}'s home planet`,
            owner: systemData.ownedBy,
            fields: 40,
            resources: [],
            buildings: [],
            ships: [],
            defenses: []
        }

        systemData.planets.push(planetData._id);

        await createSystem(systemData);
        await createPlanet(planetData);
        await addPlanetToSystem(systemData._id, planetData._id);

        const systemObject: System = {
            _id: systemData._id,
            sector: sector,
            name: systemData.name,
            ownedBy: userObject,
            //@ts-ignore
            structures: null,
            //@ts-ignore
            resources: null,
            //@ts-ignore
            ships: null,
            //@ts-ignore
            defenses: null,
            planets: [],
            asteroids: []
        }
    
        const systemManager = await new SystemManager(systemObject).fillData(systemData);
        const planet = systemManager.planets.find(p => p._id.equals(planetData._id));
        if(!planet) throw new Error("FATAL: Planet was not created properly in system manager.");
        
        await userObject.addMainPlanet(planet);
        sector.systems.push(systemManager);
        await addSystemToSector(sectorId, systemData._id);

        locationManager.users.push(userObject);

        const cookieOptions: AstroCookieSetOptions = {
            path: "/",
            maxAge: sessionTime,
            sameSite: "lax",
            secure: true
        }

        Astro.cookies.set("username", username, cookieOptions);
        Astro.cookies.set("userid", user._id.toString() as string, cookieOptions);
        Astro.cookies.set("currentPlanet", planetData._id.toString(), cookieOptions);
        Astro.cookies.set("currentSystem", systemData._id.toString(), cookieOptions);
        
        const res = await fetch(`${Astro.url.origin}/api/auth/generateAccessToken`, {
            method: 'POST',
            body: JSON.stringify({
                username,
                createdFrom: 'loginForm',
                duration: sessionTime
            }),
            headers: {
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + config.MASTER_ACCESSTOKEN
            }
        });
        const token = (await res.json()).accessToken;
        Astro.cookies.set("sessionToken", token, cookieOptions);

        return Astro.redirect("/game");
    }
}
---
<Layout title="Register">
    <NavBar loggedIn="false" active="register" />
    <form method="POST" class="register-form">
        <input class="register-input" type="text" name="username" placeholder="username" /><br />
        <input class="register-input" type="email" name="email" placeholder="email" /><br />
        <input class="register-input" type="password" name="password" placeholder="password" /><br />
        <input class="register-input" type="password" name="password2" placeholder="password2" /><br />
        <input class="register-submit" type="submit" value="register" />
        <p style="color: red;">{error}</p>
    </form>
</Layout>
<style>
.register-form {
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-top: 50px;
    background: linear-gradient(
        to bottom right,
        blue,
        red
    );
    padding: 30px;
    text-align: center;
    width: 300px;
    margin-left: auto;
    margin-right: auto;
    border-radius: 10px;
}

.register-input {
    margin: 5px;
    border-radius: 5px;
    border: 1px solid #ccc;
    width: 100%;
    padding: 10px;
}

.register-submit {
    margin: 5px;
    border-radius: 5px;
    border: 1px solid #ccc;
    width: 100%;
    padding: 10px;
    background-color: #4CAF50;
    color: white;
    cursor: pointer;
}
</style>