<?php


namespace ModulesGarden\ProxmoxAddon\App\Jobs\Vps;


use MGProvision\Proxmox\v2\models\Kvm;
use MGProvision\Proxmox\v2\models\Snapshot;
use MGProvision\Proxmox\v2\repository\SnapshotRepository;
use ModulesGarden\ProxmoxAddon\App\Models\SnapshotJob;
use ModulesGarden\ProxmoxAddon\App\Services\Vps\ProductService;
use ModulesGarden\ProxmoxAddon\App\Enum\Vps\ConfigurableOption;

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"));
        if ($this->isDone())
        {
            return true;
        }
        elseif ($this->isTaskRunning())
        {
            //sleep
            $this->sleep(25);
            return false;
        }
        syslog(LOG_NOTICE,"Snapshot Create for " . $this->model->id );
        $snapshot = new Snapshot();
        $snapshot->setApi($this->api());
        $snapshot->setPath($this->vm()->getPath() . "/snapshot");
        $snapshot->setAttributes([
            "name"        => $this->getSnapshotJob()->name . "_" . date("m") . "_" . date("d") . "_" . date("H") . "_" . date("i"),
            "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 ) && $this->vm() instanceof  Kvm)
        {
            $snapshot->setVmstate($this->snapshotJob->vmstate );
        }
        try {
    	    $taskId =  $snapshot->create();
        } catch(\Exception $ex) {
    	    $message = $ex->getMessage();
    	    syslog(LOG_NOTICE,"!!Snapshot throw Exception: " . $message );
    	    if (strpos($message,"snapshot") === false && strpos($message,"already") === false && strpos($message,"used") === false ) {
    	        throw $ex;
    	    }
        }
        $this->sleep(25);
        $this->clean();
        $this->sleep(5);
        //save task id
        $this->putModelDataAndSave(["taskId" => $taskId, "node" => $this->vm()->getNode()]);
        //sleep
        syslog(LOG_NOTICE,"Snapshot Processing DONE" );
        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());
        syslog(LOG_NOTICE,"   Checking Snapshot Limit (" . $limit . ") for " . $this->model->id );
        if($limit=="-1"){
            return;
        }
        if(!$limit || !is_numeric($limit)){
            throw new \InvalidArgumentException("Snapshot limit cannot be empty");
        }
        $snapshotRepository = new SnapshotRepository();
        $snapshotRepository->setApi($this->api());
        $snapshotRepository->findByVm($this->vm());
        $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() );
                try {
	            $result = $entity->delete();
	            //syslog(LOG_NOTICE,"   ->RESULT " . print_r($result,true) );

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