<?php

namespace idoit\Module\Pro\SettingPage\Center;

use Carbon\Carbon;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\RequestOptions;
use idoit\Exception\Exception;
use idoit\Module\License\Entity\License;
use idoit\Module\License\Exception\LicenseInvalidException;
use idoit\Module\License\LicenseServiceFactory;
use idoit\Module\System\SettingPage\SettingPage;
use isys_application;
use isys_component_template_navbar;
use isys_module_pro as ModulePro;
use Throwable;

abstract class Base extends SettingPage
{
    private string $contactMail = 'sales@i-doit.com';
    private string $contactCall = '+49 (0) 211 - 699 31 185';

    /**
     * @param $navMode
     *
     * @return void
     */
    public function renderPage($navMode)
    {
        global $g_license_token;

        $this->checkAuth();
        isys_component_template_navbar::getInstance()
            ->hide_all_buttons();

        try {
            $this->validateLicense();

            // Call route
            $response = isys_application::instance()->container->get('http_client')
                ->request(
                    "https://crm-gateway.i-doit.com/api" . $this->getUrl(),
                    'GET',
                    [
                        RequestOptions::HEADERS => [
                            'Content-Type' => 'application/json',
                            'X-AUTH-TOKEN' => $g_license_token
                        ]
                    ]
                );
            $jsonResponse = $response->getBody()->getContents();
            $this->validateResponse($jsonResponse);

            $this->render($navMode, \isys_format_json::decode($jsonResponse));
            return;
        } catch (LicenseInvalidException $e) {
            $this->tpl
                ->assign('licenseError', true)
                ->assign('contactMail', $this->contactMail)
                ->assign('contactCall', $this->contactCall);
        } catch (ClientException $e) {
            $this->tpl
                ->assign('error', true)
                ->assign('errorCode', $e->getCode());
        } catch (Throwable $e) {
            $this->tpl
                ->assign('error', true)
                ->assign('errorMessage', $e->getMessage())
                ->assign('errorCode', $e->getCode());
        }

        $this->tpl->assign('cssPath', ModulePro::getPath() . 'assets/css/center-base.css')
            ->smarty_tom_add_rule('tom.content.navbar.cRecStatus.p_bInvisible=1')
            ->include_template('contentbottomcontent', ModulePro::getPath() . 'templates/SettingPage/Center/shared/base.tpl');
    }

    /**
     * @return void
     * @throws Exception
     * @throws LicenseInvalidException
     */
    private function validateLicense()
    {
        global $g_license_token;

        // No license token is being used so a legacy licence file is being used
        if ($g_license_token === '' && $_SESSION['licenced'] === false) {
            throw new LicenseInvalidException($this->lang->get('LC__CENTER_BASE__NO_VALID_LICENSE_FOUND'));
        }

        try {
            $licenseService = LicenseServiceFactory::createDefaultLicenseService(isys_application::instance()->container->get('database_system'), $g_license_token);
            $licenseEntity = $licenseService->getEarliestExpiringLicense();
        } catch (Throwable $e) {
            throw new LicenseInvalidException($this->lang->get('LC__CENTER_BASE__NO_VALID_LICENSE_FOUND'));
        }

        // @see ID-10502 ID-10503 Jump out because we won't show 'Download' or 'Contract' page for multi-tenant licenses.
        if ($licenseService->getTotalTenants() > 1) {
            throw new Exception($this->lang->get('LC__CENTER_BASE__HOSTING_ERROR'), '', 401);
        }

        if ($licenseEntity === false) {
            throw new LicenseInvalidException($this->lang->get('LC__CENTER_BASE__NO_VALID_LICENSE_FOUND'));
        }

        // License is expired check
        if ($licenseEntity instanceof License) {
            $start = Carbon::createFromTimestamp($licenseEntity->getValidityFrom()
                ->getTimestamp());
            $end = Carbon::createFromTimestamp($licenseEntity->getValidityTo()
                ->getTimestamp());

            if (!Carbon::now()
                ->between($start, $end)) {
                throw new LicenseInvalidException($this->lang->get('LC__CENTER_BASE__NO_VALID_LICENSE_FOUND'));
            }
        } elseif (is_array($licenseEntity)) {
            throw new LicenseInvalidException($this->lang->get('LC__CENTER_BASE__NO_VALID_LICENSE_FOUND'));
        }
    }

    /**
     * @param string $response
     *
     * @return void
     * @throws Exception
     */
    protected function validateResponse(string $response)
    {
        $responseContent = json_decode($response, true);
        if ($responseContent['success'] === false) {
            throw new Exception($this->lang->get('LC__CENTER_BASE__SERVICE_IS_OFFLINE'));
        }
    }

    /**
     * @return string
     */
    abstract protected function getUrl(): string;

    /**
     * @return void
     */
    abstract protected function checkAuth(): void;

    /**
     * @param $navMode
     *
     * @return void
     */
    abstract protected function render($navMode, array $response): void;
}
