#!perl -T
use warnings; use strict;
use Test::More;
use Test::Fatal;

use Elive;
use Elive::Entity::Session;
use Elive::Util;
use version;

use lib '.';
use t::Elive;

my $t = Test::More->builder();

my $class = 'Elive::Entity::Session' ;

use Scalar::Util;
use Try::Tiny;

my $MODULE = 'Test::Taint';
eval "use $MODULE";
plan skip_all => "$MODULE not available for taint tests"
    if $@;

plan tests => 21;

taint_checking_ok();

do {
    my $string = 'gfdsgdfrg %^&%*( fdsfs';

    is(exception {Elive::Util::_freeze($string, 'Str')} => undef,
       '_freeze of untainted data -lives');

    taint($string);

    isnt(exception {Elive::Util::_freeze($string, 'Str')} => undef,
       '_freeze of tainted data -lives');

};

SKIP: {

    my $skippable = 18;

    my %result = t::Elive->test_connection(only => 'real');
    my $auth = $result{auth};

    skip ($result{reason} || 'skipping live tests', $skippable)
	unless $auth && @$auth;

    my $connection_class = $result{class};
    my $connection = $connection_class->connect(@$auth);

    my $min_elm3_version =  '9.5.0';
    my $server_details = $connection->server_details;
    my $server_version = $server_details->version;

    my $have_elm3 = do {
	my $min_elm3_version_num = version->new($min_elm3_version)->numify;
	my $server_version_num = version->new($server_version)->numify;

	$server_version_num >= $min_elm3_version_num;
    };

    skip ($result{reason} || 'Test requires ELM > 3.0', $skippable)
	unless $have_elm3;

    Elive->connection($connection);

    my $session_start = time();
    my $session_end = $session_start + 15 * 10;

    my $session_name_clean = 'test session, generated by t/soap-taint-mode.t(' . t::Elive::generate_id() . ')';
    taint( my $session_name_tainted = $session_name_clean);

    untainted_ok($session_name_clean, 'untainted sanity');
    tainted_ok($session_name_tainted, 'tainted sanity');

    my %session_data = (
	name => $session_name_clean,
	start =>  $session_start . '000',
	end => $session_end . '000',
    );

    my $session;

    is( exception {$session = $class->insert(\%session_data);} => undef,
	     'insert with no tainted data - lives');

    isa_ok($session, $class, 'session');

    $session_data{name} = $session_name_tainted;
    isnt( exception {$class->insert(\%session_data);} => undef,
	     'insert with tainted Str data - dies');

    my $user_notes_clean = 'this is a test';
    my $user_notes_tainted = $user_notes_clean;
    taint($user_notes_tainted);

    my %update_data = (
	userNotes => $user_notes_clean,
	);

    is( exception {$session->update(\%update_data)} => undef, 'update with clean Str data - lives');

    $update_data{userNotes} = $user_notes_tainted;

    isnt( exception {$session->update(\%update_data)} => undef, 'update with tainted data - dies');

    is( exception {$session->revert} => undef, 'revert tainted data - lives');

    $session->{meeting}{name} = $session_name_tainted;
    isnt( exception {$session->is_changed} => undef, 'is_changed() on tainted data - dies');

    $session->{meeting}{name} = $session_name_clean;
    is( exception {$session->is_changed} => undef, 'is_changed() on clean data - lives');

    my $session_id = $session->sessionId;

    $session->_db_data(undef);

    isnt( exception {Elive::Entity::Session->list(filter => "name = '$session_name_tainted'")} => undef,
	'List with tainted filter - dies');
  
    isnt( exception {Elive::Entity::Session->list(filter => "name = ".Elive::Entity::Session->quote($session_name_tainted))} => undef,
	'List with tainted filter quoted - dies');
  
    my $sessions;

    is( exception {$sessions = Elive::Entity::Session->list(filter => "name = '$session_name_clean'")} => undef,
	'List with clean filter - lives');
  
    is( exception {Elive::Entity::Session->list(filter => "name = ".Elive::Entity::Session->quote($session_name_clean))} => undef,
	'List with clean filter quoted - lives');
  
    is(scalar @$sessions, 1, 'list returns unique session');

    is( try {$sessions->[0]->sessionId}, $session_id, 'listed sessionId as expected');
    $sessions = undef;

    ok ($session = Elive::Entity::Session->retrieve($session_id),
	'Refetch of session');

    is( exception {$session->delete} => undef,'session deletion - lives');

}

Elive->disconnect;
