#!/usr/bin/env perl
use strict;
use warnings;
use HTTP::Tiny;
use JSON qw(decode_json encode_json);
use MIME::Base64 qw(encode_base64);
use Time::HiRes qw(sleep);

my $base     = $ENV{VSPHERE_BASE}     // 'https://localhost';
my $user     = $ENV{VSPHERE_USER}     // 'administrator@vsphere.local';
my $password = $ENV{VSPHERE_PASSWORD} // 'VMware1!';
my $vm_name  = $ENV{VSPHERE_VM_NAME}  // 'perl-lab-01';

# Lab self-signed certificate only — do not disable verification against a real vCenter.
my $http = HTTP::Tiny->new(timeout => 60, verify_SSL => 0);

sub api {
    my ($method, $path, %opts) = @_;
    my $res = $http->request($method, "$base$path", \%opts);
    die "$method $path failed: $res->{status} $res->{content}\n" unless $res->{success};
    return $res->{content};
}

sub json_field {
    my ($body, $field) = @_;
    my $data = decode_json($body);
    return $data->{$field};
}

sub wait_task {
    my ($task, $headers) = @_;
    return unless $task;
    my $deadline = time + 120;
    while (time < $deadline) {
        my $body = api('GET', "/api/cis/tasks/$task", headers => $headers);
        my $status = json_field($body, 'status');
        return if $status eq 'SUCCEEDED' || $status eq 'FAILED';
        sleep(0.3);
    }
    die "timeout waiting for task $task\n";
}

my $auth = 'Basic ' . encode_base64("$user:$password", '');
my $session_body = api('POST', '/api/session', headers => { Authorization => $auth });
(my $session_id = $session_body) =~ s/^"(.*)"$/$1/;
print "session: $session_id\n";

my %headers = ('vmware-api-session-id' => $session_id);

my $vms_before = api('GET', '/api/vcenter/vm', headers => \%headers);
print 'vms before: ', scalar(@{ decode_json($vms_before) }), "\n";

my $create_body = encode_json({
    name      => $vm_name,
    guest_OS  => 'OTHER_GUEST_64',
    placement => {
        folder        => 'group-v23',
        host          => 'host-11',
        datastore     => 'datastore-31',
        resource_pool => 'resgroup-22',
    },
    cpu    => { count => 1 },
    memory => { size_MiB => 512 },
});
my $created = api(
    'POST', '/api/vcenter/vm',
    headers => { %headers, 'Content-Type' => 'application/json' },
    content => $create_body,
);
(my $moid = $created) =~ s/^"(.*)"$/$1/;
print "created: $moid\n";

my $power = api('POST', "/api/vcenter/vm/$moid/power?action=start", headers => \%headers);
wait_task(json_field($power, 'task'), \%headers);

my $detail = api('GET', "/api/vcenter/vm/$moid", headers => \%headers);
print 'power_state: ', json_field($detail, 'power_state'), "\n";

$power = api('POST', "/api/vcenter/vm/$moid/power?action=stop", headers => \%headers);
wait_task(json_field($power, 'task'), \%headers);

api('DELETE', "/api/vcenter/vm/$moid", headers => \%headers);
api('DELETE', '/api/session', headers => \%headers);
print "ok\n";
