<?php


namespace ModulesGarden\ProxmoxAddon\App\Services\Vps;


use MGProvision\Proxmox\v2\ProxmoxApiException;
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;

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

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

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

    public function getUserAndUpdate()
    {
        if(!$this->configuration()->isAgentTemplateUser()){
            return;
        }
        $response = $this->vm()->agent()->getUsers();
        if(!$response['result']['0']['user']){
            throw  new ProxmoxApiException("OS user not found");
        }
        $user = $response['result']['0']['user'];
        $this->hosting()->username = $user;
        $this->hosting()->save();

    }

    public function passwordUpdate()
    {
        if(!$this->configuration()->isAgentServicePassword()){
            return;
        }
        $this->vm()->agent()->setUserPassword($this->hosting()->username, $this->getWhmcsParamByKey("password"));

    }

    public function configureNetwork()
    {
        if(!$this->configuration()->isAgentConfigureNetwork()){
            return;
        }
        $this->networkInterfaces = $this->vm()->agent()->networkGetInterfaces();
        //remove
        $this->deleteIpAddresses();
        $ips = VmIpAddress::ofHostingId($this->getWhmcsParamByKey("serviceid"))
                           ->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->ip == $this->hosting()->dedicatedip){
                        $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);
                    }
                }
                $this->vm()->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);
                $this->vm()->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);
                $this->vm()->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"))->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);
                }
                $this->vm()->agent()->exec($command);
                sleep(1);
            }
        }
    }
}