<?php


namespace ModulesGarden\ProxmoxAddon\App\Services\Cloud;


use ModulesGarden\ProxmoxAddon\App\Models\VmIpAddress;
use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
use ModulesGarden\ProxmoxAddon\App\UI\IpManagement\Providers\IpAddressProvider;
use ModulesGarden\ProxmoxAddon\Core\UI\Traits\WhmcsParams;
use function ModulesGarden\ProxmoxAddon\Core\Helper\sl;

class AgentService
{
    use WhmcsParams;
    use ApiService;
    use ProductService;
    use HostingService;

    private $networkInterfaces=[];
    private $assignedIpAddresses=[];

    public function isEnabled()
    {
        $configurationIsOn =  $this->configuration()->isAgent() && ( $this->configuration()->isAgentConfigureNetwork() ||  $this->configuration()->isAgentPassword());
        $ostype = sl('Vm')->getVm()->config()['ostype'];
        return $configurationIsOn &&  preg_match('/w/', $ostype);
    }


    public function passwordUpdate()
    {
        if(!$this->configuration()->isAgentPassword()){
            return;
        }
        $user =  sl('Vm')->getVm()->config()['ciuser'] ? sl('Vm')->getVm()->config()['ciuser'] : 'Administrator';
        sl('Vm')->getVm()->agent()->setUserPassword($user, sl('Vm')->getVmModel()->getPassword());

    }

    public function configureNetwork()
    {
        if(!$this->configuration()->isAgentConfigureNetwork()){
            return;
        }
        $this->networkInterfaces = sl('Vm')->getVm()->agent()->networkGetInterfaces();
        //remove
        $this->deleteIpAddresses();
        $ips = VmIpAddress::ofHostingId($this->getWhmcsParamByKey("serviceid"))
            ->ofVmId( sl('Vm')->getVmModel()->id)
                           ->orderByIdAsc();

        foreach ($this->networkInterfaces['result'] as $net){
            $networkName = $net['name'];
            if(!$net['hardware-address'] || preg_match("/loopback/", strtolower($networkName) ) ){ //Loopback
                continue;
            }
            /**
             * Add IP Addresses
             * @var $ip VmIpAddress
             */
            foreach ($ips->get() as $ip){
                //exist?
                if(in_array($ip->ip, (array) $this->assignedIpAddresses)){
                    continue;
                }
                //IPV6
                if(preg_match("/\:/", $ip->ip )){
                    $command = sprintf("netsh interface ipv6 add address \"%s\" %s", $networkName,  $ip->ip);
                    //IPV4
                }else {
                    $subnet = $ip->subnet_mask ? $ip->subnet_mask : IpAddressProvider::translateBitmaskToNetmask($ip->cidr);
                    if($ip->net == 'net0'){
                        $command = sprintf("netsh interface ipv4 set address name=\"%s\" static %s %s %s",$networkName, $ip->ip, $subnet, $ip->gateway);
                    }else{
                        $command = sprintf("netsh interface ipv4 add address name=\"%s\" %s %s %s",$networkName, $ip->ip, $subnet, $ip->gateway);
                    }
                }
                sl('Vm')->getVm()->agent()->exec($command);
                $this->assignedIpAddresses[] =  $ip->ip;
                sleep(1);
                if(!$this->configuration()->isOneNetworkDevice()){
                    break;
                }
            }
            //configure DNS
            $ns1 = trim($this->hosting()->ns1);
            $ns2 = trim($this->hosting()->ns2);
            if (!empty($ns1) && filter_var($ns1, FILTER_VALIDATE_IP))
            {
                $command = sprintf("netsh interface ip set dns name=\"%s\" static %s",$networkName, $ns1);
                sl('Vm')->getVm()->agent()->exec($command);
                sleep(1);
            }
            if (!empty($ns2) && filter_var($ns2, FILTER_VALIDATE_IP))
            {
                $command = sprintf("netsh interface ip add dns name=\"%s\" %s index=2",$networkName, $ns2);
                sl('Vm')->getVm()->agent()->exec($command);
                sleep(1);
            }
        }
    }

    private function deleteIpAddresses(){
        foreach ($this->networkInterfaces['result'] as $net){
            foreach ($net['ip-addresses'] as $ipAddress)
            {
                if(!$net['hardware-address'] || preg_match("/loopback/", strtolower($net['name']) ) ){ //Loopback
                    continue;
                }

                $ipAddress = $ipAddress['ip-address'];
                $this->assignedIpAddresses[] = $ipAddress;
                if(!$ipAddress  || VmIpAddress::ofHostingId($this->getWhmcsParamByKey("serviceid"))
                        ->ofVmId(sl('Vm')->getVmModel()->id)
                        ->ofIp($ipAddress)->count()){
                    continue;
                }
                //IPV6
                if(preg_match("/\:/", $ipAddress )){
                    $command = sprintf("netsh interface ipv6 delete address %s",  $ipAddress);
                    //IPV4
                }else{
                    $command = sprintf("netsh interface ipv4 delete address name=\"%s\" %s",  $net['name'],  $ipAddress);
                }
                sl('Vm')->getVm()->agent()->exec($command);
                sleep(1);
            }
        }
    }
}