#!/usr/bin/perl

use strict;
use warnings;
use lib 't/lib';

use English qw(-no_match_vars);
use Test::Deep;
use Test::Exception;
use Test::More;
use JSON;

use GLPI::Agent::Logger;
use GLPI::Agent::Version;
use GLPI::Agent::XML::Response;

use GLPI::Agent::Protocol::Inventory;

my $deviceid = "device-id-123456789";
my %inventories = (
    # each case: case_name => {
    #   content  => { INVENTORY HASH as generated by Inventory task },
    #   expected => { resulting hash after being normalized and json decoded },
    #   itemtype => "Computer"
    # }
    "simple" => {
        content     => {
            BIOS    => {
                BDATE   => "2021-06-25",
            }
        },
        expected    => {
            action      => "inventory",
            deviceid    => $deviceid,
            itemtype    => "Computer",
            content     => {
                bios    => {
                    bdate   => "2021-06-25",
                }
            }
        },
        itemtype    => "Computer",
    },
    "bdate fix" => {
        content     => {
            BIOS    => {
                BDATE   => "25/06/2021",
            }
        },
        expected    => {
            action      => "inventory",
            deviceid    => $deviceid,
            itemtype    => "Computer",
            content     => {
                bios    => {
                    bdate   => "2021-06-25",
                }
            }
        },
        itemtype    => "Computer",
    },
    "bdate fix with assettag cleanup" => {
        content     => {
            BIOS    => {
                BDATE   => "25/06/2021",
                ASSETTAG => undef
            }
        },
        expected    => {
            action      => "inventory",
            deviceid    => $deviceid,
            itemtype    => "Computer",
            content     => {
                bios    => {
                    bdate   => "2021-06-25",
                }
            }
        },
        itemtype    => "Computer",
    },
    "antivirus boolean" => {
        content     => {
            ANTIVIRUS   => {
                ENABLED => "1",
            }
        },
        expected    => {
            action      => "inventory",
            deviceid    => $deviceid,
            itemtype    => "Computer",
            content     => {
                antivirus   => {
                    enabled => $JSON::true,
                }
            }
        },
        itemtype    => "Computer",
    },
    "antivirus boolean with fixed expiration" => {
        content     => {
            ANTIVIRUS   => {
                ENABLED     => "1",
                EXPIRATION  => "2021-06-25 17:12:33",
            }
        },
        expected    => {
            action      => "inventory",
            deviceid    => $deviceid,
            itemtype    => "Computer",
            content     => {
                antivirus   => {
                    enabled     => $JSON::true,
                    expiration  => "2021-06-25",
                }
            }
        },
        itemtype    => "Computer",
    },
    "antivirus boolean with fixed expiration (2)" => {
        content     => {
            ANTIVIRUS   => {
                ENABLED     => 0,
                EXPIRATION  => "25/06/2021",
            }
        },
        expected    => {
            action      => "inventory",
            deviceid    => $deviceid,
            itemtype    => "Computer",
            content     => {
                antivirus   => {
                    enabled     => $JSON::false,
                    expiration  => "2021-06-25",
                }
            }
        },
        itemtype    => "Computer",
    },
    "antivirus boolean and wrong expiration" => {
        content     => {
            ANTIVIRUS   => {
                ENABLED     => "1",
                EXPIRATION  => "never",
            }
        },
        expected    => {
            action      => "inventory",
            deviceid    => $deviceid,
            itemtype    => "Computer",
            content     => {
                antivirus   => {
                    enabled     => $JSON::true,
                }
            }
        },
        itemtype    => "Computer",
    },
    "process" => {
        content     => {
            PROCESSES   => {
                STARTED => "0000-00-00 00:00",
                PID     => "001",
            }
        },
        expected    => {
            action      => "inventory",
            deviceid    => $deviceid,
            itemtype    => "Computer",
            content     => {
                processes   => {
                    started => "0000-00-00 00:00:00",
                    pid     => 1,
                }
            }
        },
        itemtype    => "Computer",
    },
    "process with date" => {
        content     => {
            PROCESSES   => {
                STARTED => "25/06/2021",
                PID     => "001",
            }
        },
        expected    => {
            action      => "inventory",
            deviceid    => $deviceid,
            itemtype    => "Computer",
            content     => {
                processes   => {
                    started => "2021-06-25 00:00:00",
                    pid     => 1,
                }
            }
        },
        itemtype    => "Computer",
    },
    "process and wrong dateordatetime" => {
        content     => {
            PROCESSES   => {
                STARTED => "at boot",
                PID     => "001",
            }
        },
        expected    => {
            action      => "inventory",
            deviceid    => $deviceid,
            itemtype    => "Computer",
            content     => {
                processes   => {
                    pid     => 1,
                }
            }
        },
        itemtype    => "Computer",
    },
    "storage" => {
        content     => {
            STORAGES   => {
                DISKSIZE    => "128000",
                NAME        => "C:",
                INTERFACE   => "ide"
            }
        },
        expected    => {
            action      => "inventory",
            deviceid    => $deviceid,
            itemtype    => "Computer",
            content     => {
                storages    => {
                    interface   => "IDE",
                    name        => "C:",
                    disksize    => 128000,
                }
            }
        },
        itemtype    => "Computer",
    },
    "vm" => {
        content     => {
            VIRTUALMACHINES => {
                VCPU    => "16",
                NAME    => "Glpi",
                STATUS  => "Down"
            }
        },
        expected    => {
            action      => "inventory",
            deviceid    => $deviceid,
            itemtype    => "Computer",
            content     => {
                virtualmachines => {
                    vcpu    => 16,
                    name    => "Glpi",
                    status  => "down",
                }
            }
        },
        itemtype    => "Computer",
    },
    "vms and one with undefined memory" => {
        content     => {
            VIRTUALMACHINES => [
            {
                VCPU    => "16",
                NAME    => "Glpi",
                STATUS  => "Down"
            },{
                VCPU    => "0032",
                NAME    => "Glpi32",
                STATUS  => "UP",
                MEMORY  => undef
            }]
        },
        expected    => {
            action      => "inventory",
            deviceid    => $deviceid,
            itemtype    => "Computer",
            content     => {
                virtualmachines => [
                {
                    vcpu    => 16,
                    name    => "Glpi",
                    status  => "down",
                },{
                    vcpu    => 32,
                    name    => "Glpi32",
                    status  => "up",
                }]
            }
        },
        itemtype    => "Computer",
    },
);

plan tests => 7 + 3*keys(%inventories);

my $logger = GLPI::Agent::Logger->new(
    logger => [ 'Test' ]
);

my $inventory;

lives_ok {
    $inventory = GLPI::Agent::Protocol::Inventory->new(
        logger      => $logger,
        deviceid    => $deviceid,
        content     => {},
        itemtype    => "empty",
    );
} "empty inventory";

isa_ok($inventory, "GLPI::Agent::Protocol::Inventory");

is($inventory->get("itemtype"), "empty", "Inventory request: get itemtype");
is($inventory->get("deviceid"), $deviceid, "Inventory request: get deviceid");

my $content;
lives_ok {
    $content = $inventory->getContent();
} "Inventory request: get content access";

my $decoded_content;
lives_ok {
    $decoded_content = JSON::decode_json($content);
} "Inventory request: content must be a JSON";

my $expected_content = {
    deviceid    => $deviceid,
    action      => "inventory",
    itemtype    => "empty",
    content     => {},
};

cmp_deeply($decoded_content, $expected_content, "Inventory message: empty content check");

my $answer;
foreach my $case (keys(%inventories)) {
    my $content  = $inventories{$case}->{content};
    my $expected = $inventories{$case}->{expected};
    lives_ok {
        $inventory = GLPI::Agent::Protocol::Inventory->new(
            logger      => $logger,
            deviceid    => $deviceid,
            content     => $content,
            itemtype    => $inventories{$case}->{type} // "Computer",
        );
        $inventory->normalize();
    } "$case inventory";
    cmp_deeply(
        JSON::decode_json($inventory->getContent()),
        $expected,
        "$case inventory message check"
    );
    is($inventory->get('itemtype'), $inventories{$case}->{type} // "Computer", "$case item type");
}
