<?php
/**
 * Licensed Product Type
 *
 * @package Jeremias\WcLicensedProduct\Product
 */

declare(strict_types=1);

namespace Jeremias\WcLicensedProduct\Product;

use Jeremias\WcLicensedProduct\Admin\SettingsController;

/**
 * Registers and handles the Licensed product types for WooCommerce
 * Supports both simple licensed products and variable licensed products
 */
final class LicensedProductType
{
    /**
     * Constructor
     */
    public function __construct()
    {
        $this->registerHooks();
    }

    /**
     * Register WordPress hooks
     */
    private function registerHooks(): void
    {
        // Register product types
        add_filter('product_type_selector', [$this, 'addProductType']);
        add_filter('woocommerce_product_class', [$this, 'getProductClass'], 10, 2);

        // Add product data tabs
        add_filter('woocommerce_product_data_tabs', [$this, 'addProductDataTab']);
        add_action('woocommerce_product_data_panels', [$this, 'addProductDataPanel']);

        // Save product meta
        add_action('woocommerce_process_product_meta_licensed', [$this, 'saveProductMeta']);
        add_action('woocommerce_process_product_meta_licensed-variable', [$this, 'saveProductMeta']);

        // Show price and add to cart for licensed products
        add_action('woocommerce_licensed_add_to_cart', [$this, 'addToCartTemplate']);
        add_action('woocommerce_licensed-variable_add_to_cart', [$this, 'variableAddToCartTemplate']);

        // Make product virtual by default
        add_filter('woocommerce_product_is_virtual', [$this, 'isVirtual'], 10, 2);

        // Display current version under product title on single product page
        add_action('woocommerce_single_product_summary', [$this, 'displayCurrentVersion'], 6);

        // Enqueue frontend CSS for licensed products on single product pages
        add_action('wp_enqueue_scripts', [$this, 'enqueueFrontendStyles']);

        // Variable product support - variation settings
        add_action('woocommerce_variation_options', [$this, 'addVariationOptions'], 10, 3);
        add_action('woocommerce_product_after_variable_attributes', [$this, 'addVariationFields'], 10, 3);
        add_action('woocommerce_save_product_variation', [$this, 'saveVariationFields'], 10, 2);

        // Admin scripts for licensed-variable type
        add_action('admin_footer', [$this, 'addVariableProductScripts']);
    }

    /**
     * Add product types to selector
     */
    public function addProductType(array $types): array
    {
        $types['licensed'] = __('Licensed Product', 'wc-licensed-product');
        $types['licensed-variable'] = __('Licensed Variable Product', 'wc-licensed-product');
        return $types;
    }

    /**
     * Get product class for licensed types
     */
    public function getProductClass(string $className, string $productType): string
    {
        if ($productType === 'licensed') {
            return LicensedProduct::class;
        }
        if ($productType === 'licensed-variable') {
            return LicensedVariableProduct::class;
        }
        // Handle variations of licensed-variable products
        if ($productType === 'variation') {
            // Check if parent is licensed-variable
            global $post;
            if ($post && $post->post_parent) {
                $parentType = \WC_Product_Factory::get_product_type($post->post_parent);
                if ($parentType === 'licensed-variable') {
                    return LicensedProductVariation::class;
                }
            }
        }
        return $className;
    }

    /**
     * Add product data tab for license settings
     */
    public function addProductDataTab(array $tabs): array
    {
        $tabs['licensed_product'] = [
            'label' => __('License Settings', 'wc-licensed-product'),
            'target' => 'licensed_product_data',
            'class' => ['show_if_licensed', 'show_if_licensed-variable'],
            'priority' => 21,
        ];
        return $tabs;
    }

    /**
     * Add product data panel content
     */
    public function addProductDataPanel(): void
    {
        global $post;

        // Get current product values
        $currentMaxActivations = get_post_meta($post->ID, '_licensed_max_activations', true);
        $currentValidityDays = get_post_meta($post->ID, '_licensed_validity_days', true);
        $currentBindToVersion = get_post_meta($post->ID, '_licensed_bind_to_version', true);

        // Get default values
        $defaultMaxActivations = SettingsController::getDefaultMaxActivations();
        $defaultValidityDays = SettingsController::getDefaultValidityDays();
        $defaultBindToVersion = SettingsController::getDefaultBindToVersion();

        // Format default validity for display
        $defaultValidityDisplay = $defaultValidityDays !== null
            ? sprintf(__('%d days', 'wc-licensed-product'), $defaultValidityDays)
            : __('Lifetime', 'wc-licensed-product');

        ?>
        <div id="licensed_product_data" class="panel woocommerce_options_panel hidden">
            <div class="options_group">
                <p class="form-field">
                    <em><?php
                        printf(
                            /* translators: %s: URL to settings page */
                            esc_html__('Leave fields empty to use default settings from %s.', 'wc-licensed-product'),
                            '<a href="' . esc_url(admin_url('admin.php?page=wc-settings&tab=licensed_product')) . '">' .
                            esc_html__('WooCommerce > Settings > Licensed Products', 'wc-licensed-product') . '</a>'
                        );
                    ?></em>
                </p>
                <?php
                woocommerce_wp_text_input([
                    'id' => '_licensed_max_activations',
                    'label' => __('Max Activations', 'wc-licensed-product'),
                    'description' => sprintf(
                        /* translators: %d: default max activations value */
                        __('Maximum number of domain activations per license. Default: %d', 'wc-licensed-product'),
                        $defaultMaxActivations
                    ),
                    'desc_tip' => true,
                    'type' => 'number',
                    'custom_attributes' => [
                        'min' => '1',
                        'step' => '1',
                    ],
                    'placeholder' => (string) $defaultMaxActivations,
                    'value' => $currentMaxActivations,
                ]);

                woocommerce_wp_text_input([
                    'id' => '_licensed_validity_days',
                    'label' => __('License Validity (Days)', 'wc-licensed-product'),
                    'description' => sprintf(
                        /* translators: %s: default validity value */
                        __('Number of days the license is valid. Leave empty for default (%s).', 'wc-licensed-product'),
                        $defaultValidityDisplay
                    ),
                    'desc_tip' => true,
                    'type' => 'number',
                    'custom_attributes' => [
                        'min' => '0',
                        'step' => '1',
                    ],
                    'placeholder' => $defaultValidityDays !== null ? (string) $defaultValidityDays : __('Lifetime', 'wc-licensed-product'),
                    'value' => $currentValidityDays,
                ]);

                woocommerce_wp_checkbox([
                    'id' => '_licensed_bind_to_version',
                    'label' => __('Bind to Major Version', 'wc-licensed-product'),
                    'description' => sprintf(
                        /* translators: %s: default bind to version value (Yes/No) */
                        __('If enabled, licenses are bound to the major version at purchase time. Default: %s', 'wc-licensed-product'),
                        $defaultBindToVersion ? __('Yes', 'wc-licensed-product') : __('No', 'wc-licensed-product')
                    ),
                    'value' => $currentBindToVersion ?: ($defaultBindToVersion ? 'yes' : 'no'),
                    'cbvalue' => 'yes',
                ]);
                ?>
            </div>
        </div>
        <script type="text/javascript">
            jQuery(document).ready(function($) {
                // Show/hide panels based on product type
                $('select#product-type').change(function() {
                    if ($(this).val() === 'licensed') {
                        $('.show_if_licensed').show();
                        $('.general_options').show();
                        $('.pricing').show();
                    } else {
                        $('.show_if_licensed').hide();
                    }
                }).change();

                // Show general tab for licensed products
                $('#product-type').on('change', function() {
                    if ($(this).val() === 'licensed') {
                        $('.general_tab').show();
                    }
                });
            });
        </script>
        <?php
    }

    /**
     * Save product meta
     */
    public function saveProductMeta(int $postId): void
    {
        // Verify nonce is handled by WooCommerce
        // Allow empty values to fall back to defaults
        // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce is verified by WooCommerce
        $maxActivations = isset($_POST['_licensed_max_activations']) && $_POST['_licensed_max_activations'] !== ''
            ? absint($_POST['_licensed_max_activations'])
            : '';
        update_post_meta($postId, '_licensed_max_activations', $maxActivations);

        // phpcs:ignore WordPress.Security.NonceVerification.Missing
        $validityDays = isset($_POST['_licensed_validity_days']) && $_POST['_licensed_validity_days'] !== ''
            ? absint($_POST['_licensed_validity_days'])
            : '';
        update_post_meta($postId, '_licensed_validity_days', $validityDays);

        // For checkbox, we need to distinguish between "not set" and "explicitly unchecked"
        // If the hidden field is present, the form was submitted and we save the actual value
        // phpcs:ignore WordPress.Security.NonceVerification.Missing
        $bindToVersion = isset($_POST['_licensed_bind_to_version']) ? 'yes' : 'no';
        update_post_meta($postId, '_licensed_bind_to_version', $bindToVersion);
    }

    /**
     * Add to cart template for licensed products
     */
    public function addToCartTemplate(): void
    {
        wc_get_template('single-product/add-to-cart/simple.php');
    }

    /**
     * Make licensed products virtual by default
     */
    public function isVirtual(bool $isVirtual, \WC_Product $product): bool
    {
        if ($product->is_type('licensed') || $product->is_type('licensed-variable')) {
            return true;
        }
        // Also handle variations of licensed-variable products
        if ($product->is_type('variation') && $product->get_parent_id()) {
            $parent = wc_get_product($product->get_parent_id());
            if ($parent && $parent->is_type('licensed-variable')) {
                return true;
            }
        }
        return $isVirtual;
    }

    /**
     * Enqueue frontend styles for licensed products on single product pages
     */
    public function enqueueFrontendStyles(): void
    {
        if (!is_product()) {
            return;
        }

        global $product;

        if (!$product || (!$product->is_type('licensed') && !$product->is_type('licensed-variable'))) {
            return;
        }

        wp_enqueue_style(
            'wc-licensed-product-frontend',
            WC_LICENSED_PRODUCT_PLUGIN_URL . 'assets/css/frontend.css',
            [],
            WC_LICENSED_PRODUCT_VERSION
        );
    }

    /**
     * Display current version under product title on single product page
     */
    public function displayCurrentVersion(): void
    {
        global $product;

        if (!$product || (!$product->is_type('licensed') && !$product->is_type('licensed-variable'))) {
            return;
        }

        /** @var LicensedProduct|LicensedVariableProduct $product */
        $version = $product->get_current_version();

        if (empty($version)) {
            return;
        }

        printf(
            '<p class="wclp-product-version"><span class="version-label">%s</span> <span class="version-number">%s</span></p>',
            esc_html__('Version:', 'wc-licensed-product'),
            esc_html($version)
        );
    }

    /**
     * Add to cart template for variable licensed products
     */
    public function variableAddToCartTemplate(): void
    {
        wc_get_template('single-product/add-to-cart/variable.php');
    }

    /**
     * Add variation options (checkboxes next to variation header)
     */
    public function addVariationOptions(int $loop, array $variationData, \WP_Post $variation): void
    {
        // Check if parent is licensed-variable
        $parentId = $variation->post_parent;
        $parentProduct = wc_get_product($parentId);

        if (!$parentProduct || !$parentProduct->is_type('licensed-variable')) {
            return;
        }

        $isVirtual = get_post_meta($variation->ID, '_virtual', true);
        ?>
        <label class="tips" data-tip="<?php esc_attr_e('Licensed products are always virtual', 'wc-licensed-product'); ?>">
            <input type="checkbox" class="checkbox" disabled checked />
            <?php esc_html_e('Virtual', 'wc-licensed-product'); ?>
        </label>
        <?php
    }

    /**
     * Add variation fields for license settings
     */
    public function addVariationFields(int $loop, array $variationData, \WP_Post $variation): void
    {
        // Check if parent is licensed-variable
        $parentId = $variation->post_parent;
        $parentProduct = wc_get_product($parentId);

        if (!$parentProduct || !$parentProduct->is_type('licensed-variable')) {
            return;
        }

        // Get variation values
        $validityDays = get_post_meta($variation->ID, '_licensed_validity_days', true);
        $maxActivations = get_post_meta($variation->ID, '_licensed_max_activations', true);

        // Get parent defaults for placeholder
        $parentValidityDays = $parentProduct->get_validity_days();
        $parentMaxActivations = $parentProduct->get_max_activations();

        $parentValidityDisplay = $parentValidityDays !== null
            ? sprintf(__('%d days', 'wc-licensed-product'), $parentValidityDays)
            : __('Lifetime', 'wc-licensed-product');

        ?>
        <div class="wclp-variation-license-settings">
            <p class="form-row form-row-first">
                <label><?php esc_html_e('License Duration (Days)', 'wc-licensed-product'); ?></label>
                <input type="number"
                       name="wclp_validity_days[<?php echo esc_attr($loop); ?>]"
                       class="short"
                       min="0"
                       step="1"
                       placeholder="<?php echo esc_attr($parentValidityDisplay); ?>"
                       value="<?php echo esc_attr($validityDays); ?>"
                />
                <span class="description"><?php esc_html_e('Leave empty for parent default. 0 = Lifetime.', 'wc-licensed-product'); ?></span>
            </p>
            <p class="form-row form-row-last">
                <label><?php esc_html_e('Max Activations', 'wc-licensed-product'); ?></label>
                <input type="number"
                       name="wclp_max_activations[<?php echo esc_attr($loop); ?>]"
                       class="short"
                       min="1"
                       step="1"
                       placeholder="<?php echo esc_attr($parentMaxActivations); ?>"
                       value="<?php echo esc_attr($maxActivations); ?>"
                />
                <span class="description"><?php esc_html_e('Leave empty for parent default.', 'wc-licensed-product'); ?></span>
            </p>
        </div>
        <style>
            .wclp-variation-license-settings {
                background: #f8f8f8;
                border: 1px solid #e5e5e5;
                padding: 10px;
                margin: 10px 0;
                border-radius: 4px;
            }
            .wclp-variation-license-settings .description {
                display: block;
                font-style: italic;
                color: #666;
                margin-top: 4px;
            }
        </style>
        <?php
    }

    /**
     * Save variation fields
     */
    public function saveVariationFields(int $variationId, int $loop): void
    {
        // Check if parent is licensed-variable
        $variation = wc_get_product($variationId);
        if (!$variation) {
            return;
        }

        $parentProduct = wc_get_product($variation->get_parent_id());
        if (!$parentProduct || !$parentProduct->is_type('licensed-variable')) {
            return;
        }

        // Save validity days
        // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce is verified by WooCommerce
        if (isset($_POST['wclp_validity_days'][$loop])) {
            // phpcs:ignore WordPress.Security.NonceVerification.Missing
            $validityDays = sanitize_text_field($_POST['wclp_validity_days'][$loop]);
            if ($validityDays !== '') {
                update_post_meta($variationId, '_licensed_validity_days', absint($validityDays));
            } else {
                delete_post_meta($variationId, '_licensed_validity_days');
            }
        }

        // Save max activations
        // phpcs:ignore WordPress.Security.NonceVerification.Missing
        if (isset($_POST['wclp_max_activations'][$loop])) {
            // phpcs:ignore WordPress.Security.NonceVerification.Missing
            $maxActivations = sanitize_text_field($_POST['wclp_max_activations'][$loop]);
            if ($maxActivations !== '') {
                update_post_meta($variationId, '_licensed_max_activations', absint($maxActivations));
            } else {
                delete_post_meta($variationId, '_licensed_max_activations');
            }
        }

        // Set variation as virtual (licensed products are always virtual)
        update_post_meta($variationId, '_virtual', 'yes');
    }

    /**
     * Add JavaScript for licensed-variable product type in admin
     */
    public function addVariableProductScripts(): void
    {
        global $post, $pagenow;

        if ($pagenow !== 'post.php' && $pagenow !== 'post-new.php') {
            return;
        }

        if (!$post || get_post_type($post) !== 'product') {
            return;
        }

        ?>
        <script type="text/javascript">
            jQuery(document).ready(function($) {
                // Show/hide panels based on product type
                function toggleLicensedVariableOptions() {
                    var productType = $('#product-type').val();

                    if (productType === 'licensed-variable') {
                        // Show variable product options
                        $('.show_if_variable').show();
                        $('.hide_if_variable').hide();

                        // Show licensed product options
                        $('.show_if_licensed-variable').show();
                        $('.show_if_licensed').show();

                        // Show general and variations tabs
                        $('.general_tab').show();
                        $('.variations_tab').show();

                        // Hide shipping tab (virtual products)
                        $('.shipping_tab').hide();
                    }
                }

                // Initial check
                toggleLicensedVariableOptions();

                // On product type change
                $('#product-type').on('change', function() {
                    toggleLicensedVariableOptions();
                });
            });
        </script>
        <?php
    }
}
