<?php


namespace ModulesGarden\ProxmoxAddon\App\Services\Vps;

use MGProvision\Proxmox\v2\repository\BackupScheduleRepository;
use MGProvision\Proxmox\v2\repository\FileRepository;
use MGProvision\Proxmox\v2\repository\FirewallRulesRepository;
use MGProvision\Proxmox\v2\repository\HardDiskRepostiory;
use MGProvision\Proxmox\v2\repository\MountPointRepostiory;
use MGProvision\Proxmox\v2\repository\SnapshotRepository;
use ModulesGarden\ProxmoxAddon\App\Models\SnapshotJob;
use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
use ModulesGarden\ProxmoxAddon\App\Services\Utility;
use ModulesGarden\ProxmoxAddon\App\Enum\Vps\ConfigurableOption;
use ModulesGarden\ProxmoxAddon\Core\UI\Traits\WhmcsParams;
use function ModulesGarden\Servers\ProxmoxVps\Core\Helper\sl;

class ResourceGuard
{
    use WhmcsParams;
    use ProductService;
    use ApiService;

    public function backupLimit()
    {
        //Backup repository
        $backupRepository = new FileRepository();
        $backupRepository->setApi($this->api());
        $backupRepository->findBackup($this->vm())
            ->findByStorages([$this->configuration()->getBackupStorage()]);
        //Files limit
        $maxFiles = $this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES,  $this->configuration()->getBackupMaxFiles()) ;
        if ($maxFiles != "-1"  && $this->configuration()->isBackupRouting())
        {
            $maxFiles++;
        }
        if ($maxFiles != "-1" && $backupRepository->count() >= $maxFiles)
        {
            throw new \Exception(sl("lang")->abtr("The maximum number of backup files has been exceeded. Please remove the old backup files."));
        }
        //Size limit
        $maxSize = $this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_SIZE,  $this->configuration()->getBackupMaxSize()) ;
        $used    = $backupRepository->size();
        Utility::unitFormat($used, "bytes", "gb");
        if ($maxSize != "-1" && $used >= $maxSize)
        {
            throw new \Exception(sl("lang")->abtr("The maximum size set for a backup has been exceeded. Please remove the old backup files."));
        }
    }

    public function hasBackupLimit()
    {
        try
        {
            $this->backupLimit();
            return true;
        }
        catch (\Exception $ex)
        {
            return false;
        }
    }

    public function backupJobLimit()
    {
        $this->backupLimit();
        //Backup repository
        $backupRepository = new BackupScheduleRepository();
        $backupRepository->setApi($this->api());
        $backupRepository->findByVm($this->vm());
        //Files limit
        $maxFiles = $this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES,  $this->configuration()->getBackupMaxFiles()) ;
        if ($maxFiles != "-1" && $backupRepository->count() >= $maxFiles)
        {
            throw new \Exception(sl("lang")->tr("The maximum number of backup files has been exceeded. Please remove the old backup files."));
        }
    }

    public function hasBackupJobLimit()
    {
        try
        {
            $this->backupJobLimit();
            return true;
        }
        catch (\Exception $ex)
        {
            return false;
        }
    }

    public function snapshotLimit()
    {
        $snapshotRepository = new SnapshotRepository();
        $snapshotRepository->setApi($this->api());
        $snapshotRepository->findByVm($this->vm());
        $snapshotRepository->ignoreCurrent(true);
        //Files limit
        $maxFiles = $this->getWhmcsConfigOption(ConfigurableOption::SNAPSHOTS, $this->configuration()->getSnapshotMaxFiles());
        if ($maxFiles != "-1" && $snapshotRepository->count() >= $maxFiles)
        {
            throw new \Exception(sl("lang")->tr("The maximum number of snapshots has been exceeded. Please remove the old snapshots."));
        }
    }

    public function hasSnapshotLimit()
    {
        try
        {
            $this->snapshotLimit();
            return true;
        }
        catch (\Exception $ex)
        {
            return false;
        }
    }


    public function snapshotJobLimit()
    {

        $max = $this->getWhmcsConfigOption(ConfigurableOption::SNAPSHOT_JOBS, $this->configuration()->getSnapshotJobs());
        if($max == "-1"){
            return;
        }
        $query = SnapshotJob::ofHostingId($this->getWhmcsParamByKey("serviceid"));
        if ($max != "-1" && $query->count() >= $max)
        {
            throw new \Exception(sl("lang")->tr("The maximum number of snapshot jobs has been exceeded. Please remove the old snapshot jobs."));
        }
    }

    public function hasSnapshotJobLimit()
    {
        try
        {
            $this->snapshotJobLimit();
            return true;
        }
        catch (\Exception $ex)
        {
            return false;
        }
    }

    public function firewallLimit($newRules=0)
    {
        $repository    = new FirewallRulesRepository();
        $repository->setApi($this->api());
        $repository->findByVm($this->vm());
        //Files limit
        $max = (int)$this->configuration()->getFirewallMaxRules();
        if ($max != "-1" && $repository->count()+$newRules > $max)
        {
            throw new \Exception(sl("lang")->tr("The maximum number of firewall rules has been exceeded. Please remove the old firewall rules."));
        }
    }

    public function hasfirewallLimit()
    {
        try
        {
            $this->firewallLimit();
            return true;
        }
        catch (\Exception $ex)
        {
            return false;
        }
    }

    public function mountPointLimit($newSize = 0, $excludeId = null)
    {
        //Max size
        $maxSize = $this->configuration()->getAdditionalDiskSize();//GB
        if ($this->isWhmcsConfigOption(ConfigurableOption::ADDITIONAL_DISKS_SIZE) )
        {
            $maxSize = $this->getWhmcsConfigOption(ConfigurableOption::ADDITIONAL_DISKS_SIZE);
            Utility::unitFormat($maxSize, $this->configuration()->getAdditionalDiskUnit(), "gb");
        }
        $repository = new MountPointRepostiory();
        $repository->setApi($this->api());
        $repository->findByPath($this->vm()->getPath() . '/config');
        if (!is_null($excludeId))
        {
            $repository->whereNotIn([$excludeId]);
        }
        $used = $repository->additionalSize();
        $free = $maxSize - $used;
        if ($maxSize != "-1"  && $newSize > $free)
        {
            throw new \Exception(sprintf(sl("lang")->tr("You are not able to set %s GB of disk size. Available disk size: %s GB"), $newSize, $free));
        }

    }

    public function hasMountPointLimit()
    {
        //Max size
        $maxSize = $this->configuration()->getAdditionalDiskSize();//GB
        if ($this->isWhmcsConfigOption(ConfigurableOption::ADDITIONAL_DISKS_SIZE) )
        {
            $maxSize = $this->getWhmcsConfigOption(ConfigurableOption::ADDITIONAL_DISKS_SIZE);
            Utility::unitFormat($maxSize, $this->configuration()->getAdditionalDiskUnit(), "gb");
        }
        return $this->vm()->getMounPoints()->additionalSize() < $maxSize;
    }


    public function diskLimit($newSize = 0, $excludeId = null)
    {
        //Max size
        $maxSize = $this->configuration()->getAdditionalDiskSize();//GB
        if ($this->isWhmcsConfigOption(ConfigurableOption::ADDITIONAL_DISKS_SIZE) )
        {
            $maxSize = $this->getWhmcsConfigOption(ConfigurableOption::ADDITIONAL_DISKS_SIZE);
            Utility::unitFormat($maxSize, $this->configuration()->getAdditionalDiskUnit(), "gb");
        }
        $repository = new HardDiskRepostiory();
        $repository->setApi($this->api());
        $repository->findByPath($this->vm()->getPath() . '/config');
        if (!is_null($excludeId))
        {
            $repository->whereNotIn([$excludeId]);
        }
        $used = $repository->additionalSize();
        $free = $maxSize - $used;
        if ($maxSize != "-1" &&  $newSize > $free)
        {
            throw new \Exception(sprintf(sl("lang")->tr("You are not able to set %s GB of disk size. Available disk size: %s GB"), $newSize, $free));
        }

    }

    public function hasDiskLimit()
    {
        //Max size
        $maxSize = $this->configuration()->getAdditionalDiskSize();//GB
        if ($this->isWhmcsConfigOption(ConfigurableOption::ADDITIONAL_DISKS_SIZE) )
        {
            $maxSize = $this->getWhmcsConfigOption(ConfigurableOption::ADDITIONAL_DISKS_SIZE);
            Utility::unitFormat($maxSize, $this->configuration()->getAdditionalDiskUnit(), "gb");
        }
        $repository = new HardDiskRepostiory();
        $repository->setApi($this->api());
        $repository->findByPath($this->vm()->getPath() . '/config');
        return $repository->additionalSize() < $maxSize;
    }

}