package LasTres::Controller::PJ;

use v5.36.0;

use strict;
use warnings;

use UUID::URandom qw/create_uuid_string/;

use Try::Tiny;

use LasTres::DAO::PJs;
use LasTres::DAO::Equipments;
use LasTres::DAO::Teams;
use LasTres::DAO::Stats;
use LasTres::DAO::SkillLikeLists;
use LasTres::DAO::Inventories;
use LasTres::Schema;
use LasTres::Races;

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

my $schema                     = LasTres::Schema->Schema;
my $result_set_pjs             = LasTres::DAO::PJs->ResultSet;
my $result_set_equipments      = LasTres::DAO::Equipments->ResultSet;
my $result_set_teams           = LasTres::DAO::Teams->ResultSet;
my $result_set_stats           = LasTres::DAO::Stats->ResultSet;
my $result_set_skill_like_list = LasTres::DAO::SkillLikeLists->ResultSet;
my $result_set_inventory       = LasTres::DAO::Inventories->ResultSet;

sub list_my_pjs ($self) {
    my $user = $self->user;
    if ( !defined $user ) {
        return $self->render(
            status => 401,
            json   => { error => 'You must login first.' }
        );
    }
    my @pjs      = $user->pjs;
    my @pjs_hash = (
        map {
            $_->hash;
        } @pjs
    );
    return $self->render(
        status => 200,
        json   => \@pjs_hash,
    );
}

sub create ($self) {
    my %param = %{ $self->req->json };
    my $user  = $self->user;
    if ( !defined $user ) {
        return $self->render(
            status => 401,
            json   => { error => 'You must login first.' }
        );
    }
    my @pjs = $user->pjs;
    if ( scalar @pjs >= 3 ) {
        return $self->render(
            status => 401,
            json   => {
                error =>
'You reached the limit of free pjs, delete one or update to premium.',
            }
        );
    }
    my $uuid      = create_uuid_string();
    my $owner     = $user;
    my $full_name = $param{full_name};
    if ( !defined $full_name || length $full_name < 3 ) {
        return $self->render(
            status => 400,
            json   => { error => 'The full_name is too short.', }
        );
    }
    my $short_name = $param{short_name};
    if ( !defined $short_name || length $short_name < 3 ) {
        return $self->render(
            status => 400,
            json   => { error => 'The short_name is too short.', }
        );
    }
    my $nick = $param{'nick'};
    if ( !defined $nick || length $nick <= 0 ) {
        return $self->render(
            status => 400,
            json   => { error => 'You must set a nick.', }
        );
    }
    my $race_identifier = $param{'race'};
    if ( !defined $race_identifier || !length $race_identifier ) {
        return $self->_invalid_race;
    }
    my $races = LasTres::Races->new;
    my $race  = $races->hash_playable->{$race_identifier};
    if ( !defined $race ) {
        return $self->_invalid_race;
    }
    my $exception;
    try {
        $schema->txn_do(
            sub {
                $self->_insert_new_player( $owner, $full_name, $short_name,
                    $nick, $race );
            }
        );
    }
    catch {
        $exception = $_;
        if ( $_ =~ /Rollback failed/ ) {
            say STDERR "Unable to rollback failed transaction:";
        }
        say STDERR $_;
    };
    if ( defined $exception ) {
        return $self->render(
            status => 500,
            json   => { error => 'Database error' },
        );
    }
    return $self->render(
        status => 200,
        json   => { info => 'Sucessfully created pj.' },
    );
}

sub _insert_new_player ( $self, $owner, $full_name, $short_name, $nick, $race )
{
    require LasTres::Schema;
    my $schema = LasTres::Schema->Schema;
    my $uuid_born_stats     = create_uuid_string;
    my $uuid_training_stats = create_uuid_string;
    my $uuid_equipment      = create_uuid_string;
    my $uuid_skills         = create_uuid_string;
    my $uuid_spells         = create_uuid_string;
    my $uuid_pj             = create_uuid_string;
    my $uuid_inventory      = create_uuid_string;
    my $uuid_team           = create_uuid_string;
    my $uuid_owner          = $owner->uuid;

    my $born_stats = $schema->resultset('Stats')->new({
        uuid         => $uuid_born_stats,
        health       => $self->_get_random_born_stat,
        strength     => $self->_get_random_born_stat,
        resistance   => $self->_get_random_born_stat,
        mana         => $self->_get_random_born_stat,
        magic        => $self->_get_random_born_stat,
        speed        => $self->_get_random_born_stat,
        intelligence => $self->_get_random_born_stat,
    });
    $born_stats->insert;
    my $training_stats = $schema->resultset('Stats')->new({
        uuid         => $uuid_training_stats,
        health       => 0,
        strength     => 0,
        resistance   => 0,
        mana         => 0,
        magic        => 0,
        speed        => 0,
        intelligence => 0,
    });
    $training_stats->insert;
    $result_set_equipments->new( { uuid => $uuid_equipment } )->insert;
    $result_set_skill_like_list->new( { uuid => $uuid_skills } )->insert;
    $result_set_skill_like_list->new( { uuid => $uuid_spells } )->insert;
    $result_set_inventory->new( { uuid => $uuid_inventory } )->insert;
    my $location   = $race->spawn;
    my $area       = $location->parent;
    my $super_area = $area->parent;
    my $planet     = $super_area->parent;
    my $team       = $result_set_teams->new(
        {
            uuid       => $uuid_team,
            leader     => undef,
            name       => $uuid_team,
            planet     => $planet->identifier,
            super_area => $super_area->identifier,
            area       => $area->identifier,
            location   => $location->identifier,

        }
    );
    $team->insert;
    $result_set_pjs->new(
        {
            uuid           => $uuid_pj,
            owner          => $uuid_owner,
            full_name      => $full_name,
            short_name     => $short_name,
            nick           => $nick,
            race           => $race->identifier,
            team           => $uuid_team,
            experience     => 126,
            equipment      => $uuid_equipment,
            born_stats     => $uuid_born_stats,
            training_stats => $uuid_training_stats,
            skills         => $uuid_skills,
            spells         => $uuid_spells,
            inventory      => $uuid_inventory,
            health         => 999,
            mana           => 999,
        }
    )->insert;
    $team->leader($uuid_pj);
    $team->update;
}

sub _get_random_born_stat ($self) {
    return int( rand(32) );
}

sub _invalid_race ($self) {
    return $self->render(
        status => 400,
        json   => { error => 'Invalid race.', }
    );
}
1;
