<?php

namespace GriffinForms\Includes\Extensions;

class ExtensionRegistry
{
    use \GriffinForms\Traits\Singleton;

    protected const BADGE_ASSET_DIR = 'admin/images/extension-badges/';

    protected $extensions = [];
    protected $field_extensions = [];

    protected function setExtensions(): void
    {
        $extensions = [
            'pro' => [
                'name'        => 'GriffinForms Pro',
                'buy_url'     => 'https://griffinforms.com/pricing.php',
                'docs_url'    => 'https://griffinforms.com/docs',
                'description' => 'Premium GriffinForms features for advanced fields, workflows, and admin tooling.',
                'badge_url'   => '',
            ],
        ];
        $extensions = apply_filters('griffinforms_register_extensions', $extensions);

        $normalized = [];
        foreach ((array) $extensions as $key => $definition) {
            $key = sanitize_key((string) $key);
            if ($key === '') {
                continue;
            }
            $normalized[$key] = $this->normalizeExtensionDefinition($key, is_array($definition) ? $definition : []);
        }

        $this->extensions = $normalized;
    }

    protected function setFieldextensions(): void
    {
        $map = [
            'signature'      => 'pro',
            'inputrating'    => 'pro',
            'inputrichtext'  => 'pro',
            'inputlikert'    => 'pro',
            'imageselection' => 'pro',
        ];
        $this->field_extensions = apply_filters('griffinforms_register_field_extensions', $map);
    }

    public function get(string $key): array
    {
        $key = sanitize_key($key);
        return is_array($this->extensions[$key] ?? null)
            ? $this->extensions[$key]
            : $this->normalizeExtensionDefinition($key, []);
    }

    public function getForFieldType(string $field_type): array
    {
        $key = sanitize_key($field_type);
        $extension_key = isset($this->field_extensions[$key]) ? (string) $this->field_extensions[$key] : '';
        if ($extension_key === '') {
            return [];
        }
        return $this->get($extension_key);
    }

    public function getPackageIdForFieldType(string $field_type): string
    {
        $key = sanitize_key($field_type);
        return isset($this->field_extensions[$key]) ? sanitize_key((string) $this->field_extensions[$key]) : '';
    }

    public function getFieldExtensions(): array
    {
        return $this->field_extensions;
    }

    public function getFieldTypesByExtension(string $extension_key): array
    {
        $extension_key = sanitize_key($extension_key);
        if ($extension_key === '') {
            return [];
        }

        $field_types = [];
        foreach ($this->field_extensions as $field_type => $owner_key) {
            if (sanitize_key((string) $owner_key) === $extension_key) {
                $field_types[] = (string) $field_type;
            }
        }

        return $field_types;
    }

    public function getName(string $key): string
    {
        $name = trim((string) ($this->get($key)['name'] ?? ''));
        return $name !== '' ? $name : __('an add-on', 'griffinforms-form-builder');
    }

    public function getPurchaseUrl(string $key): string
    {
        return esc_url_raw(trim((string) ($this->get($key)['buy_url'] ?? '')));
    }

    public function getBuyUrl(string $key): string
    {
        return $this->getPurchaseUrl($key);
    }

    public function getDocsUrl(string $key): string
    {
        return esc_url_raw(trim((string) ($this->get($key)['docs_url'] ?? '')));
    }

    public function getDescription(string $key): string
    {
        return trim((string) ($this->get($key)['description'] ?? ''));
    }

    public function getBadgeUrl(string $key): string
    {
        return esc_url_raw(trim((string) ($this->get($key)['badge_url'] ?? '')));
    }

    public function getBadgeAssetsRelativePath(): string
    {
        return self::BADGE_ASSET_DIR;
    }

    public function getBadgeAssetsPath(): string
    {
        return \GriffinForms\Config::getInstance()->getRootPath() . self::BADGE_ASSET_DIR;
    }

    public function getBadgeAssetsUrl(): string
    {
        return \GriffinForms\Config::getInstance()->getRootUrl() . self::BADGE_ASSET_DIR;
    }

    protected function normalizeExtensionDefinition(string $key, array $definition): array
    {
        $key = sanitize_key($key);
        $name = trim((string) ($definition['name'] ?? ''));
        $buy_url = trim((string) ($definition['buy_url'] ?? $this->getDefaultBuyUrl($key)));
        $docs_url = trim((string) ($definition['docs_url'] ?? $this->getDefaultDocsUrl($key)));
        $description = trim((string) ($definition['description'] ?? $this->getDefaultDescription($name !== '' ? $name : $key)));
        $badge_url = $this->resolveBadgeUrl($key, $definition);

        return array_merge($definition, [
            'name' => $name !== '' ? $name : $this->getDefaultName($key),
            'buy_url' => esc_url_raw($buy_url),
            'docs_url' => esc_url_raw($docs_url),
            'description' => $description,
            'badge_url' => esc_url_raw($badge_url),
        ]);
    }

    protected function getDefaultName(string $key): string
    {
        if ($key === 'pro') {
            return 'GriffinForms Pro';
        }

        return __('GriffinForms Extension', 'griffinforms-form-builder');
    }

    protected function getDefaultBuyUrl(string $key): string
    {
        if ($key === 'pro') {
            return 'https://griffinforms.com/pricing.php';
        }

        return 'https://griffinforms.com';
    }

    protected function getDefaultDocsUrl(string $key): string
    {
        if ($key === 'pro') {
            return 'https://griffinforms.com/docs';
        }

        return 'https://griffinforms.com/docs';
    }

    protected function getDefaultDescription(string $name): string
    {
        if ($name === '') {
            $name = __('This extension', 'griffinforms-form-builder');
        }

        return sprintf(
            /* translators: %s: extension name */
            __('Learn more about %s and how it extends GriffinForms.', 'griffinforms-form-builder'),
            $name
        );
    }

    protected function resolveBadgeUrl(string $key, array $definition): string
    {
        $explicit_badge_url = trim((string) ($definition['badge_url'] ?? ''));
        if ($explicit_badge_url !== '') {
            return $explicit_badge_url;
        }

        return $this->findBadgeAssetUrl($key);
    }

    protected function findBadgeAssetUrl(string $key): string
    {
        $key = sanitize_key($key);
        if ($key === '') {
            return '';
        }

        $base_path = trailingslashit($this->getBadgeAssetsPath());
        $base_url = trailingslashit($this->getBadgeAssetsUrl());
        $extensions = ['svg', 'png', 'webp', 'jpg', 'jpeg'];

        foreach ($extensions as $extension) {
            $filename = $key . '.' . $extension;
            if (is_readable($base_path . $filename)) {
                return $base_url . $filename;
            }
        }

        return '';
    }
}
