<?php

declare(strict_types=1);

namespace apexl\Io\modules\email\services;

use apexl\Io\includes\System;
use Arrayy\Type\StringCollection;

final readonly class TemplateService
{
    private const string SYSTEM_VAR_PREFIX = 'io_email_';
    
    private(set) StringCollection $locations;

    public function __construct()
    {
        $this->locations = new StringCollection();
    }

    /**
     * @param array<string, string> $replacements
     */
    public function fetch(string $templateName, array $replacements): ?string
    {
        if (!$content = self::load($templateName)) {
            return null;
        }

        return self::replace($content, $replacements);
    }

    private function load(string $templateName): ?string
    {
        $templateFilename = sprintf('%s.html', $templateName);

        $locations = $this->locations();

        foreach ($locations as $location) {
            $path = sprintf('%s/%s', $location, $templateFilename);
            if (file_exists($path)) {
                return file_get_contents($path);
            }
        }

        return null;
    }

    private function locations(): StringCollection
    {
        return StringCollection::createFromArray([
            sprintf('%s/../template/email', $_SERVER['DOCUMENT_ROOT']),
            $this->locations->toArray(),
            sprintf('%s/../templates', dirname(__FILE__)),
        ]);
    }

    /**
     * @param array<string, string> $replacements
     */
    private function replace(string $content, array $replacements): string
    {
        // Add system variables to replacements
        // Only use vars prefixed io_email_
        $systemVariables = array_filter(
            System::getVariables(),
            fn(string $key) => str_starts_with($key, self::SYSTEM_VAR_PREFIX),
            ARRAY_FILTER_USE_KEY,
        );

        foreach ($systemVariables as $key => $value) {
            $key = str_replace(self::SYSTEM_VAR_PREFIX, '', $key);
            $replacements[$key] = $value;
        }

        return preg_replace(
            array_map(
                fn(string $key) => sprintf('/\{\{\s*%s\s*}}/', $key),
                array_keys($replacements)
            ),
            array_values($replacements),
            $content
        );
    }
}
