<?php

namespace NewsletterBridge\Services\ImgCDN;

class ImgProxy implements CDN {

    protected string $baseUrl;
    protected string $key;
    protected string $salt;

    public function __construct(
        string $baseUrl,
        string $key,
        string $salt
    ) {
        $this->baseUrl = $baseUrl;
        $this->key = $key;
        $this->salt = $salt;
        $this->baseUrl = rtrim($this->baseUrl, '/');
    }

    public function getUrl(string $sourceUrl, array $args = []): string {
        if (!$this->isConfigured() || empty($sourceUrl)) {
            return $sourceUrl;
        }

        $normalizedSource = ltrim($sourceUrl, '/');
        $processingOptions = $this->getProcessingOptions($args);
        $format = isset($args['format']) && $args['format'] !== '' ? $args['format'] : 'webp';
        $path = "/{$processingOptions}/plain/{$normalizedSource}@{$format}";

        return $this->buildSignedUrl($path);
    }

    protected function getProcessingOptions(array $args): string {
        $width   = isset($args['width']) ? (int) $args['width'] : 0;
        $height  = isset($args['height']) ? (int) $args['height'] : 0;
        $quality = isset($args['quality']) ? (int) $args['quality'] : 85;
        $resize  = isset($args['resize']) && $args['resize'] !== '' ? $args['resize'] : 'fill';

        return sprintf(
            'rs:%s:%s:%s/q:%s',
            $resize,
            $width > 0 ? $width : '',
            $height > 0 ? $height : '',
            $quality > 0 ? $quality : 85
        );
    }

    protected function buildSignedUrl(string $path): string {
        $signature = $this->getSignature($path);
        return sprintf('%s/%s%s', $this->baseUrl, $signature, $path);
    }

    protected function getSignature(string $path): string {
        $keyBin = pack('H*', $this->key);
        if (empty($keyBin)) {
            throw new \RuntimeException('ImgProxy key must be an hex-encoded string');
        }

        $saltBin = pack('H*', $this->salt);
        if (empty($saltBin)) {
            throw new \RuntimeException('ImgProxy salt must be an hex-encoded string');
        }

        $result = hash_hmac('sha256', $saltBin . $path, $keyBin, true);
        return rtrim(strtr(base64_encode($result), '+/', '-_'), '=');
    }

    protected function isConfigured(): bool
    {
        return $this->baseUrl !== '' && $this->key !== '' && $this->salt !== '';
    }
}
