<?php

// +-------------------------------------------------+
// © 2002-2004 PMB Services / www.sigb.net pmb@sigb.net et contributeurs (voir www.sigb.net)
// +-------------------------------------------------+
// $Id: ApiSignature.php,v 1.1.2.7 2026/02/11 08:47:24 qvarin Exp $

namespace Pmb\Digitalsignature\Library;

use Curl;
use CURLFile;
use CurlResponse;
use Pmb\Common\Library\Crypto\Crypto;

class ApiSignature
{
    protected $url = "";

    protected $token = "";

    public const API_CHECK_TEST = "/";

    public const API_CHECK_SIGNATURE = "/check/signature";

    public const API_SIGN_DOCUMENT = "/sign/document";

    public const API_SIGN_METADATA = "/sign/metadata";

    public const API_SIGN_LOG = "/sign/log";

    public const API_CHECK_INTEGRITY_BACK = "/check/back/integrity";

    public const API_CHECK_INTEGRITY_OPAC = "/check/opac/integrity";

    public const API_OPAC_HASH = "/opac/hash";

    public const API_BACK_HASH = "/back/hash";


    public function __construct(string $url, string $token)
    {
        $crypto = new Crypto();
        $crypto->loadPMBRSAContext();

        $this->url = $crypto->decryptFromHexa($url);
        $this->token = $token;
    }

    public function initCommunication()
    {
        $url = rtrim($this->url, '/') . self::API_CHECK_TEST;

        $curl = new Curl();
        $curl->headers = $this->getHeaders();

        $curlResponse = $curl->get($url);

        // Souci dans le header, on peut avoir deux valeurs : ([Status] => 100 ContinueHTTP/1.1 200 OK)
        if (($curlResponse instanceof CurlResponse) && strpos(strtolower($curlResponse->headers['Status']), '200 ok') !== false) {
            return true;
        }
        return false;
    }

    public function signDocument(string $filePath)
    {
        $url = rtrim($this->url, '/') . self::API_SIGN_DOCUMENT;

        $curl = new Curl();
        $curl->headers = $this->getHeaders();
        $curl->options['CURLOPT_POSTFIELDS'] = [
            'document' => new CURLFile($filePath),
        ];

        $curlResponse = $curl->post($url);

        // Souci dans le header, on peut avoir deux valeurs : ([Status] => 100 ContinueHTTP/1.1 200 OK)
        if (($curlResponse instanceof CurlResponse) && strpos(strtolower($curlResponse->headers['Status']), '200 ok') !== false) {
            $result = json_decode($curlResponse->body, true);
            if (is_array($result) && !empty($result['signature'])) {
                return $result;
            }
        }

        return false;
    }

    public function signMetadata(object $metadata)
    {
        $url = rtrim($this->url, '/') . self::API_SIGN_METADATA;

        $curl = new Curl();
        $curl->headers = $this->getHeaders();

        $options = [
            'metadata' => json_encode([
                'date' => date('Y-m-d H:i:s'),
                'metadata' => $metadata,
                'signature' => $metadata->signature,
            ]),
        ];

        $curlResponse = $curl->post($url, $options);

        // Souci dans le header, on peut avoir deux valeurs : ([Status] => 100 ContinueHTTP/1.1 200 OK)
        if (($curlResponse instanceof CurlResponse) && strpos(strtolower($curlResponse->headers['Status']), '200 ok') !== false) {
            $result = json_decode($curlResponse->body, true);
            if (is_array($result) && !empty($result['signature'])) {
                return $result;
            }
        }
        return false;
    }

    public function check_integrity(string $fileName, string $content)
    {
        if (strpos($fileName, 'opac') !== false) {
            $url = rtrim($this->url, '/') . self::API_CHECK_INTEGRITY_OPAC;
        } else if (strpos($fileName, 'back') !== false) {
            $url = rtrim($this->url, '/') . self::API_CHECK_INTEGRITY_BACK;
        } else {
            return "";
        }

        $curl = new Curl();
        $curl->headers = $this->getHeaders();
        $curl->set_option("CURLOPT_POSTFIELDS", [
            'document' => new \CURLStringFile($content, 'hashFile.json', 'application/json'),
        ]);

        $curlResponse = $curl->post($url);

        // Souci dans le header, on peut avoir deux valeurs : ([Status] => 100 ContinueHTTP/1.1 200 OK)
        if (($curlResponse instanceof CurlResponse) && strpos(strtolower($curlResponse->headers['Status']), '200 ok') !== false) {
            $result = json_decode($curlResponse->body, true);
            if (is_array($result) && !empty($result['result'])) {
                return $result;
            }
        }

        return false;
    }

    public function checkSignature(\explnum $explnum, string $cmsPath)
    {
        $url = rtrim($this->url, '/') . self::API_CHECK_SIGNATURE;

        $curl = new Curl();
        $curl->headers = $this->getHeaders();

        $curl->set_option("CURLOPT_POSTFIELDS", [
            'signature' => new \CURLStringFile(file_get_contents($cmsPath), 'sign.cms', 'text/plain'),
            'document' => new \CURLStringFile($explnum->get_file_content(), $explnum->explnum_nomfichier, $explnum->explnum_mimetype)
        ]);

        $curlResponse = $curl->post($url);

        // Souci dans le header, on peut avoir deux valeurs : ([Status] => 100 ContinueHTTP/1.1 200 OK)
        if (($curlResponse instanceof CurlResponse) && strpos(strtolower($curlResponse->headers['Status']), '200 ok') !== false) {
            $result = json_decode($curlResponse->body, true);
            if (is_array($result) && !empty($result['metadata'])) {
                return $result;
            }
        }

        return false;
    }

    public function get_hash(string $type)
    {
        if ($type == "back") {
            $url = rtrim($this->url, '/') . self::API_BACK_HASH;
        } else if ($type == "opac") {
            $url = rtrim($this->url, '/') . self::API_OPAC_HASH;
        } else {
        	return "";
        }

        $curl = new Curl();
        $curl->headers = $this->getHeaders();

        $curlResponse = $curl->get($url);

        // Souci dans le header, on peut avoir deux valeurs : ([Status] => 100 ContinueHTTP/1.1 200 OK)
        if (($curlResponse instanceof CurlResponse) && strpos(strtolower($curlResponse->headers['Status']), '200 ok') !== false) {
            return $curlResponse->body;
        }

        return false;
    }

    private function getHeaders()
    {
        return [
            'X-Sign-Server-Token' => $this->token,
        ];
    }
}
