<?php

namespace ModulesGarden\Servers\ZimbraEmail\App\Libs\Metrics;

use ModulesGarden\Servers\HetznerVps\App\Libs\HetznerVps\Api;
use ModulesGarden\Servers\HetznerVps\App\Libs\HetznerVps\Api\Constants;
use ModulesGarden\Servers\ZimbraEmail\App\Helpers\ZimbraManager;
use ModulesGarden\Servers\ZimbraEmail\App\Enums\Size;
use mysql_xdevapi\DocResult;
use WHMCS\UsageBilling\Contracts\Metrics\MetricInterface;
use WHMCS\UsageBilling\Contracts\Metrics\ProviderInterface;
use WHMCS\UsageBilling\Metrics\Metric;
use WHMCS\UsageBilling\Metrics\Units\WholeNumber;
use WHMCS\UsageBilling\Metrics\Usage;
use WHMCS\UsageBilling\Metrics\Units\GigaBytes;

class MyMetricProvider implements ProviderInterface
{
    private $moduleParams = [];
    public function __construct($moduleParams)
    {
        $this->moduleParams = $moduleParams;
    }

    public function metrics()
    {
        return [
            new Metric(
                'mailboxes',
                'Email Accounts',
                MetricInterface::TYPE_SNAPSHOT
            ),
            new Metric(
                'aliases',
                'Email Aliases',
                MetricInterface::TYPE_SNAPSHOT
            ),
            new Metric(
                'distributionLists',
                'Distribution Lists',
                MetricInterface::TYPE_SNAPSHOT
            ),
            new Metric(
                'domainAliases',
                'Domain Aliases',
                MetricInterface::TYPE_SNAPSHOT
            ),
            new Metric(
                'storage',
                'Storage',
                MetricInterface::TYPE_SNAPSHOT,
                new GigaBytes()
            )
        ];
    }

    public function usage()
    {
        $domains =(new ZimbraManager())
            ->getApiByServer($this->moduleParams['serverid'])
            ->soap
            ->repository()
            ->domains()
            ->getAll();

        $usage = [];
        foreach ($domains as $domain)
        {
            $domainName = $domain->getName();

            $mailboxes = $this->getAccounts($domainName);
            $countOfMailboxes = count($mailboxes);

            $countOfDistributionList = count($this->getDistributionList($domainName));

            $countOfEmailAliases = 0;

            foreach ($mailboxes as $account)
            {
                $countOfEmailAliases += count($account->getAliases());
            }

            $domainAliases = $this->getDomainAliases($domainName);
            $countOfDomainAliases = count($domainAliases);

            $storage = $this->getDomainUsage($domainName);


            $domainData = [
                'mailboxes' => $countOfMailboxes,
                'distributionLists' => $countOfDistributionList,
                'aliases' => $countOfEmailAliases,
                'domainAliases' => $countOfDomainAliases,
                'storage' => round($storage / Size::B_TO_GB, 2),
            ];

            $usage[$domainName] = $this->wrapUserData($domainData);

        }
        return $usage;
    }

    public function tenantUsage($tenant)
    {
        $mailboxes = $this->getAccounts($tenant);
        $countOfMailboxes = count($mailboxes);

        $countOfEmailAliases = 0;

        foreach ($mailboxes as $account)
        {
            $countOfEmailAliases += count($account->getAliases());
        }

        $countOfDistributionList = count($this->getDistributionList($tenant));

        $domainAliases = $this->getDomainAliases($tenant);
        $countOfDomainAliases = count($domainAliases);

        $storage = $this->getDomainUsage($tenant);

        $userData = [
            'mailboxes' => $countOfMailboxes,
            'distributionLists' => $countOfDistributionList,
            'aliases' => $countOfEmailAliases,
            'domainAliases' => $countOfDomainAliases,
            'storage' => round($storage / Size::B_TO_GB, 2),
        ];

        return $this->wrapUserData($userData);
    }

    private function wrapUserData($data)
    {
        $wrapped = [];
        foreach ($this->metrics() as $metric) {
            $key = $metric->systemName();
            if ($data[$key]) {
                $value = $data[$key];
                $metric = $metric->withUsage(
                    new Usage($value)
                );
            }

            $wrapped[] = $metric;
        }

        return $wrapped;
    }

    private function getAccounts($tenant)
    {
        $accounts =(new ZimbraManager())
            ->getApiByServer($this->moduleParams['serverid'])
            ->soap
            ->repository()
            ->accounts()
            ->getByDomainName($tenant);

        return $accounts;
    }

    private function getDomainAliases($tenant)
    {
        $domainAliases =(new ZimbraManager())
            ->getApiByServer($this->moduleParams['serverid'])
            ->soap
            ->repository()
            ->domains
            ->getAliases($tenant);

        return $domainAliases;
    }

    private function getDomainUsage($tenant)
    {
        $accounts =(new ZimbraManager())
            ->getApiByServer($this->moduleParams['serverid'])
            ->soap
            ->repository()
            ->accounts
            ->getUsages($tenant);

        $totalUsage = 0;
        foreach ($accounts as $account)
        {
            $usage = $account->getUsed();
            $totalUsage += $usage;
        }

        return $totalUsage;
    }

    private function getDistributionList($tenant)
    {
        $distributionList =(new ZimbraManager())
            ->getApiByServer($this->moduleParams['serverid'])
            ->soap
            ->repository()
            ->lists
            ->getAllDistributionListsByDomain($tenant);

        return $distributionList;
    }

}
