<?php

/* * ********************************************************************
 * ProxmoxAddon product developed. (Sep 19, 2018)
 * *
 *
 *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
 *  CONTACT                        ->       contact@modulesgarden.com
 *
 *
 * This software is furnished under a license and may be used and copied
 * only  in  accordance  with  the  terms  of such  license and with the
 * inclusion of the above copyright notice.  This software  or any other
 * copies thereof may not be provided or otherwise made available to any
 * other person.  No title to and  ownership of the  software is  hereby
 * transferred.
 *
 *
 * ******************************************************************** */

namespace ModulesGarden\ProxmoxAddon\App\Cron;

use Illuminate\Database\Capsule\Manager as DB;
use MGProvision\Proxmox\v2 as proxmox;
use ModulesGarden\ProxmoxAddon as main;
use ModulesGarden\ProxmoxAddon\Core\CommandLine\Command;
use ModulesGarden\ProxmoxAddon\Core\CommandLine\Hypervisor;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

/**
 * Description of RecoveryList
 *
 * @author Pawel Kopec <pawelk@modulesgardne.com>
 */
class RecoveryList extends Command
{

    use main\App\Services\BaseService;
    /**
     * Command name
     * @var string
     */
    protected $name = 'recoveryList';

    /**
     * Command description
     * @var string
     */
    protected $description = '';

    /**
     * Command help text
     * @var string
     */
    protected $help = '';

    protected function process(InputInterface $input, OutputInterface $output, SymfonyStyle $io)
    {
        $io->title('Synchronize recovery list: Starting');
        if (!function_exists('ModuleBuildParams'))
        {
            require_once ROOTDIR . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . "modulefunctions.php";
        }
        $activeHostings = [];
        $activeVservers = [];
        //Get Hostings
        $h        = (new main\Core\Models\Whmcs\Hosting)->getTable();
        $s        = (new main\Core\Models\Whmcs\Server)->getTable();
        $hostings = main\Core\Models\Whmcs\Hosting::select("{$h}.*")
            ->rightJoin($s, "{$h}.server", '=', "{$s}.id")
            ->where("{$h}.domainstatus", "Active")
            ->whereIn("{$s}.type", ["proxmoxVPS", "ProxmoxCloudVps"])
            ->orderBy("{$h}.server");
        $i        = 0;
        foreach ($hostings->get() as $hosting)
        {
            /* @var $hosting main\Core\Models\Whmcs\Hosting */
            $i++;
            try
            {
                $activeHostings[] = (int)$hosting->id;
                $params           = \ModuleBuildParams($hosting->id);
                $this->setServerId($hosting->server);
                if ($this->getServer()->id != $this->getServerId())
                {
                    unset($this->server, $this->api);
                }
                $this->getApi()->setInstance();
                if ($params['moduletype'] == "proxmoxVPS")
                {
                    if (!$params['customfields']['vmid'])
                    {
                        throw new \Exception("Custom Field \"vmid\" is empty");
                    }
                    if (!$params['customfields']['node'])
                    {
                        throw new \Exception("Custom Field \"node\" is empty");
                    }
                    $virtualization = \json_decode(DB::table('ProxmoxAddon_ProductConfiguration')
                        ->where('product_id', $hosting->packageid)
                        ->where('setting', 'virtualization')
                        ->value('value'));
                    $vm             = proxmox\Factory::vmVps($virtualization, $params);
                    if (main\App\Models\RecoveryVm::where('service_id', $hosting->id)->count())
                    {
                        $recovery = main\App\Models\RecoveryVm::where('service_id', $hosting->id)->first();
                    }
                    else
                    {
                        $recovery = new main\App\Models\RecoveryVm();
                    }
                    $recovery->client_id      = $hosting->userid;
                    $recovery->service_id     = $hosting->id;
                    $recovery->server_id      = $this->getServer()->id;
                    $recovery->vserver_id     = 0;
                    $recovery->last_update    = date('Y-m-d H:i:s', strtotime('now'));
                    $recovery->status         = json_encode($vm->status());
                    $recovery->config         = json_encode($vm->config());
                    $recovery->virtualization = $vm->getVirtualization();
                    $recovery->vmid           = $vm->getVmid();
                    $recovery->node           = $vm->getNode();
                    try
                    {
                        $recovery->dns = json_encode($vm->node()->getDns());
                    }
                    catch (\Exception $ex)
                    {
                        $recovery->dns = "Error: " . $ex->getMessage();
                    }
                    $recovery->save();
                }
                else
                {
                    if ($params['moduletype'] == "ProxmoxCloudVps")
                    {
                        $vservers = main\App\Models\VmModel::ofHostingId($hosting->id);
                        foreach ($vservers->get() as $vserver)
                        {
                            $activeVservers[] = $vserver->id;

                            $vm               =  (new proxmox\VmFactory())->fromVmModel($vserver);
                            if (main\App\Models\RecoveryVm::where('service_id', $hosting->id)->where('vserver_id', $vserver->id)->count())
                            {
                                $recovery = main\App\Models\RecoveryVm::where('service_id', $hosting->id)->where('vserver_id', $vserver->id)->first();
                            }
                            else
                            {
                                $recovery = new main\App\Models\RecoveryVm();
                            }
                            $recovery->client_id      = $hosting->userid;
                            $recovery->service_id     = $hosting->id;
                            $recovery->server_id      = $this->getServer()->id;
                            $recovery->vserver_id     = $vserver->id;
                            $recovery->last_update    = date('Y-m-d H:i:s', strtotime('now'));
                            $recovery->status         = json_encode($vm->status());
                            $recovery->config         = json_encode($vm->config());
                            $recovery->virtualization = $vm->getVirtualization();
                            $recovery->vmid           = $vm->getVmid();
                            $recovery->node           = $vm->getNode();
                            try
                            {
                                $recovery->dns = json_encode($vm->node()->getDns());
                            }
                            catch (\Exception $ex)
                            {
                                $recovery->dns = "Error: " . $ex->getMessage();
                            }
                            $recovery->save();
                        }
                        $output->writeln(sprintf("Hosting: %s has been synchronized", $hosting->id));
                    }
                }
            }
            catch (\Exception $ex)
            {
                if ($hosting)
                {
                    $io->error("Hosting Id #{$hosting->id}, " . $ex->getMessage());
                }
                else
                {
                    $io->error($ex->getMessage());
                }
            }
            (new Hypervisor($this->getName(), $input->getOptions()))
                ->ping();
        }
        //Remove entries which does not exist  on $activeHostings
        if (!empty($activeHostings))
        {
            main\App\Models\RecoveryVm::whereNotIn('service_id', $activeHostings)->delete();
        }
        //Remove entries which does not exist  on $activeVservers
        if (!empty($activeVservers))
        {
            $activeVservers[] = '0';
            main\App\Models\RecoveryVm::whereNotIn('vserver_id', $activeVservers)->delete();
        }
        $output->writeln("");
        $io->success([
            sprintf("Synchronize recovery list: %s Entries Processed.", $i),
            "Synchronize recovery list: Done"
        ]);
    }
}
