package RT::Extension::REST2::Test;

use strict;
use warnings;

### after: use lib qw(@RT_LIB_PATH@);
use lib qw(/opt/rt4/local/lib /opt/rt4/lib);

use base 'RT::Test';
use Test::WWW::Mechanize::PSGI;

sub import {
    my $class = shift;
    my %args  = @_;

    $args{'requires'} ||= [];
    if ( $args{'testing'} ) {
        unshift @{ $args{'requires'} }, 'RT::Extension::REST2';
    } else {
        $args{'testing'} = 'RT::Extension::REST2';
    }

    $class->SUPER::import( %args );
    $class->export_to_level(1);

    require RT::Extension::REST2;
}

sub mech { RT::Extension::REST2::Test::Mechanize->new }

{
    my $u;

    sub authorization_header {
        $u = _create_user() unless ($u && $u->id);
        return 'Basic dGVzdDpwYXNzd29yZA==';
    }

    sub user {
        $u = _create_user() unless ($u && $u->id);
        return $u;
    }

    sub _create_user {
        my $u = RT::User->new( RT->SystemUser );
        $u->Create(
            Name => 'test',
            Password => 'password',
            EmailAddress => 'test@rt.example',
            Privileged => 1,
        );
        return $u;
    }
}

{
    package RT::Extension::REST2::Test::Mechanize;
    use parent 'Test::WWW::Mechanize::PSGI';

    use JSON;
    my $json = JSON->new->utf8;

    sub new {
        my $class = shift;
        my %args = (
            app => RT::Extension::REST2->PSGIWrap(sub { die "Requested non-REST path" }),
            @_,
        );
        return $class->SUPER::new(%args);
    }

    sub hypermedia_ref {
        my ($self, $ref) = @_;

        my $json = $self->json_response;
        my @matches = grep { $_->{ref} eq $ref } @{ $json->{_hyperlinks} };
        Test::More::is(@matches, 1, "got one match for hypermedia with ref '$ref'") or return;
        return $matches[0];

    }

    sub url_for_hypermedia {
        my ($self, $ref) = @_;
        return $self->hypermedia_ref($ref)->{_url};
    }

    sub post_json {
        my ($self, $url, $payload, %headers) = @_;
        $self->post(
            $url,
            Content => $json->encode($payload),
            'Content-Type' => 'application/json; charset=utf-8',
            %headers,
        );
    }

    sub put_json {
        my ($self, $url, $payload, %headers) = @_;
        $self->put(
            $url,
            Content => $json->encode($payload),
            'Content-Type' => 'application/json; charset=utf-8',
            %headers,
        );
    }

    sub json_response {
        local $Test::Builder::Level = $Test::Builder::Level + 1;
        my $self = shift;

        my $res = $self->response;

        local $main::TODO;
        Test::More::like($res->header('content-type'),
            qr{^application/json(?:; charset="?utf-8"?)?$});

        return $json->decode($res->content);
    }
}

1;