<?php


namespace ModulesGarden\ProxmoxAddon\App\Cron;


use MGProvision\Proxmox\v2\repository\FileRepository;
use ModulesGarden\ProxmoxAddon\App\Models\ProductConfiguration;
use ModulesGarden\ProxmoxAddon\App\Models\VmModel;
use ModulesGarden\ProxmoxAddon\App\Models\Whmcs\Hosting;
use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
use ModulesGarden\ProxmoxAddon\App\Services\Vps\ProductService;
use ModulesGarden\ProxmoxAddon\Core\CommandLine\Command;
use ModulesGarden\ProxmoxAddon\Core\CommandLine\Hypervisor;
use ModulesGarden\ProxmoxAddon\Core\Models\Whmcs\Server;
use ModulesGarden\ProxmoxAddon\Core\UI\Traits\WhmcsParams;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use function ModulesGarden\ProxmoxAddon\Core\Helper\di;
use ModulesGarden\ProxmoxAddon\App\Enum\Vps;
use ModulesGarden\ProxmoxAddon\App\Enum\Cloud;

class BackupRemove extends Command
{
    use WhmcsParams;
    use ProductService;
    use ApiService;

    /**
     * Command name
     * @var string
     */
    protected $name = 'remove-backups';

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

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

    protected $input;
    protected $output;
    protected $io;

    protected function process(InputInterface $input, OutputInterface $output, SymfonyStyle $io)
    {
        $this->input = $input;
        $this->output = $output;
        $this->io = $io;
        $io->title('Update Backups: Starting');
        if (!function_exists('ModuleBuildParams'))
        {
            require_once ROOTDIR . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . "modulefunctions.php";
        }
        $pc = (new ProductConfiguration())->getTable();

        $productIds = ProductConfiguration::pluck("product_id")
            ->all();
        if (empty($productIds))
        {
            $io->error("Store The Backup For X Days is not configured");
            return;
        }
        $h        = (new Hosting())->getTable();
        $s        = (new Server())->getTable();
        $hostings = Hosting::select("{$h}.id", "{$h}.packageid", "{$h}.lastupdate", "{$h}.bwusage", "{$h}.bwlimit", "{$h}.regdate")
            ->rightJoin($s, "{$h}.server", '=', "{$s}.id")
            ->where("{$h}.domainstatus", "Active")
            ->whereIn("{$h}.packageid", $productIds)
            ->whereIn("{$s}.type", ["proxmoxVPS", "ProxmoxCloudVps" ])
            ->orderBy("{$h}.server");
        $i        = 0;


        /**
         * @var Hosting $hosting
         */
        foreach ($hostings->get() as $hosting)
        {
            $i++;
            $output->writeln(sprintf("Synchronize hosting: %s", $hosting->id));
            try
            {
                $params = \ModuleBuildParams($hosting->id);
                $method = lcfirst($params['moduletype'])."Process";
                if(!method_exists($this,  $method )){
                    continue;
                }
                $this->{$method}($params);
                $output->writeln(sprintf("Hosting: %s has been synchronized", $hosting->id));
            }
            catch (\Exception $ex)
            {
                $msg = $ex->getMessage();
                if ($hosting)
                {
                    $msg = sprintf("Hosting Id #%s, %s", $hosting->id, $ex->getMessage());
                }
                $io->error($msg);
            }
            (new Hypervisor($this->getName(), $input->getOptions()))
                ->ping();
        }
        $output->writeln("");
        $io->success([
            sprintf("Synchronize hostings: %s Entries Processed.", $i),
            "Update Backups: Done"
        ]);
    }

    private function proxmoxVPSProcess($params){
        if (!$params['customfields'][Vps\CustomField::VMID])
        {
            throw new \Exception("Custom Field \"vmid\" is empty");
        }
        if (!$params['customfields'][Vps\CustomField::NODE])
        {
            throw new \Exception("Custom Field \"node\" is empty");
        }
        $whmcsParams = di('whmcsParams');
        $whmcsParams->setParams($params);
        unset($this->vm, $this->api, $this->configuration);
        $storage        = $this->configuration()->getBackupStorage() ? $this->configuration()->getBackupStorage() : 'local';

                logModuleCall(
                    'ProxmoxCloudVps',
                    __FUNCTION__,
                    $storage,
                    'Debug remove Backup Cron',
                    $this->configuration()
                );

        $fileRepository = new FileRepository();
        $fileRepository->setApi($this->api());
        $fileRepository->findBackup($this->vm())
            ->findByStorages([$storage]);
        if($this->configuration()->getBackupStoreDays()){
            foreach ($fileRepository->fetch() as $id => $backup)
            {
                $matches = [];
                preg_match('/[0-9]{4}_[0-9]{2}_[0-9]{2}/', $backup->getVolid(), $matches);
                $dateCreated = str_replace("_", "-", $matches[0]);
                if (!$dateCreated)
                {
                    continue;
                }
                $dateCreated = new \DateTime($dateCreated);
                $now         = new \DateTime();
                $dDiff       = $dateCreated->diff($now);
                if ($dDiff->days > $this->configuration()->getBackupStoreDays())
                {
                    $backup->delete();
                    $fileRepository->remove($id);
                    $this->output->writeln(sprintf("Backup with date %s has been deleted", $params['serviceid'], $backup->getDate()));
                }
            }
        }
        $sizeMax = $this->getWhmcsConfigOption(Vps\ConfigurableOption::BACKUPS_SIZE,  $this->configuration()->getBackupMaxSize());
        if($sizeMax && $sizeMax!="-1" && $fileRepository->getSizeInGb() > $sizeMax){
            $this->output->writeln(sprintf("The maximum size set for a backup has been exceeded of %s GB", $fileRepository->getSizeInGb()- $sizeMax ));
            foreach ($fileRepository->sortByTime()->fetch() as $id => &$backup)
            {
                if($fileRepository->getSizeInGb() <= $sizeMax){
                    break;
                }
                $this->output->writeln(sprintf("Backup with date %s %s has been deleted", $backup->getDate(), $backup->getHour()));
                $fileRepository->remove($id);
                $backup->delete();
            }
        }
        $limitMax = $this->getWhmcsConfigOption(Vps\ConfigurableOption::BACKUPS_FILES,  $this->configuration()->getBackupMaxFiles());
        if($limitMax && $limitMax!="-1" && $fileRepository->count() > $limitMax){
            $this->output->writeln(sprintf("The maximum number set for a backup has been exceeded of %s", $fileRepository->count() - $limitMax ));
            foreach ($fileRepository->sortByTime()->fetch() as $id => &$backup)
            {
                if($fileRepository->count() <= $limitMax){
                    break;
                }
                $this->output->writeln(sprintf("Backup with date %s %s has been deleted", $params['serviceid'], $backup->getDate(), $backup->getHour()));
                $fileRepository->remove($id);
                $backup->delete();
            }
        }
    }

    private function proxmoxCloudVpsProcess($params){
        $whmcsParams = di('whmcsParams');
        $whmcsParams->setParams($params);
        unset($this->vm, $this->api, $this->configuration);
        $storage        = $this->configuration()->getBackupStorage() ? $this->configuration()->getBackupStorage() : 'local';
        $fileRepository = new FileRepository();
        $fileRepository->setApi($this->api());
        $fileRepository->findBackupByVmModel(VmModel::ofHostingId($params['serviceid'])->get())
                      ->findByStorages([$storage]);
        if($this->configuration()->getBackupStoreDays()){
            foreach ($fileRepository->fetch() as $id => $backup)
            {
                $matches = [];
                preg_match('/[0-9]{4}_[0-9]{2}_[0-9]{2}/', $backup->getVolid(), $matches);
                $dateCreated = str_replace("_", "-", $matches[0]);
                if (!$dateCreated)
                {
                    continue;
                }
                $dateCreated = new \DateTime($dateCreated);
                $now         = new \DateTime();
                $dDiff       = $dateCreated->diff($now);
                if ($dDiff->days > $this->configuration()->getBackupStoreDays())
                {
                    $backup->delete();
                    $fileRepository->remove($id);
                    $this->output->writeln(sprintf("Backup with date %s has been deleted", $params['serviceid'], $backup->getDate()));
                }
            }
        }
        $sizeMax = $this->getWhmcsConfigOption(Cloud\ConfigurableOption::BACKUPS_SIZE,  $this->configuration()->getBackupMaxSize());
        if($sizeMax && $sizeMax!="-1" && $fileRepository->getSizeInGb() > $sizeMax){
            $this->output->writeln(sprintf("The maximum size set for a backup has been exceeded of %s GB", $fileRepository->getSizeInGb()- $sizeMax ));
            foreach ($fileRepository->sortByTime()->fetch() as $id => &$backup)
            {
                if($fileRepository->getSizeInGb() <= $sizeMax){
                    break;
                }
                $this->output->writeln(sprintf("Backup with date %s %s has been deleted", $params['serviceid'], $backup->getDate(), $backup->getHour()));
                $fileRepository->remove($id);
                $backup->delete();
            }
        }
        $limitMax = $this->getWhmcsConfigOption(Cloud\ConfigurableOption::BACKUPS_FILES,  $this->configuration()->getBackupMaxFiles());
        if($limitMax && $limitMax!="-1" && $fileRepository->count() > $limitMax){
            $this->output->writeln(sprintf("The maximum number set for a backup has been exceeded of %s", $fileRepository->count() - $limitMax ));
            foreach ($fileRepository->sortByTime()->fetch() as $id => &$backup)
            {
                if($fileRepository->count() <= $limitMax){
                    break;
                }
                $this->output->writeln(sprintf("Backup with date %s %s has been deleted", $backup->getDate(), $backup->getHour()));
                $fileRepository->remove($id);
                $backup->delete();
            }
        }


    }

}