# --
# TicketSearch.t - GenericInterface transport interface tests for TicketConnector backend
# Copyright (C) 2001-2012 OTRS AG, http://otrs.org/
# --
# $Id: TicketSearch.t,v 1.2 2012/01/11 22:50:07 cg Exp $
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (AGPL). If you
# did not receive this file, see http://www.gnu.org/licenses/agpl.txt.
# --

use strict;
use warnings;
use utf8;
use vars (qw($Self));

use Kernel::System::Ticket;
use Kernel::GenericInterface::Debugger;
use Kernel::GenericInterface::Requester;
use Kernel::System::GenericInterface::Webservice;
use Kernel::System::UnitTest::Helper;
use Kernel::GenericInterface::Operation::Ticket::TicketSearch;
use Kernel::GenericInterface::Operation::Ticket::SessionIDGet;
use Kernel::System::VariableCheck qw(:all);

# set UserID to root because in public interface there is no user
$Self->{UserID} = 1;

# create ticket object
my $TicketObject = Kernel::System::Ticket->new( %{$Self} );

# create a ticket
my $TicketID = $TicketObject->TicketCreate(
    Title        => 'Some Ticket Title',
    Queue        => 'Raw',
    Lock         => 'unlock',
    Priority     => '3 normal',
    State        => 'new',
    CustomerID   => '123465',
    CustomerUser => 'customer@example.com',
    OwnerID      => 1,
    UserID       => 1,
);

# sanity check
$Self->True(
    $TicketID,
    "TicketCreate() successful for Ticket ID $TicketID",
);

# get the Ticket entry
my %TicketEntry = $TicketObject->TicketSearch(
    TicketID      => $TicketID,
    DynamicFields => 0,
    UserID        => $Self->{UserID},
);

$Self->True(
    IsHashRefWithData( \%TicketEntry ),
    "TicketSearch() successful for Local TicketSearch ID $TicketID",
);

for my $Key ( keys %TicketEntry ) {
    if ( !$TicketEntry{$Key} ) {
        $TicketEntry{$Key} = '';
    }
    if ( $Key eq 'Age' ) {
        delete $TicketEntry{$Key};
    }
}

# helper object
my $HelperObject = Kernel::System::UnitTest::Helper->new(
    %{$Self},
    UnitTestObject => $Self,
);

# set webservice name
my $WebserviceName = '-Test-' . $HelperObject->GetRandomID();

# set UserID on 1
my $UserID = 1;

# create webservice object
my $WebserviceObject = Kernel::System::GenericInterface::Webservice->new( %{$Self} );
$Self->Is(
    'Kernel::System::GenericInterface::Webservice',
    ref $WebserviceObject,
    "Create webservice object",
);

my $WebserviceID = $WebserviceObject->WebserviceAdd(
    Name    => $WebserviceName,
    Config  => {},
    ValidID => 1,
    UserID  => 1,
);
$Self->True(
    $WebserviceID,
    "Added Webservice",
);

# get remote host with some precautions for certain unit test systems
my $Host;
my $FQDN = $Self->{ConfigObject}->Get('FQDN');

# try to resolve fqdn host
if ( $FQDN ne 'yourhost.example.com' && gethostbyname($FQDN) ) {
    $Host = $FQDN;
}

# try to resolve localhost instead
if ( !$Host && gethostbyname('localhost') ) {
    $Host = 'localhost';
}

# use hardcoded localhost ip address
if ( !$Host ) {
    $Host = '127.0.0.1';
}

# prepare webservice config
my $RemoteSystem =
    $Self->{ConfigObject}->Get('HttpType')
    . '://'
    . $Host
    . '/'
    . $Self->{ConfigObject}->Get('ScriptAlias')
    . '/nph-genericinterface.pl/WebserviceID/'
    . $WebserviceID;

my $WebserviceConfig = {

    #    Name => '',
    Description =>
        'Test for Ticket Connector using SOAP transport backend.',
    Debugger => {
        DebugThreshold => 'debug',
        TestMode       => 1,
    },
    Provider => {
        Transport => {
            Type   => 'HTTP::SOAP',
            Config => {
                MaxLength => 10000000,
                NameSpace => 'http://otrs.org/SoapTestInterface/',
                Endpoint  => $RemoteSystem,
            },
        },
        Operation => {
            TicketSearch => {
                Type => 'Ticket::TicketSearch',
            },
            SessionIDGet => {
                Type => 'Ticket::SessionIDGet',
            },
        },
    },
    Requester => {
        Transport => {
            Type   => 'HTTP::SOAP',
            Config => {
                NameSpace => 'http://otrs.org/SoapTestInterface/',
                Encoding  => 'UTF-8',
                Endpoint  => $RemoteSystem,
            },
        },
        Invoker => {
            TicketSearch => {
                Type => 'Test::TestSimple',
            },
            SessionIDGet => {
                Type => 'Test::TestSimple',
            },
        },
    },
};

# update webservice with real config
my $WebserviceUpdate = $WebserviceObject->WebserviceUpdate(
    ID      => $WebserviceID,
    Name    => $WebserviceName,
    Config  => $WebserviceConfig,
    ValidID => 1,
    UserID  => $UserID,
);
$Self->True(
    $WebserviceUpdate,
    "Updated Webservice $WebserviceID - $WebserviceName",
);

# Get SessionID
# create requester object
my $RequesterSessionObject = Kernel::GenericInterface::Requester->new( %{$Self} );
$Self->Is(
    'Kernel::GenericInterface::Requester',
    ref $RequesterSessionObject,
    "SessionID - Create requester object",
);

# start requester with our webservice
my $UserLogin              = 'root@localhost';
my $Password               = 'root';
my $RequesterSessionResult = $RequesterSessionObject->Run(
    WebserviceID => $WebserviceID,
    Invoker      => 'SessionIDGet',
    Data         => {
        UserLogin => $UserLogin,
        Password  => $Password,
    },
);

my $NewSessionID = $RequesterSessionResult->{Data}->{SessionID};
my @Tests        = (
    {
        Name           => 'Test 1',
        SuccessRequest => 1,
        RequestData    => {
            TicketNumber => 'NotARealTicketNumber',
        },
        ExpectedReturnLocalData => {
            Data => {
                Error => {
                    ErrorCode => 'TicketSearch.NotTicketData',
                    ErrorMessage =>
                        'TicketSearch: Could not get Ticket data in Kernel::GenericInterface::Operation::Ticket::TicketSearch::Run()'
                },
            },
            Success => 1
        },
        ExpectedReturnRemoteData => {
            Data => {
                Error => {
                    ErrorCode => 'TicketSearch.NotTicketData',
                    ErrorMessage =>
                        'TicketSearch: Could not get Ticket data in Kernel::GenericInterface::Operation::Ticket::TicketSearch::Run()'
                    }
            },
            Success => 1
        },
        Operation => 'TicketSearch',
    },

);

# debugger object
my $DebuggerObject = Kernel::GenericInterface::Debugger->new(
    %{$Self},
    DebuggerConfig => {
        DebugThreshold => 'debug',
        TestMode       => 1,
    },
    WebserviceID      => $WebserviceID,
    CommunicationType => 'Provider',
);
$Self->Is(
    ref $DebuggerObject,
    'Kernel::GenericInterface::Debugger',
    'DebuggerObject instanciate correctly',
);

for my $Test (@Tests) {

    # create local object
    my $LocalObject = "Kernel::GenericInterface::Operation::Ticket::$Test->{Operation}"->new(
        %{$Self},
        DebuggerObject => $DebuggerObject,
        WebserviceID   => $WebserviceID,
    );

    $Self->Is(
        "Kernel::GenericInterface::Operation::Ticket::$Test->{Operation}",
        ref $LocalObject,
        "$Test->{Name} - Create local object",
    );

    # start requester with our webservice
    my $LocalResult = $LocalObject->Run(
        WebserviceID => $WebserviceID,
        Invoker      => $Test->{Operation},
        Data         => {
            UserLogin => $UserLogin,
            Password  => $Password,
            %{ $Test->{RequestData} },
            }
    );

    # check result
    $Self->Is(
        'HASH',
        ref $LocalResult,
        "$Test->{Name} - Local result structure is valid",
    );

    # create requester object
    my $RequesterObject = Kernel::GenericInterface::Requester->new( %{$Self} );
    $Self->Is(
        'Kernel::GenericInterface::Requester',
        ref $RequesterObject,
        "$Test->{Name} - Create requester object",
    );

    # start requester with our webservice
    my $RequesterResult = $RequesterObject->Run(
        WebserviceID => $WebserviceID,
        Invoker      => $Test->{Operation},
        Data         => {
            SessionID => $NewSessionID,
            %{ $Test->{RequestData} },
            }
    );

    # check result
    $Self->Is(
        'HASH',
        ref $RequesterResult,
        "$Test->{Name} - Requester result structure is valid",
    );

    $Self->Is(
        $RequesterResult->{Success},
        $Test->{SuccessRequest},
        "$Test->{Name} - Requester successful result",
    );

    #    # workaround because results from direct call and
    #    # from SOAP call are a little bit different
    #    if ( $Test->{Operation} eq 'TicketSearch' ) {
    #
    #        if ( ref $LocalResult->{Data}->{Item} eq 'ARRAY' ) {
    #            for my $Item ( @{ $LocalResult->{Data}->{Item} } ) {
    #                for my $Key ( keys %{ $Item->{Ticket} } ) {
    #                    if ( !$Item->{Ticket}->{$Key} ) {
    #                        $Item->{Ticket}->{$Key} = '';
    #                    }
    #                    if ( $Key eq 'Age' ) {
    #                        delete $Item->{Ticket}->{$Key};
    #                    }
    #                }
    #            }
    #        }
    #
    #        if (
    #            defined $RequesterResult->{Data}
    #            && defined $RequesterResult->{Data}->{Item}
    #            )
    #        {
    #            if ( ref $RequesterResult->{Data}->{Item} eq 'ARRAY' ) {
    #                for my $Item ( @{ $RequesterResult->{Data}->{Item} } ) {
    #                    for my $Key ( keys %{ $Item->{Ticket} } ) {
    #                        if ( !$Item->{Ticket}->{$Key} ) {
    #                            $Item->{Ticket}->{$Key} = '';
    #                        }
    #                        if ( $Key eq 'Age' ) {
    #                            delete $Item->{Ticket}->{$Key};
    #                        }
    #                    }
    #                }
    #            }
    #            elsif ( ref $RequesterResult->{Data}->{Item} eq 'HASH' ) {
    #                for my $Key ( keys %{ $RequesterResult->{Data}->{Item}->{Ticket} } ) {
    #                    if ( !$RequesterResult->{Data}->{Item}->{Ticket}->{$Key} ) {
    #                        $RequesterResult->{Data}->{Item}->{Ticket}->{$Key} = '';
    #                    }
    #                    if ( $Key eq 'Age' ) {
    #                        delete $RequesterResult->{Data}->{Item}->{Ticket}->{$Key};
    #                    }
    #                }
    #            }
    #        }
    #
    #    }

    # remove ErrorMessage parameter from direct call
    # result to be consistent with SOAP call result
    if ( $LocalResult->{ErrorMessage} ) {
        delete $LocalResult->{ErrorMessage};
    }

    $Self->IsDeeply(
        $RequesterResult,
        $Test->{ExpectedReturnRemoteData},
        "$Test->{Name} - Requester success status (needs configured and running webserver)",
    );

    if ( $Test->{ExpectedReturnLocalData} ) {
        $Self->IsDeeply(
            $LocalResult,
            $Test->{ExpectedReturnLocalData},
            "$Test->{Name} - Local result matched with expected local call result.",
        );
    }
    else {
        $Self->IsDeeply(
            $LocalResult,
            $Test->{ExpectedReturnRemoteData},
            "$Test->{Name} - Local result matched with remote result.",
        );
    }

}    #end loop

# clean up webservice
my $WebserviceDelete = $WebserviceObject->WebserviceDelete(
    ID     => $WebserviceID,
    UserID => $UserID,
);
$Self->True(
    $WebserviceDelete,
    "Deleted Webservice $WebserviceID",
);

# delete the ticket
my $TicketDelete = $TicketObject->TicketDelete(
    TicketID => $TicketID,
    UserID   => 1,
);

# sanity check
$Self->True(
    $TicketDelete,
    "TicketDelete() successful for Ticket ID $TicketID",
);

1;
