<?php
/**
 * Simplyin HyvaPayment Theme Detection Plugin
 *
 * Detects if Hyva theme is active and conditionally enables/disables
 * the module's frontend assets based on the active theme.
 *
 * Requirements: 1.3, 1.4
 * - THE Hyva_Checkout_Module SHALL only load its frontend assets when Hyva theme is active
 * - WHEN Luma theme is active, THE Hyva_Checkout_Module SHALL not interfere with existing Simplyin_Payment functionality
 */

declare(strict_types=1);

namespace Simplyin\HyvaPayment\Plugin;

use Magento\Framework\ObjectManagerInterface;
use Magento\Framework\View\LayoutInterface;
use Psr\Log\LoggerInterface;

/**
 * Plugin to detect Hyva theme and conditionally load module assets
 *
 * This plugin intercepts layout generation to ensure that Simplyin_HyvaPayment
 * assets are only loaded when a Hyva theme is active. When Luma or other
 * non-Hyva themes are active, the plugin prevents the module's frontend
 * assets from loading, allowing the original Simplyin_Payment module to
 * function without interference.
 */
class HyvaThemeDetection
{
    /**
     * FQN of the Hyva theme service, referenced as a string on purpose.
     *
     * This module ships in the same package as the Luma Simplyin_Payment module and may be enabled
     * on a store that does NOT have the Hyva theme installed. Type-hinting this class in the
     * constructor would make Magento's DI reflection fail (the class does not exist) and take the
     * whole store down with a 500 before this plugin can do its job. We reference it as a string
     * and resolve it lazily, only when it actually exists.
     */
    // phpcs:ignore Magento2.PHP.LiteralNamespaces -- string FQN on purpose: the class may be absent (Luma), and ::class notation would make PHPStan report class-not-found.
    private const CURRENT_THEME_CLASS = 'Hyva\\Theme\\Service\\CurrentTheme';

    /**
     * @var ObjectManagerInterface
     */
    private ObjectManagerInterface $objectManager;

    /**
     * @var LoggerInterface
     */
    private LoggerInterface $logger;

    /**
     * @var bool|null
     */
    private ?bool $isHyvaThemeActive = null;

    /**
     * Layout handles that should only be loaded for Hyva themes
     */
    private const HYVA_ONLY_HANDLES = [
        'simplyin_hyvapayment_checkout',
        'simplyin_hyvapayment_success',
    ];

    /**
     * @param ObjectManagerInterface $objectManager
     * @param LoggerInterface $logger
     */
    public function __construct(
        ObjectManagerInterface $objectManager,
        LoggerInterface $logger
    ) {
        $this->objectManager = $objectManager;
        $this->logger = $logger;
    }

    /**
     * Check if Hyva theme is currently active
     *
     * @return bool
     */
    public function isHyvaThemeActive(): bool
    {
        if ($this->isHyvaThemeActive === null) {
            // Default to inert. Only flip to true when the Hyva theme is genuinely present AND
            // usable — never let this optional integration take the storefront down (a missing
            // class, or a partial/misconfigured Hyva install that throws on resolution, must all
            // degrade to "not Hyva" rather than a 500).
            $this->isHyvaThemeActive = false;
            if (class_exists(self::CURRENT_THEME_CLASS)) {
                try {
                    $currentTheme = $this->objectManager->get(self::CURRENT_THEME_CLASS);
                    /** @phpstan-ignore-next-line resolved only when the Hyva theme class exists */
                    $this->isHyvaThemeActive = (bool) $currentTheme->isHyva();
                } catch (\Throwable $e) {
                    // Keep the storefront up, but leave a breadcrumb: a present-but-unusable Hyva
                    // service (partial/misconfigured install) is worth knowing about.
                    $this->logger->warning(
                        'Simplyin_HyvaPayment: Hyva theme service present but not resolvable; '
                        . 'treating theme as non-Hyva.',
                        ['exception' => $e]
                    );
                    $this->isHyvaThemeActive = false;
                }
            }
        }

        return $this->isHyvaThemeActive;
    }

    /**
     * Plugin to conditionally add layout handles based on active theme
     *
     * Before adding a layout handle, this plugin checks if the handle is
     * specific to Hyva theme. If so, it only allows the handle to be added
     * when Hyva theme is active.
     *
     * @param LayoutInterface $subject
     * @param string|string[] $handleName
     * @return array
     */
    public function beforeAddHandle(LayoutInterface $subject, $handleName): array
    {
        // If it's an array of handles, filter out Hyva-only handles when not on Hyva theme
        if (is_array($handleName)) {
            if (!$this->isHyvaThemeActive()) {
                $handleName = array_filter($handleName, function ($handle) {
                    return !$this->isHyvaOnlyHandle($handle);
                });
            }
            return [$handleName];
        }

        // For single handle, return empty array to skip if it's Hyva-only and not on Hyva theme
        if (!$this->isHyvaThemeActive() && $this->isHyvaOnlyHandle($handleName)) {
            // Return a non-existent handle to effectively skip this handle
            return ['simplyin_hyvapayment_disabled'];
        }

        return [$handleName];
    }

    /**
     * Check if a layout handle is specific to Hyva theme
     *
     * @param string $handleName
     * @return bool
     */
    private function isHyvaOnlyHandle(string $handleName): bool
    {
        foreach (self::HYVA_ONLY_HANDLES as $hyvaHandle) {
            if (strpos($handleName, $hyvaHandle) !== false) {
                return true;
            }
        }

        return false;
    }

    /**
     * Plugin to conditionally modify layout XML based on active theme
     *
     * This method can be used to remove or modify layout blocks that should
     * only appear on Hyva themes.
     *
     * @param LayoutInterface $subject
     * @param callable $proceed
     * @return LayoutInterface
     */
    public function aroundGenerateXml(LayoutInterface $subject, callable $proceed): LayoutInterface
    {
        $result = $proceed();

        // If not on Hyva theme, remove any Simplyin HyvaPayment blocks that might have been added
        if (!$this->isHyvaThemeActive()) {
            $this->removeHyvaPaymentBlocks($subject);
        }

        return $result;
    }

    /**
     * Remove Simplyin HyvaPayment blocks from layout when not on Hyva theme
     *
     * @param LayoutInterface $layout
     * @return void
     */
    private function removeHyvaPaymentBlocks(LayoutInterface $layout): void
    {
        // List of block names that should be removed when not on Hyva theme
        $blocksToRemove = [
            'simplyin.hyvapayment.checkout',
            'simplyin.hyvapayment.email.verification',
            'simplyin.hyvapayment.otp.modal',
            'simplyin.hyvapayment.push.notification.modal',
            'simplyin.hyvapayment.account.details.modal',
            'simplyin.hyvapayment.address.selection',
            'simplyin.hyvapayment.shipping.methods',
            'simplyin.hyvapayment.pickup.points',
            'simplyin.hyvapayment.payment.methods',
            'simplyin.hyvapayment.blik.input',
            'simplyin.hyvapayment.new.account.section',
            'simplyin.hyvapayment.cc.iframe',
            'simplyin.hyvapayment.3ds.handler',
            'simplyin.hyvapayment.payment.status',
        ];

        foreach ($blocksToRemove as $blockName) {
            if ($layout->hasElement($blockName)) {
                $layout->unsetElement($blockName);
            }
        }
    }
}
