package Yukki::Web::Controller::Admin::User;
$Yukki::Web::Controller::Admin::User::VERSION = '0.991_007'; # TRIAL
$Yukki::Web::Controller::Admin::User::VERSION = '0.991007';
use v5.24;
use utf8;
use Moo;

use Email::Valid;
use FormValidator::Tiny qw( :validation :predicates :filters );
use Yukki::Error qw( http_throw );
use Yukki::User;

with 'Yukki::Web::Controller';

use namespace::clean;

# ABSTRACT: controller for administering your users


sub fire {
    my ($self, $ctx) = @_;

    my $action = $ctx->request->path_parameters->{action};
    if ($action eq 'list') { $self->list_users($ctx) }
    elsif ($action eq 'add') { $self->add_user($ctx) }
    elsif ($action eq 'edit') { $self->edit_user($ctx) }
    elsif ($action eq 'remove') { $self->remove_user($ctx) }
    else {
        http_throw('No action found matching that URL.', {
            status => 'NotFound',
        });
    }
}


sub list_users {
    my ($self, $ctx) = @_;

    my $users = $self->model('User');
    my @users = map { $users->find(login_name => $_) } $users->list;

    my $body = $self->view('Admin::User')->list($ctx, {
        users => \@users,
    });

    $ctx->response->body($body);
}


validation_spec add_user => [
    login_name => [
        required => 1,
        must => limit_character_set('a-z', 'A-Z', '0-9', '_', '-'),
        must => length_in_range(3, 20),
    ],
    name => [
        required => 1,
        must => length_in_range(1, 200),
    ],
    email => [
        required => 1,
        must => length_in_range(1, 200),
        must => sub {
            (Email::Valid->address($_), 'Not a valid email address.')
        },
    ],
    password => [
        required => 1,
        must => length_in_range(8, 72),
    ],
    groups => [
        optional  => 1,
        into      => split_by(qr/,/),
        each_into => trim(),
        each_must => limit_character_set('a-z', 'A-Z', '0-9', '_', '-'),
    ],
];

sub add_user {
    my ($self, $ctx) = @_;

    my $form_errors;
    if ($ctx->request->method eq 'POST') {
        my $user_params;
        ($user_params, $form_errors)
            = validate_form add_user => $ctx->request->body_parameters;

        if (!defined $form_errors) {
            my $user = Yukki::User->new(
                login_name => $user_params->{login_name},
                password   => $user_params->{password},
                name       => $user_params->{name},
                email      => $user_params->{email},
                groups     => $user_params->{groups},
            );

            $self->model('User')->save($user);

            $ctx->add_info('Saved '.$user->login_name.'.');

            $ctx->response->redirect('/admin/user/list');
            return;
        }
    }

    my @breadcrumb = (
        {
            label => 'List',
            href  => '/admin/user/list',
        },
    );

    my $body = $self->view('Admin::User')->edit($ctx, {
        form        => $ctx->request->body_parameters->as_hashref,
        breadcrumb  => \@breadcrumb,
        form_errors => $form_errors,
    });

    $ctx->response->body($body);
}


validation_spec edit_user => [
    name => [
        required => 1,
        must => length_in_range(1, 200),
    ],
    email => [
        required => 1,
        must => length_in_range(1, 200),
        must => sub {
            (Email::Valid->address($_), 'Not a valid email address.')
        },
    ],
    password => [
        optional => 1,
        must => length_in_range(8, 72),
    ],
    groups => [
        optional  => 1,
        into      => split_by(qr/,/),
        each_into => trim(),
        each_must => limit_character_set('a-z', 'A-Z', '0-9', '_', '-'),
    ],
];

sub edit_user {
    my ($self, $ctx) = @_;

    my $login_name = $ctx->request->path_parameters->{login_name};
    my $user = $self->model('User')->find(login_name => $login_name);

    my $form_errors;
    if ($ctx->request->method eq 'POST') {
        my $user_params;
        ($user_params, $form_errors)
            = validate_form edit_user => $ctx->request->body_parameters;

        if (!defined $form_errors) {
            $user->password($user_params->{password})
                if defined $user_params->{password};
            $user->name($user_params->{name});
            $user->email($user_params->{email});
            $user->groups->@* = $user_params->{groups}->@*
                if defined $user_params->{groups};

            $self->model('User')->save($user);

            $ctx->add_info('Saved '.$user->login_name.'.');

            $ctx->response->redirect('/admin/user/list');
            return;
        }
    }

    my @breadcrumb = (
        {
            label => 'List',
            href  => '/admin/user/list',
        },
    );

    my $body = $self->view('Admin::User')->edit($ctx, {
        user        => $user,
        breadcrumb  => \@breadcrumb,
        form_errors => $form_errors,
    });

    $ctx->response->body($body);
}


sub remove_user {
    my ($self, $ctx) = @_;

    my $login_name = $ctx->request->path_parameters->{login_name};
    my $user = $self->model('User')->find(login_name => $login_name);

    if (!$user) {
        $ctx->add_errors("No user found with login naem $login_name.");
        $ctx->response->redirect('/admin/user/list');
        return;
    }

    my @breadcrumb = (
        {
            label => 'List',
            href  => '/admin/user/list',
        },
    );

    my $confirmed = $ctx->request->body_parameters->{confirmed};
    if ($ctx->request->method eq 'POST' and $confirmed) {

        $self->model('User')->delete($user);
        $ctx->add_info("Removed user with login name $login_name.");
        $ctx->response->redirect('/admin/user/list');
        return;
    }

    my $body = $self->view('Admin::User')->remove($ctx, {
        title       => 'Remove ' . $user->login_name,
        user        => $user,
        breadcrumb  => \@breadcrumb,
        return_link => $ctx->rebase_url('/admin/user/list'),
    });

    $ctx->response->body($body);
}

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

Yukki::Web::Controller::Admin::User - controller for administering your users

=head1 VERSION

version 0.991_007

=head1 DESCRIPTION

Controller for administering the wiki users.

=head1 METHODS

=head2 fire

=head2 list_users

Displays a page listing user records.

=head2 add_user

Add a user account.

=head2 edit_user

Edit a user account.

=head2 remove_user

Display a confirmation page and confirm the deletion of a user.

=head1 AUTHOR

Andrew Sterling Hanenkamp <hanenkamp@cpan.org>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2026 by Qubling Software LLC.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut
