package LasTres::Controller::Player;

use v5.36.0;

use strict;
use warnings;

use Crypt::URandom qw/urandom/;
use Crypt::Bcrypt  qw/bcrypt bcrypt_check/;
use UUID::URandom  qw/create_uuid_string/;

use LasTres::DAO::Players;

use Mojo::Base 'Mojolicious::Controller', -signatures;

my $result_set_players = LasTres::DAO::Players->ResultSet;

sub check_login($self) {
    my $user = $self->user;
    my $return_hash = {
        is_login => 0,
        is_verified => 0,
    };
    if (!defined $user) {
        return $self->render(status => 200, json => $return_hash);
    }
    $return_hash->{is_login} = 1;
    if ($user->verified) {
        $return_hash->{is_verified} = 1;
    }
    return $self->render(status => 200, json => $return_hash);
}

sub login ($self) {
    my %params          = %{ $self->req->json };
    my $username        = $params{username};
    my $password        = $params{password};
    my @players = $result_set_players->search({
        -or => [
            username => $username,
            email => $username,
        ]
    });
    my $player = $players[0];
    if (!defined $player) {
        return $self->return_incorrect_username_or_password();
    }
    if (!bcrypt_check($password, $player->encrypted_password)) {
        return $self->return_incorrect_username_or_password();
    }
    $self->session->{uuid} = $player->uuid;
    return $self->render(
        status => 200,
        json   => {
            info => 'Login sucessful',
        }
    );
}

sub return_incorrect_username_or_password($self) {
    return $self->render(
        status => 400,
        json   => {
            error => 'Incorrect username or password.',
        }
    );
}

sub register ($self) {
    my %params          = %{ $self->req->json };
    my $username        = $params{username};
    my $password        = $params{password};
    my $repeat_password = $params{repeat_password};
    my $email           = $params{email};
    if ( !defined $username || length $username < 5 ) {
        return $self->render(
            status => 400,
            json   => { error => 'Username too short, minimum 5 characters.', },
        );
    }
    if ($username =~ /@/) {
        return $self->render(
            status => 400,
            json   => { error => 'The character @ is forbidden in usernames.', },
        );
    }
    if ( !defined $email || $email !~ /@/ ) {
        return $self->render(
            status => 400,
            json   => { error => 'This is not a valid mail.', },
        );
    }
    if ( $password ne $repeat_password ) {
        return $self->render(
            status => 400,
            json   => { error => 'Passwords do not match.' }
        );
    }
    if ( $password =~ /^\d+$/ ) {
        return $self->render(
            status => 400,
            json   => {
                error => 'Numeric only password are too unsafe to be allowed.'
            }
        );
    }
    if ( length $password < 12 ) {
        return $self->render(
            status => 400,
            json   => {
                error => 'The password should be at least 12 characters long.'
            }
        );
    }
    my $new_salt           = urandom(16);
    my $encrypted_password = bcrypt $password, '2b', 12, $new_salt;
    my $uuid               = create_uuid_string();
    eval {
        $result_set_players->create(
            {
                uuid               => $uuid,
                username           => $username,
                encrypted_password => $encrypted_password,
                email              => $email,
                verified           => 0,
            }
        );
    };
    if ($@) {
        if ( $@ =~ /Key \((.*?)\)=\((.*?)\) already exists\./ ) {
            return $self->render(
                status => 400,
                json   => {
                    error => "The key $1 ($2) already exists in the database.",
                }
            );
        }
        say STDERR $@;
        return $self->render(
            status => 500,
            json   => {
                error => 'Unhandled database error.',
            }
        );
    }

    my @players = $result_set_players->search({
        uuid               => $uuid,
    });
    my $player = $players[0];

    if (!defined $player) {
        return $self->render(
            status => 500,
            json   => {
                error => 'Unknown error creating entity player.',
            }
        );
    }

    undef($@);

    $self->session->{uuid} = $player->uuid;

    return $self->render(
        status => 200,
        json   => {
            user => {
                username => $username,
                email    => $email,
                verified => 0,
            },
            info => 'User sucessfully created',
        }
    );
}
1;
