package Pcore::API::PAUSE;

use Pcore -class, -res;
use Pcore::Util::Text qw[encode_utf8];
use Pcore::Util::Scalar qw[is_coderef];

has username => ( required => 1 );
has password => ( required => 1 );

has _auth_header => ( is => 'lazy', init_arg => undef );

sub _build__auth_header ($self) {
    return 'Basic ' . P->data->to_b64u( encode_utf8( $self->{username} ) . q[:] . encode_utf8( $self->{password} ) ) . q[==];
}

sub upload ( $self, $path ) {
    my $body;

    $path = P->path($path);

    my $boundary = P->random->bytes_hex(64);

    $self->_pack_multipart( \$body, $boundary, 'HIDDENNAME', \encode_utf8( $self->{username} ) );

    $self->_pack_multipart( \$body, $boundary, 'pause99_add_uri_subdirtext', \$EMPTY );

    $self->_pack_multipart( \$body, $boundary, 'CAN_MULTIPART', \1 );

    $self->_pack_multipart( \$body, $boundary, 'pause99_add_uri_upload', \$path->{filename} );

    $self->_pack_multipart( \$body, $boundary, 'pause99_add_uri_httpupload', \P->file->read_bin($path), $path->{filename} );

    $self->_pack_multipart( \$body, $boundary, 'pause99_add_uri_uri', \$EMPTY );

    $self->_pack_multipart( \$body, $boundary, 'SUBMIT_pause99_add_uri_httpupload', \q[ Upload this file from my disk ] );

    $body .= "--$boundary--\r\n\r\n";

    return P->http->post(
        'https://pause.perl.org/pause/authenquery',
        headers => [
            Authorization  => $self->_auth_header,
            'Content-Type' => qq[multipart/form-data; boundary=$boundary],
        ],
        data => \$body,
    );
}

sub clean ( $self, @args ) {
    my %args = (
        keep => 2,
        @args,
    );

    return res [ 400, q[Bad "keep" arument.] ] if !$args{keep};

    my $res = P->http->get( 'https://pause.perl.org/pause/authenquery?ACTION=delete_files', headers => [ Authorization => $self->_auth_header ] );

    return res [ $res->{status}, $res->{reason} ] if !$res;

    my $releases;

    for my $node ( $res->tree->find('tbody.list > tr')->@* ) {
        my ( $name, $ver ) = $node->at('td.file')->text =~ /\A(.+)-v([[:alnum:].]+)[.]tar[.]gz\z/sm;

        next if !$name;

        next if $node->at('td.modified')->text =~ /Scheduled for deletion/smi;

        $releases->{$name}->{$ver} = undef;
    }

    my $params = [
        HIDDENNAME                         => uc encode_utf8( $self->{username} ),
        SUBMIT_pause99_delete_files_delete => 'Delete',
    ];

    my $releases_to_remove;

    for my $release ( keys $releases->%* ) {
        my $versions = [ map {"$_"} reverse sort map { version->new($_) } keys $releases->{$release}->%* ];

        # keep last releases
        splice $versions->@*, 0, $args{keep}, ();

        if ( $versions->@* ) {
            for my $version ( $versions->@* ) {
                $releases_to_remove->{"$release-v$version"} = undef;

                push $params->@*, pause99_delete_files_FILE => "$release-v$version.tar.gz";
                push $params->@*, pause99_delete_files_FILE => "$release-v$version.meta";
                push $params->@*, pause99_delete_files_FILE => "$release-v$version.readme";
            }
        }
    }

    return res [ 200, 'Nothing to do' ] if !$releases_to_remove;

    $res = P->http->post(
        'https://pause.perl.org/pause/authenquery?ACTION=delete_files',
        headers => [
            Authorization  => $self->_auth_header,
            'Content-Type' => 'application/x-www-form-urlencoded',
        ],
        data => P->data->to_uri($params),
    );

    return res [ $res->{status}, $res->{reason} ], [ sort keys $releases_to_remove->%* ];
}

sub _pack_multipart ( $self, $body, $boundary, $name, $content, $filename = undef ) {
    $body->$* .= "--$boundary\r\n";

    $body->$* .= qq[Content-Disposition: form-data; name="$name"];

    $body->$* .= qq[; filename="$filename"] if $filename;

    $body->$* .= "\r\n" x 2;

    $body->$* .= $content->$*;

    $body->$* .= "\r\n";

    return;
}

1;
## -----SOURCE FILTER LOG BEGIN-----
##
## PerlCritic profile "pcore-script" policy violations:
## +------+----------------------+----------------------------------------------------------------------------------------------------------------+
## | Sev. | Lines                | Policy                                                                                                         |
## |======+======================+================================================================================================================|
## |    3 | 111                  | Subroutines::ProhibitManyArgs - Too many arguments                                                             |
## +------+----------------------+----------------------------------------------------------------------------------------------------------------+
##
## -----SOURCE FILTER LOG END-----
__END__
=pod

=encoding utf8

=head1 NAME

Pcore::API::PAUSE - pause.perl.org API

=head1 SYNOPSIS

=head1 DESCRIPTION

=head1 ATTRIBUTES

=head1 METHODS

=head1 SEE ALSO

=cut
