package CF::Controller::Events;

use Mojo::Base 'Mojolicious::Controller';
use UUID::URandom qw(create_uuid_string);

use feature 'signatures';
no warnings 'experimental::signatures';

sub create ($c) {
    $c->openapi->valid_input or return;

    my $args = $c->req->json;

    my $event = $c->schema->resultset('Event')->create({
        uuid        => create_uuid_string(),
        type        => $args->{type},
        owner_id    => $c->user->{id},
        start       => $args->{start},
        finish      => $args->{finish},
        name        => $args->{name},
        description => $args->{description},
        organizer   => $args->{organizer} || $c->user->{name},
    });

    $c->render(
        status  => 201,
        openapi => { id => $event->id },
    );
};

sub get ($c) {
    $c->openapi->valid_input or return;

    my $event = $c->_get() || return;

    my $formatted = $event->format();
    $formatted->{acl} = [];
    $formatted->{stream_url} = $event->stream_url
                             // '/hls/' . $event->uuid . '.m3u8';

    my $roles = $event->user_roles( $c->user );

    if ( $roles->{chairman} ) {
        $formatted->{meet_url}   = $c->cfg->{jitsi_base_url}  . $event->uuid;
        $formatted->{record_url} = $c->cfg->{codimd_base_url} . $event->uuid;
    }
    elsif ( ! $event->is_published ) {
        # neni zverejnen
        return $c->error(404, 'Event not found');
    }

    $c->render(json => $c->spec_filter($formatted, 'Event')); # BUG: error if openpi
}

sub list ($c) {
    $c->openapi->valid_input or return;
    my $args = $c->validation->output;

    my ($cond, $attrs) = $c->search_parametrs( $args );

    $cond->{deleted} = undef;

    $cond->{type} = $args->{type} if $args->{type};

    if ( ! $args->{show_finished} ) {
        $cond->{state} = [0, 1];
    }

    if ( ! $c->user_roles->{organizer} ) {
        $cond->{is_published} = 't';
    }

    my @events = ();
    my $count = $c->schema->resultset('Event')->count($cond);

    if ( $count ) {
        my $events = $c->schema->resultset('Event')->search($cond, $attrs);

        EVENT:
        while ( my $event = $events->next() ) {
            my $formatted = $event->format();
            push @events, $c->spec_filter($formatted, 'EventInList');
        }
    }

    $c->render(json => {
        data  => \@events,
        total => $count,
    });
}

sub update ($c) {
    $c->openapi->valid_input or return;

    my $args = $c->req->json;

    my $event  = $c->_get('chairman');
    my $update = $c->prepare_update_data( $event, $c->req->json );
    $event->update({ %{ $update }, });

    $c->render(status => 204, text => '');
}

sub delete ($c) {
    $c->openapi->valid_input or return;

    my $event  = $c->_get('chairman') || return;
    $event->update({ deleted => \'now()', });

    $c->render(status => 204, text => '');
}

sub role_add ($c) {
    $c->openapi->valid_input or return;

    my $args = $c->req->json;

    my $event = $c->_get('chairman') || return;

    my $subject = $c->schema->resultset('EventACLSubject')->find_or_new({
        class => $args->{subject_class},
        key   => $args->{subject_value},
        name  => $args->{subject_name} || $args->{subject_value},
    },
    {
        key => 'class_key'
    });

    if ( $subject->in_storage ) {
        if ( $args->{subject_name} && $args->{subject_name} ne $subject->name ) {
            $subject->update({
                updated => \'now()',
                name    => $args->{subject_name},
            });
        }
    } else {
        $subject->insert;
    }

    my $acl = $event->find_or_create_related('acls', {
        subject_id => $subject->id,
        role       => $args->{role},
    });

    $c->render(
        status => 201,
        openapi => { id => $acl->id },
    );
}

sub _get ($c, $role='') {

    my $event = $c->schema->resultset('Event')->find({
        id => $c->stash->{id}
    });

    return $c->error(404, 'Event not found') if ! $event || $event->deleted;

    if ( $role ) {
        my $roles = $event->user_roles( $c->user );
        return $c->error(403, 'Access denied') if ! exists $roles->{$role};
    }

    return $event;
}

1;