#!/usr/bin/env perl
use strict;
use warnings;

use Test::More;
use Test::Exception;

use JSON;

use PUC::Module::WebApp::SQLiteStore;
## no critic (ProhibitConstantPragma)
use constant CLASS => 'PUC::Module::WebApp::SQLiteStore';
## use critic

my $domain1 = {
    'webapp' => {
        'version' => '1.2.3',
        'name'    => 'wordpress',
    },
    'domain' => {
        'name' => 'add.osshareddec4.com',
        'type' => 'sub',
    },
    'server' => {
        'hostname' => 'dschrag.vps.dev.internal.hostgator.com',
    },
    'username' => 'openshift',
};
my $domain2 = {
    'webapp' => {
        'version' => '1.2.3',
        'name'    => 'joomla',
    },
    'domain' => {
        'name' => 'parked-domain.com',
        'type' => 'parked',
    },
    'server' => {
        'hostname' => 'dschrag.vps.dev.internal.hostgator.com',
    },
    'username' => 'gr19yt17',
};
my $domain2a = {
    'webapp' => {
        'version' => '3.2.1',        # changed
        'name'    => 'wordpress',    # changed
    },
    'domain' => {
        'name' => 'parked-domain.com',
        'type' => 'parked',
    },
    'server' => {
        'hostname' => 'dschrag.vps.dev.internal.hostgator.com',
    },
    'username' => 'gr19yt17',
};

my $store;
subtest 'Setup' => sub {
    lives_ok {
        $store = CLASS->new( dbfile => $ENV{TEST_DBFILE} || ':memory:' );
    }
    'Create storage object';
    lives_ok {
        $store->create_local_store;
    }
    'Create storage object';
};

my $dbh = DBI->connect_cached( $store->dsn );

subtest 'Insert a new record' => sub {
    my $data = $domain1;

    my $update;
    lives_ok {
        $update = $store->diff_and_save($data);
    }
    'New record inserted';
    ok $update,
      'Data record to be sent';

    my ($count) = $dbh->selectrow_array('SELECT COUNT(*) FROM webapps');
    ok $count == 1,
      'One record in database';

    ## no critic (CheckingReturnValueOfEval)
    is_deeply scalar eval { decode_json($update) }, $data,
      'Returned data matches most recently inserted'
      or diag 'Returned JSON data: ', $update // '<undef>';
};

subtest 'Insert a different record' => sub {
    my $data = $domain2;

    my $update;
    lives_ok {
        $update = $store->diff_and_save($data);
    }
    'New record inserted';
    ok $update,
      'Data record to be sent';

    my ($count) = $dbh->selectrow_array('SELECT COUNT(*) FROM webapps');
    ok $count == 2,
      'Two records in database';

    ## no critic (CheckingReturnValueOfEval)
    is_deeply scalar eval { decode_json($update) }, $data,
      'Returned data matches most recently inserted'
      or diag 'Returned JSON data: ', $update // '<undef>';
};

subtest 'Attempt an identical record' => sub {
    my $data = $domain1;

    my $update;
    lives_ok {
        $update = $store->diff_and_save($data);
    }
    'Attempted insert';
    ok !$update,
      'No changes, no data record to send';

    my ($count) = $dbh->selectrow_array('SELECT COUNT(*) FROM webapps');
    ok $count == 2,
      'Two records in database';
};

subtest 'Update an existing record' => sub {
    my $data = $domain2a;

    my $update;
    lives_ok {
        $update = $store->diff_and_save($data);
    }
    'New record inserted';
    ok $update,
      'Data record to be sent';

    my ($count) = $dbh->selectrow_array('SELECT COUNT(*) FROM webapps');
    ok $count == 2,
      'Two records in database';

    ## no critic (CheckingReturnValueOfEval)
    is_deeply scalar eval { decode_json($update) }, $data,
      'Returned data matches most recently inserted'
      or diag 'Returned JSON data: ', $update // '<undef>';

    my ($store_data) = $dbh->selectrow_array(
        'SELECT data FROM webapps WHERE domain = ? ORDER BY updated DESC',
        {},
        $data->{domain}->{name}
    );

    ## no critic (CheckingReturnValueOfEval)
    is_deeply scalar eval { decode_json($store_data) }, $data,
      'Stored data matches most recently inserted'
      or diag 'Retrieved JSON data: ', $store_data // '<undef>';
};

done_testing;
