module auth.api_public;

import handy_http_primitives;
import handy_http_handlers.path_handler;
import handy_http_data.json;
import slf4d;

import auth.model;
import auth.data;
import auth.service;
import auth.data_impl_fs;

@PostMapping("/api/login")
void postLogin(ref ServerHttpRequest request, ref ServerHttpResponse response) {
    struct LoginData {
        string username;
        string password;
    }
    LoginData data = readJsonBodyAs!LoginData(request);
    string token = generateTokenForLogin(data.username, data.password);
    response.writeBodyString(token);
    infoF!"User \"%s\" logged in."(data.username);
}

struct UsernameAvailabilityResponse {
    const bool available;
}

@GetMapping("/api/register/username-availability")
void getUsernameAvailability(ref ServerHttpRequest request, ref ServerHttpResponse response) {
    string username = null;
    foreach (param; request.queryParams) {
        if (param.key == "username" && param.values.length > 0) {
            username = param.values[0];
            break;
        }
    }
    if (username is null || username.length == 0) {
        response.status = HttpStatus.BAD_REQUEST;
        response.writeBodyString("Missing username parameter.");
        return;
    }
    UserRepository userRepo = new FileSystemUserRepository();
    bool available = userRepo.findByUsername(username).isNull;
    writeJsonBody(response, UsernameAvailabilityResponse(available));
}

struct RegistrationData {
    string username;
    string password;
}

@PostMapping("/api/register")
void postRegister(ref ServerHttpRequest request, ref ServerHttpResponse response) {
    RegistrationData registrationData = readJsonBodyAs!RegistrationData(request);
    if (!validateUsername(registrationData.username)) {
        response.status = HttpStatus.BAD_REQUEST;
        response.writeBodyString("Invalid username.");
        return;
    }
    if (!validatePassword(registrationData.password)) {
        response.status = HttpStatus.BAD_REQUEST;
        response.writeBodyString("Invalid password.");
        return;
    }
    UserRepository userRepo = new FileSystemUserRepository();
    if (!userRepo.findByUsername(registrationData.username).isNull) {
        response.status = HttpStatus.BAD_REQUEST;
        response.writeBodyString("Username is taken.");
        return;
    }
    
    User user = createNewUser(userRepo, registrationData.username, registrationData.password);
    infoF!"User \"%s\" registered."(registrationData.username);
    response.writeBodyString(user.username);
}
