<?php

namespace App\Services;

use App\Enums\LandingPageLayoutMode;
use App\Enums\LandingPageVersion;
use Illuminate\Support\Arr;
use InvalidArgumentException;
use RuntimeException;

class CatalogTemplateLocator
{
    /**
     * One slot per variation that has at least one template folder.
     * The specific template-N is chosen by the user before generation.
     *
     * @return list<array{version: LandingPageVersion}>
     */
    public function slots(): array
    {
        $slots = [];

        foreach (LandingPageVersion::forLayout(LandingPageLayoutMode::Catalog) as $version) {
            if ($this->templatesFor($version) === []) {
                continue;
            }

            $slots[] = [
                'version' => $version,
            ];
        }

        return $slots;
    }

    /**
     * Template folders present for every catalog variation that has templates.
     *
     * @return list<string>
     */
    public function sharedTemplates(): array
    {
        $sets = [];

        foreach (LandingPageVersion::forLayout(LandingPageLayoutMode::Catalog) as $version) {
            $templates = $this->templatesFor($version);

            if ($templates === []) {
                continue;
            }

            $sets[] = $templates;
        }

        if ($sets === []) {
            return [];
        }

        $shared = count($sets) === 1
            ? $sets[0]
            : array_values(array_intersect(...$sets));

        natsort($shared);

        return array_values($shared);
    }

    public function previewDocument(string $template): ?string
    {
        if (! $this->isTemplateName($template)) {
            return null;
        }

        foreach (LandingPageVersion::forLayout(LandingPageLayoutMode::Catalog) as $version) {
            $directory = $this->directory($version, $template);

            if (! is_dir($directory)) {
                continue;
            }

            $htmlFile = $this->previewHtmlFile($directory, $template);

            if ($htmlFile === null) {
                continue;
            }

            $html = (string) file_get_contents($htmlFile);
            $cssFile = $directory.DIRECTORY_SEPARATOR.'style.css';

            if (is_file($cssFile)) {
                $cssUri = 'data:text/css;base64,'.base64_encode((string) file_get_contents($cssFile));
                $html = str_replace(
                    ['href="style.css"', "href='style.css'"],
                    ['href="'.$cssUri.'"', "href='".$cssUri."'"],
                    $html,
                );
            }

            return $html;
        }

        return null;
    }

    public function pickTemplate(LandingPageVersion $version, string $stored = ''): string
    {
        if ($stored !== '') {
            return $stored;
        }

        $templates = $this->templatesFor($version);

        if ($templates === []) {
            throw new RuntimeException(
                "Add a template folder such as template-1 with index.phtml under resources/landing-page-templates/{$version->value}",
            );
        }

        return Arr::random($templates);
    }

    /**
     * @return list<string>
     */
    public function templatesFor(LandingPageVersion $version): array
    {
        $directory = $this->versionDirectory($version);

        if (! is_dir($directory)) {
            return [];
        }

        $templates = [];

        foreach (scandir($directory) ?: [] as $entry) {
            if (! $this->isTemplateName($entry)) {
                continue;
            }

            $path = $directory.DIRECTORY_SEPARATOR.$entry;

            if (is_dir($path) && is_file($path.DIRECTORY_SEPARATOR.'index.phtml')) {
                $templates[] = $entry;
            }
        }

        natsort($templates);

        return array_values($templates);
    }

    public function directory(LandingPageVersion $version, string $template): string
    {
        if (! $this->isTemplateName($template)) {
            throw new InvalidArgumentException("Invalid catalog template name [{$template}].");
        }

        return $this->versionDirectory($version).DIRECTORY_SEPARATOR.$template;
    }

    private function versionDirectory(LandingPageVersion $version): string
    {
        return rtrim((string) config('landing-page-templates.path'), DIRECTORY_SEPARATOR)
            .DIRECTORY_SEPARATOR
            .$version->value;
    }

    private function previewHtmlFile(string $directory, string $template): ?string
    {
        $compact = str_replace('-', '', $template);
        $candidates = [
            $directory.DIRECTORY_SEPARATOR.'preview.html',
            $directory.DIRECTORY_SEPARATOR.$compact.'.html',
            $directory.DIRECTORY_SEPARATOR.$template.'.html',
        ];

        foreach ($candidates as $path) {
            if (is_file($path)) {
                return $path;
            }
        }

        return null;
    }

    private function isTemplateName(string $name): bool
    {
        return (bool) preg_match('/^[A-Za-z0-9][A-Za-z0-9_-]*$/', $name);
    }
}
