<?php


namespace ModulesGarden\ProxmoxAddon\App\Jobs\Cloud;


use MGProvision\Proxmox\v2\models\Kvm;
use MGProvision\Proxmox\v2\models\Snapshot;
use MGProvision\Proxmox\v2\repository\SnapshotRepository;
use ModulesGarden\ProxmoxAddon\App\Jobs\BaseJob;
use ModulesGarden\ProxmoxAddon\App\Models\SnapshotJob;
use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
use ModulesGarden\ProxmoxAddon\App\Enum\Cloud\ConfigurableOption;
use function ModulesGarden\ProxmoxAddon\Core\Helper\sl;

class SnapshotVmJob extends BaseJob
{

    use ProductService;

    /**
     * @var SnapshotJob
     */
    private  $snapshotJob;

    public function handle($text = null)
    {
        openlog("ProxmoxSnapshot", LOG_PID, LOG_SYSLOG);
        $this->initParams();
        $this->setHostingId($this->getWhmcsParamByKey("serviceid"));
        $this->initVm();
        if ($this->isDone())
        {
            return true;
        }
        elseif ($this->isTaskRunning())
        {
            //sleep
            $this->sleep(5);
            return false;
        }
        $snapshot = new Snapshot();
        $snapshot->setApi($this->api());
        $snapshot->setPath(sl('Vm')->getVm()->getPath() . "/snapshot");
        $snapshot->setAttributes([
            // "name"        => $this->getSnapshotJob()->name."_".$this->model->id,
            // Changed by Roland at 2021-08-28 because duplicate snappshot names which causes the error: TASK ERROR: snapshot name 'Secure_280' already used
            // Added ' "_" . date("m") . "_" . date("d") . "_" . date("H"),' to make the snapshot-name more unique
            "name"        => $this->getSnapshotJob()->name . "_" . $this->model->id . "_" . date("m") . "_" . date("d") . "_" . date("H"),
            "description" => $this->snapshotJob->description,
        ]);
        syslog(LOG_NOTICE,"Creating Snapshot for " . $this->getSnapshotJob()->name . "_" . $this->model->id . date("m") . "_" . date("d") . "_" . date("H"));
        if (!is_null($this->snapshotJob->vmstate ) && sl('Vm')->getVm() instanceof  Kvm)
        {
            $snapshot->setVmstate($this->snapshotJob->vmstate );
        }
        $taskId =  $snapshot->create();
        //save task id
        $this->putModelDataAndSave(["taskId" => $taskId, "node" => sl('Vm')->getVm()->getNode()]);
        //sleep
        $this->sleep(5);
        $this->clean();
        $this->sleep(25);
        return false;
    }

    /**
     * @return SnapshotJob
     */
    private  function getSnapshotJob(){
        return $this->snapshotJob = SnapshotJob::findOrFail($this->getModelData()['snapshotJobId']);
    }

    private function clean(){
        syslog(LOG_NOTICE,"Snapshot Clean for " . $this->model->id );
        $limit = $this->getWhmcsConfigOption(ConfigurableOption::SNAPSHOTS, $this->configuration()->getSnapshotMaxFiles());
        if($limit=="-1") {
            return;
        }
        syslog(LOG_NOTICE,"   Checking Snapshot Limit (" . $limit . ") for " . $this->model->id );
        if(!$limit || !is_numeric($limit)) {
            throw new \InvalidArgumentException("Snapshot limit cannot be empty");
        }
        $snapshotRepository = new SnapshotRepository();
        $snapshotRepository->setApi($this->api());
        $snapshotRepository->findByVm(sl('Vm')->getVm());
        $snapshotRepository->ignoreCurrent(true);
        if($snapshotRepository->count() < $limit) {
            return;
        }
        $toDelete = (int) $snapshotRepository->count() - $limit;
        syslog(LOG_NOTICE,"   Snapshots: Existing: " . $snapshotRepository->count() . "   Limit: " . $limit );
        syslog(LOG_NOTICE,"   Number of Snapshots to delete: " . $toDelete );
        foreach ($snapshotRepository->sortBySnaptime()->fetch() as $entity) {
            syslog(LOG_NOTICE,"   Checking Snapshot: " . $entity->getName() . " (" . $entity->getPath() . ")" );
            if($toDelete <=0) {
            	    break;
    	    }
            $errorCount = 0;
            $errorMessage = "NOT EMPTY";
            while(!empty($errorMessage) && $errorCount < 18) {
                syslog(LOG_NOTICE,"   ->Delete Snapshot: " . $entity->getName() );
                while(!empty($errorMessage) && $errorCount < 18) {
                    try {
                        $result = $entity->delete();
                        //syslog(LOG_NOTICE,"   ->RESULT " . print_r($result,true) );

                        $errorMessage = "";
                        syslog(LOG_NOTICE,"   ->SUCCESS " . $result );
                        sleep(55);
                    } catch(\Exception $ex) {
                        $errorMessage = $ex->getMessage();
                        syslog(LOG_NOTICE,"   ->ERROR " . $errorCount . ": " . $errorMessage );
                        $errorCount ++;
                        sleep(55);
                    }
                }
            $toDelete --;
            }
        }
    syslog(LOG_NOTICE,"Snapshot Clean DONE" );
    }
}
