package Oauth2;

use strict;
use warnings;
use v5.22;
use feature qw(signatures);
no warnings qw(experimental::signatures);
use Moo;

use utf8;
use LWP::Authen::OAuth2;
use DDP;
use Mojo::JSON qw(decode_json);
use Mojo::Pg;
use SQL::Abstract;
use POSIX qw(strftime);
use HTML::Strip;
use Encoding::FixLatin qw(fix_latin);

has 'db' => (
    is => 'rw',
    lazy => 1,
    builder => '_build_db',
    );

has 'db_user' => (
    is => 'rw',
    default => 'db_master',
    );

has 'db_pass' => (
    is => 'rw',
    default => 'LTL%9O9^Wj&jmX4lEg',
    );

has 'db_uri' => (
    is => 'rw',
    default => 'nehantic-dev.cnxhiwukntah.us-east-1.rds.amazonaws.com',
    );

has 'db_name' => (
    is => 'rw',
    default => 'nehantic_data',
    );

has 'authorization_endpoint' => (
    is => 'rw',
    required => 1,
);

has 'token_endpoint' => (
    is => 'rw',
    required => 1,
);

#has 'api_endpoint' => (
#    is => 'rw',
#    required => 1,
#);

has 'grant_type' => (
    is => 'rw',
    required => 1,
    );

has 'client_id' => (
    is => 'rw',
    required => 1,
    );

has 'client_secret' => (
    is => 'rw',
    required => 1,
    );

has 'redirect_uri' => (
    is => 'rw',
    required => 1,
);

has 'scope' => (
    is => 'rw',
    required => 0,
);

has 'user' => (
    is => 'rw',
    required => 1,
);

has 'token' => (
    is => 'rw',
    lazy => 1,
    builder => '_build_token',
);

has 'code' => (
    is => 'ro'
);

has 'refresh_token' => (
    is => 'rw',
    lazy => 1,
    builder => '_build_refresh_token',
);

has 'OAuth2' => (
    is => 'rw',
    required => 1,
    lazy => 1,
    builder => '_build_OAuth2',
);

has 'content_url' => (
    is => 'rw',
    required => 0,
);

has 'results' => (
    is => 'rw',
    lazy => 1,
    builder => '_build_results',
);

has 'save_token' => (
    is => 'rw',
    lazy => 1,
    builder => '_save_token',
);


sub _build_db ($self) {
    my $user = $self->db_user;
    my $pass = $self->db_pass;
    my $db_uri = $self->db_uri;
    my $db_name = $self->db_name;
    my $pg = Mojo::Pg->new("postgresql://$user:$pass\@$db_uri/$db_name");
    my $db = $pg->db;
    return $db;
}

sub _build_token ($self) {
    my $user = $self->user;
    my $db = $self->db;
    my $token = $db->select('oauth2_tokens', ['token_string'], {username=>$user})->array;
    return $token->[0];
    }

sub _save_token ($self, $user, $token) {
    my $db = $self->db;
    #my $user = $self->user;
    #my $token = $self->token;

    if (! $db->select('oauth2_tokens', ['username'], {username=>$user} )->array) {
        $db->insert('oauth2_tokens', {token_string=>$token, username=>$user,});
        return;
        }
    else {
        my $ts = strftime("%m/%d/%Y %H:%M:%S\n", localtime);
        $db->update('oauth2_tokens', {token_string=>$token, modify_timestamp=>$ts}, {username=>$user});
        return;
        }
}

sub get_initial_access_token ($self) {
    my $oauth2 = $self->Oauth2;

}


sub _build_refresh_token ($self) {
    my $oauth2 = $self->OAuth2;
    my $refresh_token = decode_json($self->token)->{'refresh_token'};

    my $res = $oauth2->request_tokens(
        grant_type => 'refresh_token',
        refresh_token => $refresh_token,
        client_id => $self->client_id,
        client_secret => $self->client_secret,
    );

    p $res
}

sub _build_OAuth2 ($self) {
    my $oauth2 = LWP::Authen::OAuth2->new(
        client_id => $self->client_id,
        client_secret => $self->client_secret,
        redirect_uri => $self->redirect_uri,
        authorization_endpoint => $self->authorization_endpoint,
        token_endpoint => $self->token_endpoint,
        #request_required_params => [ 'grant_type', 'client_id', 'client_secret'],
        #request_optional_params => [ 'scope', 'code', 'refresh_token', 'authorization_token', 'redirect_uri'],
        #refresh_required_params => ['client_id', 'client_secret', 'refresh_token'],
        #refresh_optional_params

    # Optional hook, but recommended.
        save_tokens => sub{$self->_save_token(@_)},
        save_tokens_args => [ $self->db, $self->user ],

    # This is for when you have tokens from last time.
        token_string => $self->token,
        );

    return $oauth2;
}

sub _build_results ($self) {
    my $content_url = $self->content_url;
    my $access_token = decode_json($self->token)->{'access_token'};
    my $companyid = '193514809224424';
    my $endpoint = "https://sandbox-quickbooks.api.intuit.com/v3/company/$companyid";
    my $oauth2 = $self->OAuth2;
    my $url = "$endpoint.$content_url";
    my %headers = (Authorization => "Bearer $access_token",
        Accept => 'application/json');
    my $res = $oauth2->get($url, %headers);
    my $json = $res->decoded_content;
    return $json;
}


__PACKAGE__->meta->make_immutable;