package WebService::Freshservice::API;

use v5.010;
use strict;
use warnings;
use Method::Signatures 20140224;
use JSON qw( from_json to_json );
use MIME::Base64 qw( encode_base64 );
use Try::Tiny;
use Carp qw( croak );
use LWP::UserAgent;
use Data::Dumper;
use Moo;
use namespace::clean;

# ABSTRACT: Request abstraction to the Freshservice API

our $VERSION = '0.002'; # VERSION: Generated by DZP::OurPkg:Version


our $DEBUG = $ENV{FRESHSERVICE_DEBUG} || 0;

has 'apikey'  => ( is => 'ro', required => 1 );
has 'apiurl'  => ( is => 'ro', default => sub { "https://imdexlimited.freshservice.com" } );
has '_ua'     => ( is => 'rw', lazy => 1, builder => 1 );

method _build__ua {
  my $ua = LWP::UserAgent->new();
  $ua->agent('WebService-Freshservice');
  $ua->timeout(60);
  $ua->env_proxy;
  $ua->default_headers->push_header( 'Content-Type' => "application/json" );

  # The Freshservice api isn't standards complaint as far as auth goes. It returns 200 OK
  # whether you're authenticated or not and LWP doesn't provide credentials unless it
  # it is challenged to do so. I've raised a support case..
  $ua->default_headers->push_header( Authorization => "Basic ".encode_base64($self->apikey.":X" ) );
  return $ua;
}


method get_api ($endpoint) {
  my $result = $self->_ua->get($self->apiurl."/".$endpoint);

  # uncoverable branch true
  say Dumper($result) if $DEBUG;
  croak "API failed - error: '".$result->message."'" unless $result->is_success;
 
  my $data;
  try {
    $data = from_json($result->decoded_content);
  } catch {
    croak("Failed to parse json $_");
  };
  return $data;
}


method post_api ($endpoint,$content) {
  my $result = $self->_ua->post(
    $self->apiurl."/".$endpoint, 
    "Content_Type"  => 'application/json',
    Content         => to_json($content),
  );

  # uncoverable branch true
  say Dumper($result) if $DEBUG;
  croak "API failed - error: '".$result->message."'" unless $result->is_success;
 
  my $data;
  try {
    $data = from_json($result->decoded_content);
  } catch {
    croak("Failed to parse json $_");
  };
  return $data;
}


method put_api ($endpoint,$content) {
  my $data = to_json(
    $content, { 
      allow_blessed   => 1,
      convert_blessed => 1,
    }
  );
  my $result = $self->_ua->put(
    $self->apiurl."/".$endpoint, 
    "Content_Type"  => 'application/json',
    Content         => $data,
  );

  # uncoverable branch true
  say Dumper($result) if $DEBUG;
  croak "API failed - error: '".$result->message."'" unless $result->is_success;
  return 1;
}


method delete_api ($endpoint) {
  my $result = $self->_ua->delete($self->apiurl."/".$endpoint);

  # uncoverable branch true
  say Dumper($result) if $DEBUG;
  croak "API failed - error: '".$result->message."'" unless $result->is_success;
 
  return 1;
}

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

WebService::Freshservice::API - Request abstraction to the Freshservice API

=head1 VERSION

version 0.002

=head1 SYNOPSIS

  use WebService::Freshservice::API;

  my $request = WebService::Freshservice::API->new( apikey => 'xxxxxxxxxxxxxxxxxxxxxx' );

=head1 DESCRIPTION

Provides a light wrapper to LWP::UserAgent against the Freshservice APIs

=head1 METHODS

=head2 get_api

  $api->get_api( "itil/requesters/123456.json" );

Returns a perl object of the JSON decoded data structure API. Croaks
on failure.

=head2 post_api

  $api->post_api( "itil/requesters.json", $data );

Returns a perl object of the JSON decoded data structure API. Croaks
on failure.

=head2 put_api

  $api->put_api( "itil/requesters.json", $data );

Returns 1 on success. Croaks on failure.

=head2 delete_api

  $api->delete_api( "itil/requesters/123456.json" );

Returns 1 on success. Croaks on failure.

=head1 AUTHOR

Leon Wright <techman@cpan.org>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2016 by Leon Wright.

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
