<?php

class DXBackendCommunication
{
    public function getRestApiOptions(): DXRestOptions
    {
        $result = new DXRestOptions();

        $result->endpoint = carbon_get_theme_option('dxcp_rest_endpoint');
        $result->apiKey = carbon_get_theme_option('dxcp_apikey');

        $result->endpointV2 = carbon_get_theme_option('dxcp_rest_endpoint_v2');
        $result->apiKeyV2 = carbon_get_theme_option('dxcp_apikey_v2');

        return $result;
    }

    private function getRequestArgs(): array
    {
        $request_args = array();

        $options = $this->getRestApiOptions();

        $request_args = array(
            'headers' => array(
                'DanceXAuthToken' => $options->apiKey,
                'Content-Type' => 'application/json'
            ),
            //5 minutes
            'timeout' =>  300 //How long the connection should stay open in seconds (Default 5)
        );

        return $request_args;
    }

    private function getRequestArgsV2(): array
    {
        $request_args = array();

        $options = $this->getRestApiOptions();

        $request_args = array(
            'headers' => array(
                'ApiKey' => $options->apiKeyV2,
                'Content-Type' => 'application/json'
            ),
            //5 minutes
            'timeout' =>  300 //How long the connection should stay open in seconds (Default 5)
        );

        return $request_args;
    }


    function kursAnmeldungRequestTocken(): string
    {
        $result = null;

        try {

            $options = $this->getRestApiOptions();
            $request_args = $this->getRequestArgs();

            $response = wp_remote_get($options->endpoint . "/kursAnmeldungRequestTocken", $request_args);

            if (is_wp_error($response))
                throw new Exception("WP Error occured: {$response->get_error_message()}!");

            $http_code = wp_remote_retrieve_response_code($response);
            if ($http_code != 200)
                throw new Exception("Backend-Server answered with HTTP Status: $http_code");

            $body = wp_remote_retrieve_body($response);
            $jsonAsArr = json_decode($body, true);
            $result = $jsonAsArr['NextRequestToken'];
        } catch (\Throwable $th) {
            error_log("Exception occured while calling 'kursAnmeldungRequestTocken':" . $th->getMessage());
            throw $th;
        }

        return $result;
    }

    //fehlerhafte Antwort (plain OK)
    function kursAnmeldung($data): bool
    {

        try {
            if ($data == null || !is_array($data))
                throw new Exception("data is needed as array for this method!");

            $options = $this->getRestApiOptions();
            $request_args = $this->getRequestArgs();

            //we need a RequestToken to create a 'kursAnmeldung'
            $data['RequestToken'] = $this->kursAnmeldungRequestTocken();

            $jsonData = json_encode($data);
            if ($jsonData == false)
                throw new Exception("There was a problem encoding the PHP data-array into JSON.");

            $request_args['body'] = $jsonData;

            $response = wp_remote_post($options->endpoint . "/kursAnmeldung", $request_args);
            if (is_wp_error($response))
                throw new Exception("WP Error occured: {$response->get_error_message()}!");

            $http_code = wp_remote_retrieve_response_code($response);
            if ($http_code != 200)
                throw new Exception("Backend-Server answered with HTTP Status: $http_code");

            //only returns string "OK", which is fine like this

        } catch (\Throwable $th) {
            error_log("Exception occured while calling 'kursAnmeldung':" . $th->getMessage());
            throw $th;
        }

        return true;
    }

    function getKurse(): array
    {
        try {

            $options = $this->getRestApiOptions();
            $request_args = $this->getRequestArgs();

            //leeres JSON-Object mitsenden -> heisst soviel wie kein Filter (ansonsten HTTP-500) !!
            $request_args['body'] = '{}';

            $response = wp_remote_post($options->endpoint . "/getKurse", $request_args);
            if (is_wp_error($response))
                throw new Exception("WP Error occured: {$response->get_error_message()}!");

            $http_code = wp_remote_retrieve_response_code($response);

            //das Backend antwortet mit 404, wenn die Kurse-Liste leer ist -> das muss nicht sein !!
            if ($http_code == 404)
                return array();

            if ($http_code != 200)
                throw new Exception("Backend-Server answered with HTTP Status: $http_code");

            $body = wp_remote_retrieve_body($response);
            $decodedBody = json_decode($body, true);
            $kurse = $decodedBody['Kurse'];

            return $kurse;
        } catch (\Throwable $th) {
            error_log("Exception occured while calling 'getKurse':" . $th->getMessage());
            throw $th;
        }

        return array();
    }

    function getAllEvents(): array
    {
        try {

            $options = $this->getRestApiOptions();
            $request_args = $this->getRequestArgs();

            $response = wp_remote_get($options->endpoint . "/getAllEvents", $request_args);
            if (is_wp_error($response))
                throw new Exception("WP Error occured: {$response->get_error_message()}!");

            $http_code = wp_remote_retrieve_response_code($response);
            if ($http_code != 200)
                throw new Exception("Backend-Server answered with HTTP Status: $http_code");

            $body = wp_remote_retrieve_body($response);
            $decodedBody = json_decode($body, true);
            $events = $decodedBody['Events'];

            return $events;
        } catch (\Throwable $th) {
            error_log("Exception occured while calling 'getAllEvents':" . $th->getMessage());
            throw $th;
        }

        return array();
    }

    function getAllKursgruppe(): array
    {
        try {
            $options = $this->getRestApiOptions();
            $request_args = $this->getRequestArgs();

            $response = wp_remote_get($options->endpoint . "/getAllKursgruppe", $request_args);
            if (is_wp_error($response))
                throw new Exception("WP Error occured: {$response->get_error_message()}!");

            $http_code = wp_remote_retrieve_response_code($response);
            if ($http_code != 200)
                throw new Exception("Backend-Server answered with HTTP Status: $http_code");

            $body = wp_remote_retrieve_body($response);
            $decodedBody = json_decode($body, true);
            $kursgruppen = $decodedBody['Kursgruppen'];

            return $kursgruppen;
        } catch (\Throwable $th) {
            error_log("Exception occured while calling 'getAllKursgruppe':" . $th->getMessage());
            throw $th;
        }

        return array();
    }

    function getAllKurstyp(): array
    {
        try {
            $options = $this->getRestApiOptions();
            $request_args = $this->getRequestArgs();

            $response = wp_remote_get($options->endpoint . "/getAllKurstyp", $request_args);
            if (is_wp_error($response))
                throw new Exception("WP Error occured: {$response->get_error_message()}!");

            $http_code = wp_remote_retrieve_response_code($response);
            if ($http_code != 200)
                throw new Exception("Backend-Server answered with HTTP Status: $http_code");

            $body = wp_remote_retrieve_body($response);
            $decodedBody = json_decode($body, true);
            $kurstypen = $decodedBody['Kurstypen'];

            return $kurstypen;
        } catch (\Throwable $th) {
            error_log("Exception occured while calling 'getAllKurstyp':" . $th->getMessage());
            throw $th;
        }

        return array();
    }

    function getAllKursstufe(): array
    {
        try {
            $options = $this->getRestApiOptions();
            $request_args = $this->getRequestArgs();

            $response = wp_remote_get($options->endpoint . "/getAllKursstufe", $request_args);
            if (is_wp_error($response))
                throw new Exception("WP Error occured: {$response->get_error_message()}!");

            $http_code = wp_remote_retrieve_response_code($response);
            if ($http_code != 200)
                throw new Exception("Backend-Server answered with HTTP Status: $http_code");

            $body = wp_remote_retrieve_body($response);
            $decodedBody = json_decode($body, true);
            $kursstufen = $decodedBody['Kursstufen'];

            return $kursstufen;
        } catch (\Throwable $th) {
            error_log("Exception occured while calling 'getAllKursstufe':" . $th->getMessage());
            throw $th;
        }

        return array();
    }

    function getAllKursleiterDetail(): array
    {
        try {
            $options = $this->getRestApiOptions();
            $request_args = $this->getRequestArgs();

            $response = wp_remote_get($options->endpoint . "/getAllKursleiterDetail", $request_args);
            if (is_wp_error($response))
                throw new Exception("WP Error occured: {$response->get_error_message()}!");

            $http_code = wp_remote_retrieve_response_code($response);

            //das Backend antwortet mit 404, wenn die Kursleiter-Liste leer ist -> das muss nicht sein !!
            if ($http_code == 404)
                return array();

            if ($http_code != 200)
                throw new Exception("Backend-Server answered with HTTP Status: $http_code");

            $body = wp_remote_retrieve_body($response);
            $decodedBody = json_decode($body, true);
            $kursleiter = $decodedBody['Kursleiter'];

            return $kursleiter;
        } catch (\Throwable $th) {
            error_log("Exception occured while calling 'getAllKursleiterDetail':" . $th->getMessage());
            throw $th;
        }

        return array();
    }

    function getImage($bildId): ?string
    {
        try {
            $options = $this->getRestApiOptions();
            $request_args = $this->getRequestArgs();

            $request_args['body'] = "{ \"BildId\" : \"$bildId\" }";

            $response = wp_remote_post($options->endpoint . "/getImage", $request_args);
            if (is_wp_error($response))
                throw new Exception("WP Error occured: {$response->get_error_message()}!");

            $http_code = wp_remote_retrieve_response_code($response);
            if ($http_code != 200)
                return null;

            $body = wp_remote_retrieve_body($response);
            $decodedBody = json_decode($body, true);

            return $decodedBody['Bild'];
        } catch (\Throwable $th) {
            error_log("Exception occured while calling 'getImage':" . $th->getMessage());
        }

        return null;
    }

    function getDocument($dokumentId): ?string
    {
        try {
            $options = $this->getRestApiOptions();
            $request_args = $this->getRequestArgs();

            $request_args['body'] = "{ \"DokumentId\" : \"$dokumentId\" }";

            $response = wp_remote_post($options->endpoint . "/getDocument", $request_args);
            if (is_wp_error($response))
                throw new Exception("WP Error occured: {$response->get_error_message()}!");

            $http_code = wp_remote_retrieve_response_code($response);
            if ($http_code != 200)
                return null;

            $body = wp_remote_retrieve_body($response);
            $decodedBody = json_decode($body, true);

            return $decodedBody['Dokument'];
        } catch (\Throwable $th) {
            error_log("Exception occured while calling 'getDocument':" . $th->getMessage());
        }

        return null;
    }

    function getKursbelegung(int $kursnummer): array
    {
        try {
            $options = $this->getRestApiOptions();
            $request_args = $this->getRequestArgs();

            $request_args['body'] = "{ \"Kursnummer\" : $kursnummer }";

            $response = wp_remote_post($options->endpoint . "/getKursbelegung", $request_args);
            if (is_wp_error($response))
                throw new Exception("WP Error occured: {$response->get_error_message()}!");

            $http_code = wp_remote_retrieve_response_code($response);
            if ($http_code == 404)
                return array();

            if ($http_code != 200)
                throw new Exception("Backend-Server answered with HTTP Status: $http_code");

            $body = wp_remote_retrieve_body($response);
            return json_decode($body, true);
        } catch (\Throwable $th) {
            error_log("Exception occured while calling 'getKursbelegung':" . $th->getMessage());
            throw $th;
        }

        return array();
    }

    function ping(): bool
    {
        try {
            $options = $this->getRestApiOptions();
            $request_args = $this->getRequestArgs();

            //no authentication
            $response = wp_remote_get($options->endpoint . "/ping", $request_args);
            if (is_wp_error($response))
                throw new Exception("WP Error occured: {$response->get_error_message()}!");

            $http_code = wp_remote_retrieve_response_code($response);

            return $http_code == 200;
        } catch (\Throwable $th) {
            error_log("Exception occured while calling 'ping':" . $th->getMessage());
            throw $th;
        }

        return false;
    }

    function isWsV1Callable(): bool
    {
        try {
            $options = $this->getRestApiOptions();
            $request_args = $this->getRequestArgs();

            //has authentication - sadly there is not authPing existent right now - so i choose a pretty simple function to check authentication
            $response = wp_remote_get($options->endpoint . "/getBekanntDurch", $request_args);
            if (is_wp_error($response))
                throw new Exception("WP Error occured: {$response->get_error_message()}!");

            $http_code = wp_remote_retrieve_response_code($response);

            return $http_code == 200;
        } catch (\Throwable $th) {
            error_log("Exception occured while calling 'getBekanntDurch' (Authentication-Call):" . $th->getMessage());
            throw $th;
        }

        return false;
    }

    function isWsV2Callable(): bool
    {

        try {
            $options = $this->getRestApiOptions();
            $request_args = $this->getRequestArgsV2();

            $response = wp_remote_get($options->endpointV2 . "/api/v1/RestServiceSysMon/authping", $request_args);
            if (is_wp_error($response))
                throw new Exception("WP Error occured: {$response->get_error_message()}!");

            $http_code = wp_remote_retrieve_response_code($response);

            return $http_code == 200;
        } catch (\Throwable $th) {
            error_log("Exception occured while calling 'authping':" . $th->getMessage());
            throw $th;
        }

        return false;
    }

    function getWebMenues(): array
    {
        try {
            $options = $this->getRestApiOptions();
            $request_args = $this->getRequestArgsV2();

            $response = wp_remote_get($options->endpointV2 . "/api/v1/dxc/webMenues", $request_args);
            if (is_wp_error($response))
                throw new Exception("WP Error occured: {$response->get_error_message()}!");

            $http_code = wp_remote_retrieve_response_code($response);

            if ($http_code != 200)
                throw new Exception("Backend-Server answered with HTTP Status: $http_code");

            $body = wp_remote_retrieve_body($response);
            return json_decode($body, true);
        } catch (\Throwable $th) {
            error_log("Exception occured while calling 'getWebMenues':" . $th->getMessage());
            throw $th;
        }

        return array();
    }
}
