<?php

namespace GriffinForms\Includes\Upsells;

use GriffinForms\Admin\Menu;
use GriffinForms\Includes\Packages\PackageStateResolver;
use GriffinForms\Traits\Singleton;

class UpsellRegistry extends \GriffinForms\Format
{
    use Singleton;

    protected array $definitions = [];
    protected $package_state_resolver;

    protected function setPackageStateResolver()
    {
        $this->package_state_resolver = PackageStateResolver::getInstance();
    }

    protected function setDefinitions()
    {
        $definitions = [
            'submission_editing' => [
                'feature_id' => 'submission_editing',
                'package_id' => 'pro',
                'title' => __('Submission Editing', 'griffinforms-form-builder'),
                'description' => __('Track edits and restore previous versions of this submission. Upgrade to GriffinForms Pro to unlock edit history, rollback, and frontend submission editing.', 'griffinforms-form-builder'),
                'cta_text' => __('Upgrade to Pro', 'griffinforms-form-builder'),
                'cta_url' => $this->getDefaultUpgradeUrl(),
                'badge' => __('Pro Feature', 'griffinforms-form-builder'),
                'shapes' => ['overlay', 'card', 'banner'],
            ],
            'submission_export' => [
                'feature_id' => 'submission_export',
                'package_id' => 'pro',
                'title' => __('Submission Export', 'griffinforms-form-builder'),
                'description' => __('Download submissions as CSV or JSON directly from the submissions list. Includes metadata columns and per-field data, with complex fields like Likert scales cleanly flattened. Upgrade to GriffinForms Pro to unlock export.', 'griffinforms-form-builder'),
                'cta_text' => __('Upgrade to Pro', 'griffinforms-form-builder'),
                'cta_url' => $this->getDefaultUpgradeUrl(),
                'badge' => __('Pro Feature', 'griffinforms-form-builder'),
                'shapes' => ['card', 'banner'],
            ],
            'google_sheets_sync' => [
                'feature_id' => 'google_sheets_sync',
                'package_id' => 'pro',
                'title' => __('Google Sheets Sync', 'griffinforms-form-builder'),
                'description' => __('Automatically push every new submission into a Google Sheet — one sheet per form, columns grow as your fields change. Upgrade to GriffinForms Pro to unlock live Sheets sync.', 'griffinforms-form-builder'),
                'cta_text' => __('Upgrade to Pro', 'griffinforms-form-builder'),
                'cta_url' => $this->getDefaultUpgradeUrl(),
                'badge' => __('Pro Feature', 'griffinforms-form-builder'),
                'shapes' => ['banner', 'card'],
            ],
            'square_payments' => [
                'feature_id' => 'square_payments',
                'package_id' => 'pro',
                'title' => __('Square Payments', 'griffinforms-form-builder'),
                'description' => __('Accept card payments through Square with the Web Payments SDK — secure hosted card fields, sandbox testing, and seamless checkout in your forms. Upgrade to GriffinForms Pro to unlock Square payments.', 'griffinforms-form-builder'),
                'cta_text' => __('Upgrade to Pro', 'griffinforms-form-builder'),
                'cta_url' => $this->getDefaultUpgradeUrl(),
                'badge' => __('Pro Feature', 'griffinforms-form-builder'),
                'shapes' => ['banner', 'card'],
            ],
        ];

        $definitions = apply_filters('griffinforms_register_upsell_features', $definitions);
        $this->definitions = is_array($definitions) ? $definitions : [];
    }

    public function register(string $feature_id, array $definition): void
    {
        $feature_id = sanitize_key($feature_id);
        if ($feature_id === '') {
            return;
        }

        $this->definitions[$feature_id] = array_merge(
            $this->definitions[$feature_id] ?? [],
            $definition,
            ['feature_id' => $feature_id]
        );
    }

    public function get(string $feature_id): array
    {
        $feature_id = sanitize_key($feature_id);
        return is_array($this->definitions[$feature_id] ?? null) ? $this->definitions[$feature_id] : [];
    }

    public function isDiscoverabilityEnabled(): bool
    {
        return class_exists(Menu::class) && Menu::isProEnabled();
    }

    public function isFeatureAdmitted(string $feature_id): bool
    {
        $definition = $this->get($feature_id);
        if (empty($definition)) {
            return false;
        }

        $package_state = $this->getPackageState((string) ($definition['package_id'] ?? 'pro'));
        return $this->isPackageAdmitted($package_state);
    }

    public function shouldRenderLockedShell(string $feature_id): bool
    {
        return !empty($this->get($feature_id)) && !$this->isFeatureAdmitted($feature_id);
    }

    public function getViewModel(string $feature_id, string $shape, array $overrides = []): array
    {
        $definition = $this->get($feature_id);
        if (empty($definition)) {
            return [];
        }

        $shape = sanitize_key($shape);
        $package_id = sanitize_key((string) ($definition['package_id'] ?? 'pro'));
        $package_state = $this->getPackageState($package_id);
        $action = $this->getActionModel($package_state);

        $description = trim((string) ($definition['description'] ?? ''));

        $model = [
            'feature_id' => $feature_id,
            'shape' => $shape,
            'package_id' => $package_id,
            'title' => (string) ($definition['title'] ?? ''),
            'description' => $description,
            'status_message' => $action['status_message'],
            'cta_text' => $action['cta_text'] !== '' ? $action['cta_text'] : (string) ($definition['cta_text'] ?? ''),
            'cta_url' => $action['cta_url'] !== '' ? $action['cta_url'] : (string) ($definition['cta_url'] ?? ''),
            'badge' => (string) ($definition['badge'] ?? __('Pro Feature', 'griffinforms-form-builder')),
            'package_state' => $package_state,
        ];

        return array_merge($model, $overrides);
    }

    public function render(string $feature_id, string $shape, array $overrides = []): void
    {
        $view_model = $this->getViewModel($feature_id, $shape, $overrides);
        if (empty($view_model)) {
            return;
        }

        $shell = new \GriffinForms\Admin\Html\Elements\UpsellShell($view_model);
        $shell->html();
    }

    protected function getPackageState(string $package_id): array
    {
        $state = $this->package_state_resolver->getState();
        $packages = is_array($state['packages'] ?? null) ? $state['packages'] : [];
        return is_array($packages[$package_id] ?? null) ? $packages[$package_id] : [];
    }

    protected function isPackageAdmitted(array $package_state): bool
    {
        return !empty($package_state['is_present'])
            && !empty($package_state['is_active'])
            && (($package_state['approval_status'] ?? '') === 'approved')
            && (($package_state['compatibility_state'] ?? '') === 'compatible')
            && in_array((string) ($package_state['entitlement_state'] ?? ''), ['verified_active', 'grace_period'], true);
    }

    protected function getActionModel(array $package_state): array
    {
        $recommended = (string) ($package_state['recommended_user_action'] ?? '');
        $is_present = !empty($package_state['is_present']);

        $labels = [
            'install_pro' => __('Upgrade to Pro', 'griffinforms-form-builder'),
            'activate_pro' => __('Activate Pro', 'griffinforms-form-builder'),
            'resolve_compatibility' => __('Review Compatibility', 'griffinforms-form-builder'),
            'enter_license_key' => __('Activate Pro License', 'griffinforms-form-builder'),
            'reactivate_license' => __('Reactivate License', 'griffinforms-form-builder'),
            'retry_license_verification' => __('Retry Verification', 'griffinforms-form-builder'),
            'monitor_grace_period' => __('Review License Status', 'griffinforms-form-builder'),
        ];

        $suffixes = [
            'install_pro' => __('Install the GriffinForms Pro package on this site to unlock this feature.', 'griffinforms-form-builder'),
            'activate_pro' => __('GriffinForms Pro is already installed here. Activate it to unlock this feature instead of purchasing again.', 'griffinforms-form-builder'),
            'resolve_compatibility' => __('Core detected a compatibility issue with the installed Pro package. Resolve that package health problem before this feature can go live.', 'griffinforms-form-builder'),
            'enter_license_key' => __('GriffinForms Pro is installed and active, but it still needs a valid license key before this feature can go live.', 'griffinforms-form-builder'),
            'reactivate_license' => __('This site already has GriffinForms Pro, but the current license is inactive or expired. Reactivate it to restore access.', 'griffinforms-form-builder'),
            'retry_license_verification' => __('This site already has GriffinForms Pro, but recent license verification could not be completed. Review the current license status and retry verification.', 'griffinforms-form-builder'),
            'monitor_grace_period' => __('This site is currently in a Pro grace period. Review the license status before that grace window expires.', 'griffinforms-form-builder'),
        ];

        return [
            'cta_text' => $labels[$recommended] ?? __('Upgrade to Pro', 'griffinforms-form-builder'),
            'cta_url' => $this->getActionUrl($recommended, $is_present),
            'status_message' => $suffixes[$recommended] ?? '',
        ];
    }

    protected function getActionUrl(string $recommended_action, bool $is_present = true): string
    {
        if (!$is_present) {
            return \GriffinForms\Includes\Extensions\ExtensionRegistry::getInstance()->getBuyUrl('pro');
        }

        switch ($recommended_action) {
            case 'install_pro':
                return \GriffinForms\Includes\Extensions\ExtensionRegistry::getInstance()->getBuyUrl('pro');

            case 'activate_pro':
                return admin_url('plugins.php');

            case 'resolve_compatibility':
            case 'retry_license_verification':
            case 'monitor_grace_period':
                return admin_url('admin.php?page=' . \GriffinForms\Config::PREFIX . '-diagnostics');

            case 'enter_license_key':
            case 'reactivate_license':
                if ($this->isDiscoverabilityEnabled()) {
                    return admin_url('admin.php?page=' . \GriffinForms\Config::PREFIX . '-settings-license');
                }

                return admin_url('plugins.php');
        }

        return $this->getDefaultUpgradeUrl();
    }

    protected function getDefaultUpgradeUrl(): string
    {
        return admin_url('plugins.php');
    }
}
