<?php

namespace ModulesGarden\ProxmoxAddon\App\Helper;

use Illuminate\Database\Capsule\Manager as DB;
use ModulesGarden\ProxmoxAddon\App\Models\BuildTlds\Collection;
use ModulesGarden\ProxmoxAddon\App\Models\Doe\DomainCategory;
use ModulesGarden\ProxmoxAddon\App\Models\Doe\DomainCategoryRelations;
use ModulesGarden\ProxmoxAddon\App\Models\Doe\DomainLabel;
use ModulesGarden\ProxmoxAddon\App\UI\DoeSectionsSettings\Helpers\DoeSearchTypes;
use ModulesGarden\ProxmoxAddon\App\UI\DoeSectionsSettings\Providers\DoeSettingsDataProvider;
use ModulesGarden\ProxmoxAddon\Core\Helper\DomainHelper;
use ModulesGarden\ProxmoxAddon\Core\Http\Request;
use ModulesGarden\ProxmoxAddon\Core\Models\Whmcs\Client;
use ModulesGarden\ProxmoxAddon\Core\Models\Whmcs\Currency;
use ModulesGarden\ProxmoxAddon\Core\Models\Whmcs\DomainPricing;
use ModulesGarden\ProxmoxAddon\Core\Models\Whmcs\Pricing;

/**
 * Description of BuildTlds
 *
 * @author Rafał Ossowski <rafal.os@modulesgarden.com>
 */
class BuildTlds
{
    /**
     *
     * @var DomainCategory
     */
    protected $domainCategory;

    /**
     * @var DomainPricing
     */
    protected $domainPricing;

    /**
     * @var Pricing
     */
    protected $pricing;

    /**
     * @var  DomainCategoryRelations
     */
    protected $domainCategoryRelations;

    /**
     * @var Client
     */
    protected $client;

    /**
     * @var Request
     */
    protected $request;

    /**
     * @var Currency
     */
    protected $currency;
    protected $specialTld;

    /**
     * @var Collection
     */
    protected $collection;

    /**
     * @var DomainLabel
     */
    protected $domainLabel;

    /**
     * @var DoeSettingsDataProvider
     */
    protected $doeSettingsDataProvider;

    /**
     * @var string
     */
    protected $domainSearchType;

    /**
     * @var array
     */
    protected $tlds = [];

    /**
     * @var array
     */
    protected $categoresTld = [];
    protected $subCategores = [];

    public function __construct(DoeSettingsDataProvider $doeSettingsDataProvider, DomainLabel $domainLabel, Collection $collection, Currency $currency, Request $request, Client $client, Pricing $pricing, DomainPricing $domainPricing, DomainCategory $domainCategory, DomainCategoryRelations $domainCategoryRelations)
    {
        $this->domainCategoryRelations = $domainCategoryRelations;
        $this->doeSettingsDataProvider = $doeSettingsDataProvider;

        $this->domainLabel    = $domainLabel;
        $this->collection     = $collection;
        $this->currency       = $currency;
        $this->request        = $request;
        $this->client         = $client;
        $this->pricing        = $pricing;
        $this->domainCategory = $domainCategory;
        $this->domainPricing  = $domainPricing;
        $this->loadData();
    }

    protected function loadData()
    {
        $sessionDomain = $this->getDomainWithSession();
        $this->collection->addSessionDomain($sessionDomain)
            ->setSessionSearchDomain($this->request->get('formData')['search'])
            ->setSessionCartDomain($this->request->getSession('cart', ['domains' => []])['domains']);
        if ($this->getDomainSearchType() === DoeSearchTypes::CATEGORY_SEARCH || $this->getDomainSearchType() === DoeSearchTypes::MULTIPLE_DOMAIN_SEARCH)
        {
            $this->buildCategoryTree($this->domainCategory->orderBy('suggested', 'DESC')->orderBy('order', 'ASC')->get()->toArray());
            $this->collection->generateCollection($this->categoresTld);
        }

        $princing = $this->pricing->getTable();

        $curency = $this->getCurrency();
        $this->collection->addCurrentName($this->getCurrencyName($curency));

        $query = $this->domainCategory
            ->WithDomainCategoresRelations()
            ->WithDomainPrincing()
            ->WithPrincing()
            ->WithDomainLabelRelations()
            ->WithDomainLabel()
            ->select(
                $this->domainCategory->getTable() . '.id', $this->domainCategory->getTable() . '.parent_id', $this->domainCategory->getTable() . '.header', $this->domainCategory->getTable() . '.title', $this->domainCategory->getTable() . '.type', $this->domainCategory->getTable() . '.order', $this->domainCategory->getTable() . '.suggested', "{$this->domainPricing->getTable()}.id as tld_id", "{$this->domainCategoryRelations->getTable()}.order as tld_order", "{$this->domainCategoryRelations->getTable()}.suggested as tld_suggested", "{$this->domainPricing->getTable()}.extension as tld_extension", "{$princing}.id as prince_id", "{$princing}.currency as tld_currency", "{$princing}.type as prince_type", "{$princing}.msetupfee as prince_one", "{$princing}.qsetupfee as prince_two", "{$princing}.ssetupfee as prince_three", "{$princing}.asetupfee as prince_four", "{$princing}.bsetupfee as prince_five", "{$princing}.monthly as prince_six", "{$princing}.quarterly as prince_seven", "{$princing}.semiannually as prince_eight", "{$princing}.annually as prince_nine", "{$princing}.biennially as prince_ten", "{$this->domainLabel->getTable()}.id as label_id", "{$this->domainLabel->getTable()}.title as label_title", "{$this->domainLabel->getTable()}.message as label_message", "{$this->domainLabel->getTable()}.order as label_order", "{$this->domainLabel->getTable()}.color as label_color", "{$this->domainLabel->getTable()}.background_color as label_background_color"
            )
            ->where("{$this->pricing->getTable()}.currency", "LIKE", $curency)
            ->where(DB::raw("(IF(`{$princing}`.`msetupfee` >= 0, `{$princing}`.`msetupfee`, 0) "
                            . "+ IF(`{$princing}`.`qsetupfee` >= 0, `{$princing}`.`qsetupfee`, 0) "
                            . "+ IF(`{$princing}`.`ssetupfee` >= 0, `{$princing}`.`ssetupfee`, 0) "
                            . "+ IF(`{$princing}`.`asetupfee` >= 0, `{$princing}`.`asetupfee`, 0) "
                            . "+ IF(`{$princing}`.`bsetupfee` >= 0, `{$princing}`.`bsetupfee`, 0) "
                            . "+ IF(`{$princing}`.`monthly` >= 0, `{$princing}`.`monthly`, 0) "
                            . "+ IF(`{$princing}`.`quarterly` >= 0, `{$princing}`.`quarterly`, 0) "
                            . "+ IF(`{$princing}`.`annually` >= 0, `{$princing}`.`annually`, 0) "
                            . "+ IF(`{$princing}`.`biennially` >= 0, `{$princing}`.`biennially`, 0) "
                            . "+ IF(`{$princing}`.`semiannually` >= 0, `{$princing}`.`semiannually`, 0))"), '>', 0.00);

        if ($this->getDomainSearchType() === DoeSearchTypes::CATEGORY_SEARCH || $this->getDomainSearchType() === DoeSearchTypes::MULTIPLE_DOMAIN_SEARCH)
        {
            $query = $query->orderBy('suggested', 'DESC')
                ->orderBy('order', 'ASC')
                ->orderBy("{$this->domainCategoryRelations->getTable()}.suggested", 'DESC')
                ->orderBy("{$this->domainLabel->getTable()}.order", 'DESC')
                ->orderBy("{$this->domainCategoryRelations->getTable()}.order", 'ASC');

            $return = $query->get()->toArray();
            $this->collection->addTlds($return)->setDomainSearchType($this->getDomainSearchType());
        }
        elseif ($this->getDomainSearchType() === DoeSearchTypes::SINGLE_DOMAIN_SEARCH)
        {
            $query = $query->orderBy("{$this->domainCategoryRelations->getTable()}.suggested", 'DESC')
                ->orderBy("{$this->domainLabel->getTable()}.order", 'DESC')
                ->orderBy("{$this->domainCategoryRelations->getTable()}.order", 'ASC');

            $return = $query->get()->toArray();
            $this->collection->addTldsWithoutCategory($return)->setDomainSearchType($this->getDomainSearchType());
        }

        $this->buildTld($return);
    }

    protected function getDomainWithSession()
    {
        $domains = [];
        try
        {
            $domainsSession = $this->request->getSession('cart')['domains'];
            foreach ($domainsSession as $domain)
            {
                $domain                          = new DomainHelper($domain['domain']);
                $domains[$domain->getDomain()][] = $domain->getTLDWithDot();
            }
        }
        catch (\Exception $exc)
        {

        }

        return $domains;
    }

    public function getDomainSearchType()
    {
        if (isset($this->domainSearchType) === false)
        {
            $this->domainSearchType = $this->doeSettingsDataProvider->getValueById('domainSearchType')['value'];
        }

        return $this->domainSearchType;
    }

    protected function buildCategoryTree($data)
    {
        foreach ($data as $record)
        {
            if ($record['parent_id'] !== 0)
            {
                $this->subCategores[] = $record;
            }
            else
            {
                $this->createCategory($record);
            }
        }

        foreach ($this->subCategores as $record)
        {
            $this->createSubCategory($record);
        }

        return $this;
    }

    private function createCategory($data)
    {

        $this->categoresTld[$data['id']] = [
            'id'        => $data['id'],
            'parent_id' => $data['parent_id'],
            'title'     => $data['title'],
            'header'    => $data['header'],
            'type'      => $data['type'],
            'suggested' => $data['suggested'],
            'order'     => $data['order']
        ];

        if (isset($this->categoresTld[$data['id']]['subCategory']) === false)
        {
            $this->categoresTld[$data['id']]['subCategory'] = [];
        }

        return $this;
    }

    private function createSubCategory($data)
    {
        $this->categoresTld[$data['parent_id']]['subCategory'][$data['id']] = [
            'id'        => $data['id'],
            'parent_id' => $data['parent_id'],
            'title'     => $data['title'],
            'header'    => $data['header'],
            'type'      => $data['type'],
            'suggested' => $data['suggested'],
            'order'     => $data['order']
        ];

        return $this;
    }

    protected function getCurrency()
    {
        if ($userId = $this->request->getSession("uid", false))
        {
            $currency = $this->client->find($userId)->toArray()['currency'];
        }
        elseif ($currencyId = $this->request->getSession("currency", false))
        {
            $currency = $currencyId;
        }
        else
        {
            $currency = $this->currency->where("default", "LIKE", 1)->first()->toArray()['id'];
        }
        return $currency;
    }

    protected function getCurrencyName($id)
    {
        return $this->currency->where("id", "LIKE", $id)->first()->toArray()['code'];
    }

    protected function buildTld($data)
    {
        foreach ($data as $record)
        {
            if (in_array($record['tld_extension'], $this->tlds, true) === false)
            {
                $this->tlds[$record['tld_extension']] = $record['tld_extension'];
            }
        }
        return $this;
    }

    public function setSpecialChoice($specialChoice)
    {
        $this->specialTld = $specialChoice;

        return $this;
    }

    public function getSpecialTld()
    {
        return $this->collection->getSpecialTld($this->specialTld);
    }

    public function getTlds()
    {
        $tlds = $this->tlds;
        foreach ($this->collection->getRemoveTlds() as $tld)
        {
            if (array_key_exists($tld, $tlds))
            {
                unset($tlds[$tld]);
            }
        }
        return $tlds;
    }

    public function getTldsCount()
    {
        return (count($this->tlds) - $this->collection->getSessionFindTld());
    }

    public function getCategoresTld()
    {
        return $this->collection->getDataCollection();
    }

    protected function buildCategoresTld($data)
    {
        foreach ($data as $record)
        {
            if ($record['parent_id'] !== 0)
            {
                $this->addTldToSubCategory($record);
            }
            else
            {
                $this->addTldToCategory($record);
            }
        }
        return $this;
    }

    private function addTldToSubCategory($data)
    {
        if (in_array(
                [
                    'id'   => $data['id_tld'],
                    'name' => $data['extension']
                ], $this->categoresTld[$data['parent_id']]['subCategory'][$data['id']]['tlds'], true
            ) === false
        )
        {
            $this->categoresTld[$data['parent_id']]['subCategory'][$data['id']]['tlds'][] = ['id' => $data['id_tld'], 'name' => $data['extension']];
        }

        return $this;
    }

    private function addTldToCategory($data)
    {
        if (in_array(
                [
                    'id'   => $data['id_tld'],
                    'name' => $data['extension']
                ], $this->categoresTld[$data['id']]['tlds'], true
            ) === false
        )
        {
            $this->categoresTld[$data['id']]['tlds'][] = ['id' => $data['id_tld'], 'name' => $data['extension']];
        }

        return $this;
    }
}
