<?php
/**
 * Order License Admin Controller
 *
 * @package Jeremias\WcLicensedProduct\Admin
 */

declare(strict_types=1);

namespace Jeremias\WcLicensedProduct\Admin;

use Jeremias\WcLicensedProduct\License\License;
use Jeremias\WcLicensedProduct\License\LicenseManager;

/**
 * Handles license display and editing on order admin pages
 */
final class OrderLicenseController
{
    private LicenseManager $licenseManager;

    public function __construct(LicenseManager $licenseManager)
    {
        $this->licenseManager = $licenseManager;
        $this->registerHooks();
    }

    /**
     * Register WordPress hooks
     */
    private function registerHooks(): void
    {
        // Add licenses meta box to order edit page
        add_action('add_meta_boxes', [$this, 'addLicensesMetaBox']);

        // Handle AJAX actions
        add_action('wp_ajax_wclp_update_order_domain', [$this, 'ajaxUpdateOrderDomain']);
        add_action('wp_ajax_wclp_update_license_domain', [$this, 'ajaxUpdateLicenseDomain']);
        add_action('wp_ajax_wclp_generate_order_licenses', [$this, 'ajaxGenerateOrderLicenses']);

        // Enqueue admin scripts
        add_action('admin_enqueue_scripts', [$this, 'enqueueScripts']);
    }

    /**
     * Add licenses meta box to order edit page
     */
    public function addLicensesMetaBox(): void
    {
        // Support both classic post type and HPOS
        $screen = wc_get_container()->get(\Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController::class)->custom_orders_table_usage_is_enabled()
            ? wc_get_page_screen_id('shop-order')
            : 'shop_order';

        add_meta_box(
            'wclp_order_licenses',
            __('Product Licenses', 'wc-licensed-product'),
            [$this, 'renderLicensesMetaBox'],
            $screen,
            'normal',
            'default'
        );
    }

    /**
     * Render licenses meta box
     */
    public function renderLicensesMetaBox($post_or_order): void
    {
        // Get order object - support both classic and HPOS
        if ($post_or_order instanceof \WC_Order) {
            $order = $post_or_order;
        } else {
            $order = wc_get_order($post_or_order->ID);
        }

        if (!$order) {
            echo '<p>' . esc_html__('Order not found.', 'wc-licensed-product') . '</p>';
            return;
        }

        // Check if order has licensed products
        $hasLicensedProduct = false;
        foreach ($order->get_items() as $item) {
            $product = $item->get_product();
            if ($product && $product->is_type('licensed')) {
                $hasLicensedProduct = true;
                break;
            }
        }

        if (!$hasLicensedProduct) {
            echo '<p>' . esc_html__('This order does not contain licensed products.', 'wc-licensed-product') . '</p>';
            return;
        }

        // Check for multi-domain format first, then fall back to legacy single domain
        $multiDomainData = $order->get_meta('_licensed_product_domains');
        $legacyDomain = $order->get_meta('_licensed_product_domain');
        $hasMultiDomain = !empty($multiDomainData) && is_array($multiDomainData);

        // Get licenses for this order
        $licenses = $this->licenseManager->getLicensesByOrder($order->get_id());

        wp_nonce_field('wclp_order_license_actions', 'wclp_order_license_nonce');
        ?>
        <div class="wclp-order-licenses">
            <div class="wclp-order-domain-section">
                <h4><?php esc_html_e('Order Domains', 'wc-licensed-product'); ?></h4>

                <?php if ($hasMultiDomain): ?>
                    <p class="description">
                        <?php esc_html_e('Domains specified during checkout (multi-domain order).', 'wc-licensed-product'); ?>
                    </p>
                    <div class="wclp-multi-domain-display" style="margin-top: 10px;">
                        <?php foreach ($multiDomainData as $item): ?>
                            <?php
                            $product = wc_get_product($item['product_id']);
                            $productName = $product ? $product->get_name() : __('Unknown Product', 'wc-licensed-product');
                            ?>
                            <div class="wclp-product-domains-item" style="margin-bottom: 10px; padding: 10px; background: #f8f8f8; border-radius: 4px;">
                                <strong><?php echo esc_html($productName); ?>:</strong><br>
                                <code><?php echo esc_html(implode(', ', $item['domains'])); ?></code>
                            </div>
                        <?php endforeach; ?>
                    </div>
                <?php else: ?>
                    <p class="description">
                        <?php esc_html_e('The domain specified during checkout. Changing this will not automatically update existing license domains.', 'wc-licensed-product'); ?>
                    </p>
                    <div class="wclp-inline-edit">
                        <input type="text"
                               id="wclp-order-domain"
                               class="regular-text"
                               value="<?php echo esc_attr($legacyDomain); ?>"
                               data-order-id="<?php echo esc_attr($order->get_id()); ?>"
                               placeholder="<?php esc_attr_e('example.com', 'wc-licensed-product'); ?>" />
                        <button type="button" class="button" id="wclp-save-order-domain">
                            <?php esc_html_e('Save', 'wc-licensed-product'); ?>
                        </button>
                        <span class="spinner"></span>
                        <span class="wclp-status-message"></span>
                    </div>
                <?php endif; ?>
            </div>

            <hr />

            <h4><?php esc_html_e('Licenses', 'wc-licensed-product'); ?></h4>

            <?php
            // Count expected licenses based on domain data
            $expectedLicenses = 0;
            if ($hasMultiDomain) {
                // Multi-domain: count total domains across all products
                foreach ($multiDomainData as $item) {
                    if (isset($item['domains']) && is_array($item['domains'])) {
                        $expectedLicenses += count($item['domains']);
                    }
                }
            } else {
                // Legacy: one license per licensed product
                foreach ($order->get_items() as $item) {
                    $product = $item->get_product();
                    if ($product && $product->is_type('licensed')) {
                        $expectedLicenses++;
                    }
                }
            }
            $missingLicenses = $expectedLicenses - count($licenses);
            $hasDomainData = $hasMultiDomain || !empty($legacyDomain);
            ?>

            <?php if (empty($licenses)): ?>
                <p class="description">
                    <?php esc_html_e('No licenses have been generated for this order yet.', 'wc-licensed-product'); ?>
                    <?php if ($order->is_paid()): ?>
                        <br />
                        <em><?php esc_html_e('Licenses should be generated automatically when an order is paid. If missing, check that a domain was specified during checkout.', 'wc-licensed-product'); ?></em>
                    <?php else: ?>
                        <br />
                        <em><?php esc_html_e('Licenses will be generated when the order is marked as paid/completed.', 'wc-licensed-product'); ?></em>
                    <?php endif; ?>
                </p>
                <?php if ($hasDomainData && $order->is_paid()): ?>
                    <p style="margin-top: 10px;">
                        <button type="button" class="button button-primary" id="wclp-generate-licenses" data-order-id="<?php echo esc_attr($order->get_id()); ?>">
                            <?php esc_html_e('Generate Licenses', 'wc-licensed-product'); ?>
                        </button>
                        <span class="spinner" style="float: none; margin-top: 4px;"></span>
                        <span class="wclp-generate-status"></span>
                    </p>
                <?php elseif (!$hasDomainData): ?>
                    <p class="description" style="margin-top: 10px; color: #d63638;">
                        <span class="dashicons dashicons-warning"></span>
                        <?php esc_html_e('Please set the order domain above before generating licenses.', 'wc-licensed-product'); ?>
                    </p>
                <?php endif; ?>
            <?php else: ?>
                <table class="widefat striped wclp-licenses-table">
                    <thead>
                        <tr>
                            <th><?php esc_html_e('License Key', 'wc-licensed-product'); ?></th>
                            <th><?php esc_html_e('Product', 'wc-licensed-product'); ?></th>
                            <th><?php esc_html_e('Domain', 'wc-licensed-product'); ?></th>
                            <th><?php esc_html_e('Status', 'wc-licensed-product'); ?></th>
                            <th><?php esc_html_e('Expires', 'wc-licensed-product'); ?></th>
                            <th><?php esc_html_e('Actions', 'wc-licensed-product'); ?></th>
                        </tr>
                    </thead>
                    <tbody>
                        <?php foreach ($licenses as $license): ?>
                            <?php
                            $product = wc_get_product($license->getProductId());
                            $statusClass = 'wclp-status-' . $license->getStatus();
                            ?>
                            <tr data-license-id="<?php echo esc_attr($license->getId()); ?>">
                                <td>
                                    <code class="wclp-license-key"><?php echo esc_html($license->getLicenseKey()); ?></code>
                                </td>
                                <td>
                                    <?php if ($product): ?>
                                        <a href="<?php echo esc_url(get_edit_post_link($product->get_id())); ?>">
                                            <?php echo esc_html($product->get_name()); ?>
                                        </a>
                                    <?php else: ?>
                                        <?php esc_html_e('Unknown', 'wc-licensed-product'); ?>
                                    <?php endif; ?>
                                </td>
                                <td>
                                    <div class="wclp-license-domain-edit">
                                        <span class="wclp-domain-display"><?php echo esc_html($license->getDomain()); ?></span>
                                        <input type="text"
                                               class="wclp-domain-input regular-text"
                                               value="<?php echo esc_attr($license->getDomain()); ?>"
                                               style="display: none;" />
                                        <button type="button" class="button-link wclp-edit-domain-btn" title="<?php esc_attr_e('Edit domain', 'wc-licensed-product'); ?>">
                                            <span class="dashicons dashicons-edit"></span>
                                        </button>
                                        <button type="button" class="button button-small wclp-save-domain-btn" style="display: none;">
                                            <?php esc_html_e('Save', 'wc-licensed-product'); ?>
                                        </button>
                                        <button type="button" class="button-link wclp-cancel-domain-btn" style="display: none;">
                                            <?php esc_html_e('Cancel', 'wc-licensed-product'); ?>
                                        </button>
                                        <span class="spinner"></span>
                                    </div>
                                </td>
                                <td>
                                    <span class="wclp-license-status <?php echo esc_attr($statusClass); ?>">
                                        <?php echo esc_html(ucfirst($license->getStatus())); ?>
                                    </span>
                                </td>
                                <td>
                                    <?php
                                    $expiresAt = $license->getExpiresAt();
                                    if ($expiresAt) {
                                        echo esc_html($expiresAt->format(get_option('date_format')));
                                    } else {
                                        echo '<span class="wclp-lifetime">' . esc_html__('Lifetime', 'wc-licensed-product') . '</span>';
                                    }
                                    ?>
                                </td>
                                <td>
                                    <a href="<?php echo esc_url(admin_url('admin.php?page=wc-licenses&s=' . urlencode($license->getLicenseKey()))); ?>"
                                       class="button button-small"
                                       title="<?php esc_attr_e('View in Licenses', 'wc-licensed-product'); ?>">
                                        <span class="dashicons dashicons-visibility" style="vertical-align: middle;"></span>
                                    </a>
                                </td>
                            </tr>
                        <?php endforeach; ?>
                    </tbody>
                </table>

                <p class="description" style="margin-top: 10px;">
                    <?php
                    printf(
                        /* translators: %s: Link to licenses page */
                        esc_html__('For more actions (revoke, extend, delete), go to the %s page.', 'wc-licensed-product'),
                        '<a href="' . esc_url(admin_url('admin.php?page=wc-licenses')) . '">' . esc_html__('Licenses', 'wc-licensed-product') . '</a>'
                    );
                    ?>
                </p>

                <?php if ($missingLicenses > 0 && $hasDomainData && $order->is_paid()): ?>
                    <p style="margin-top: 10px;">
                        <span class="dashicons dashicons-warning" style="color: #dba617;"></span>
                        <?php
                        printf(
                            /* translators: %d: Number of missing licenses */
                            esc_html(_n(
                                '%d licensed product is missing a license.',
                                '%d licensed products are missing licenses.',
                                $missingLicenses,
                                'wc-licensed-product'
                            )),
                            $missingLicenses
                        );
                        ?>
                        <button type="button" class="button" id="wclp-generate-licenses" data-order-id="<?php echo esc_attr($order->get_id()); ?>">
                            <?php esc_html_e('Generate Missing Licenses', 'wc-licensed-product'); ?>
                        </button>
                        <span class="spinner" style="float: none; margin-top: 4px;"></span>
                        <span class="wclp-generate-status"></span>
                    </p>
                <?php endif; ?>
            <?php endif; ?>
        </div>

        <style>
            .wclp-order-licenses { padding: 10px 0; }
            .wclp-order-domain-section { margin-bottom: 15px; }
            .wclp-inline-edit { display: flex; align-items: center; gap: 8px; margin-top: 8px; }
            .wclp-inline-edit .spinner { float: none; margin: 0; }
            .wclp-status-message { font-style: italic; color: #666; }
            .wclp-status-message.success { color: #46b450; }
            .wclp-status-message.error { color: #dc3232; }
            .wclp-licenses-table { margin-top: 10px; }
            .wclp-licenses-table th, .wclp-licenses-table td { padding: 8px 10px; vertical-align: middle; }
            .wclp-license-key { font-size: 12px; }
            .wclp-license-domain-edit { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }
            .wclp-license-domain-edit .spinner { float: none; margin: 0; }
            .wclp-domain-input { max-width: 200px; }
            .wclp-license-status { padding: 3px 8px; border-radius: 3px; font-size: 11px; font-weight: 600; text-transform: uppercase; }
            .wclp-status-active { background: #d4edda; color: #155724; }
            .wclp-status-inactive { background: #fff3cd; color: #856404; }
            .wclp-status-expired { background: #f8d7da; color: #721c24; }
            .wclp-status-revoked { background: #d6d8db; color: #383d41; }
            .wclp-lifetime { color: #0073aa; font-weight: 500; }
            .wclp-edit-domain-btn { color: #0073aa; text-decoration: none; }
            .wclp-edit-domain-btn .dashicons { font-size: 16px; width: 16px; height: 16px; }
            .wclp-generate-status { font-style: italic; margin-left: 8px; }
            .wclp-generate-status.success { color: #46b450; }
            .wclp-generate-status.error { color: #dc3232; }
        </style>
        <?php
    }

    /**
     * Enqueue admin scripts
     */
    public function enqueueScripts(string $hook): void
    {
        // Check if we're on an order edit page
        $screen = get_current_screen();
        if (!$screen) {
            return;
        }

        $isOrderEdit = in_array($screen->id, ['shop_order', 'woocommerce_page_wc-orders'], true)
            || (isset($_GET['page']) && $_GET['page'] === 'wc-orders' && isset($_GET['action']) && $_GET['action'] === 'edit');

        if (!$isOrderEdit) {
            return;
        }

        wp_enqueue_script(
            'wclp-order-licenses',
            WC_LICENSED_PRODUCT_PLUGIN_URL . 'assets/js/order-licenses.js',
            ['jquery'],
            WC_LICENSED_PRODUCT_VERSION,
            true
        );

        wp_localize_script('wclp-order-licenses', 'wclpOrderLicenses', [
            'ajaxUrl' => admin_url('admin-ajax.php'),
            'nonce' => wp_create_nonce('wclp_order_license_actions'),
            'strings' => [
                'saving' => __('Saving...', 'wc-licensed-product'),
                'saved' => __('Saved!', 'wc-licensed-product'),
                'error' => __('Error. Please try again.', 'wc-licensed-product'),
                'invalidDomain' => __('Please enter a valid domain.', 'wc-licensed-product'),
                'generating' => __('Generating...', 'wc-licensed-product'),
            ],
        ]);
    }

    /**
     * AJAX handler for updating order domain
     */
    public function ajaxUpdateOrderDomain(): void
    {
        check_ajax_referer('wclp_order_license_actions', 'nonce');

        if (!current_user_can('manage_woocommerce')) {
            wp_send_json_error(['message' => __('Permission denied.', 'wc-licensed-product')]);
        }

        $orderId = absint($_POST['order_id'] ?? 0);
        $domain = sanitize_text_field($_POST['domain'] ?? '');

        if (!$orderId) {
            wp_send_json_error(['message' => __('Invalid order ID.', 'wc-licensed-product')]);
        }

        $order = wc_get_order($orderId);
        if (!$order) {
            wp_send_json_error(['message' => __('Order not found.', 'wc-licensed-product')]);
        }

        // Normalize and validate domain
        $normalizedDomain = $this->licenseManager->normalizeDomain($domain);
        if (!empty($domain) && !$this->isValidDomain($normalizedDomain)) {
            wp_send_json_error(['message' => __('Invalid domain format.', 'wc-licensed-product')]);
        }

        // Update order meta
        $order->update_meta_data('_licensed_product_domain', $normalizedDomain);
        $order->save();

        wp_send_json_success([
            'message' => __('Order domain updated.', 'wc-licensed-product'),
            'domain' => $normalizedDomain,
        ]);
    }

    /**
     * AJAX handler for updating license domain
     */
    public function ajaxUpdateLicenseDomain(): void
    {
        check_ajax_referer('wclp_order_license_actions', 'nonce');

        if (!current_user_can('manage_woocommerce')) {
            wp_send_json_error(['message' => __('Permission denied.', 'wc-licensed-product')]);
        }

        $licenseId = absint($_POST['license_id'] ?? 0);
        $domain = sanitize_text_field($_POST['domain'] ?? '');

        if (!$licenseId) {
            wp_send_json_error(['message' => __('Invalid license ID.', 'wc-licensed-product')]);
        }

        if (empty($domain)) {
            wp_send_json_error(['message' => __('Domain cannot be empty.', 'wc-licensed-product')]);
        }

        // Normalize and validate domain
        $normalizedDomain = $this->licenseManager->normalizeDomain($domain);
        if (!$this->isValidDomain($normalizedDomain)) {
            wp_send_json_error(['message' => __('Invalid domain format.', 'wc-licensed-product')]);
        }

        // Get license to verify it exists
        $license = $this->licenseManager->getLicenseById($licenseId);
        if (!$license) {
            wp_send_json_error(['message' => __('License not found.', 'wc-licensed-product')]);
        }

        // Update license domain
        $success = $this->licenseManager->updateLicenseDomain($licenseId, $normalizedDomain);

        if ($success) {
            wp_send_json_success([
                'message' => __('License domain updated.', 'wc-licensed-product'),
                'domain' => $normalizedDomain,
            ]);
        } else {
            wp_send_json_error(['message' => __('Failed to update license domain.', 'wc-licensed-product')]);
        }
    }

    /**
     * Validate domain format
     */
    private function isValidDomain(string $domain): bool
    {
        if (empty($domain)) {
            return true; // Empty is allowed for order domain
        }

        if (strlen($domain) > 255) {
            return false;
        }

        $pattern = '/^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/';
        return (bool) preg_match($pattern, $domain);
    }

    /**
     * AJAX handler for generating order licenses
     */
    public function ajaxGenerateOrderLicenses(): void
    {
        check_ajax_referer('wclp_order_license_actions', 'nonce');

        if (!current_user_can('manage_woocommerce')) {
            wp_send_json_error(['message' => __('Permission denied.', 'wc-licensed-product')]);
        }

        $orderId = absint($_POST['order_id'] ?? 0);

        if (!$orderId) {
            wp_send_json_error(['message' => __('Invalid order ID.', 'wc-licensed-product')]);
        }

        $order = wc_get_order($orderId);
        if (!$order) {
            wp_send_json_error(['message' => __('Order not found.', 'wc-licensed-product')]);
        }

        // Check if order is paid
        if (!$order->is_paid()) {
            wp_send_json_error(['message' => __('Order must be paid before licenses can be generated.', 'wc-licensed-product')]);
        }

        // Check for multi-domain format first
        $multiDomainData = $order->get_meta('_licensed_product_domains');
        $legacyDomain = $order->get_meta('_licensed_product_domain');

        if (!empty($multiDomainData) && is_array($multiDomainData)) {
            // Multi-domain format
            $result = $this->generateMultiDomainLicenses($order, $multiDomainData);
        } elseif (!empty($legacyDomain)) {
            // Legacy single domain format
            $result = $this->generateLegacyLicenses($order, $legacyDomain);
        } else {
            wp_send_json_error(['message' => __('Please set the order domain before generating licenses.', 'wc-licensed-product')]);
            return;
        }

        if ($result['generated'] > 0) {
            wp_send_json_success([
                'message' => sprintf(
                    /* translators: %d: Number of licenses generated */
                    _n(
                        '%d license generated successfully.',
                        '%d licenses generated successfully.',
                        $result['generated'],
                        'wc-licensed-product'
                    ),
                    $result['generated']
                ),
                'generated' => $result['generated'],
                'skipped' => $result['skipped'],
                'reload' => true,
            ]);
        } else {
            wp_send_json_success([
                'message' => __('All licenses already exist for this order.', 'wc-licensed-product'),
                'generated' => 0,
                'skipped' => $result['skipped'],
                'reload' => false,
            ]);
        }
    }

    /**
     * Generate licenses for multi-domain format
     */
    private function generateMultiDomainLicenses(\WC_Order $order, array $domainData): array
    {
        $generated = 0;
        $skipped = 0;
        $orderId = $order->get_id();
        $customerId = $order->get_customer_id();

        // Index domains by product ID
        $domainsByProduct = [];
        foreach ($domainData as $item) {
            if (isset($item['product_id']) && isset($item['domains']) && is_array($item['domains'])) {
                $domainsByProduct[(int) $item['product_id']] = $item['domains'];
            }
        }

        foreach ($order->get_items() as $item) {
            $product = $item->get_product();
            if (!$product || !$product->is_type('licensed')) {
                continue;
            }

            $productId = $product->get_id();
            $domains = $domainsByProduct[$productId] ?? [];

            // Get existing licenses for this product
            $existingLicenses = $this->licenseManager->getLicensesByOrderAndProduct($orderId, $productId);
            $existingDomains = array_map(fn($l) => $l->getDomain(), $existingLicenses);

            foreach ($domains as $domain) {
                $normalizedDomain = $this->licenseManager->normalizeDomain($domain);

                // Skip if license already exists for this domain
                if (in_array($normalizedDomain, $existingDomains, true)) {
                    $skipped++;
                    continue;
                }

                $license = $this->licenseManager->generateLicense(
                    $orderId,
                    $productId,
                    $customerId,
                    $normalizedDomain
                );

                if ($license) {
                    $generated++;
                }
            }
        }

        return ['generated' => $generated, 'skipped' => $skipped];
    }

    /**
     * Generate licenses for legacy single domain format
     */
    private function generateLegacyLicenses(\WC_Order $order, string $domain): array
    {
        $generated = 0;
        $skipped = 0;
        $orderId = $order->get_id();
        $customerId = $order->get_customer_id();

        foreach ($order->get_items() as $item) {
            $product = $item->get_product();
            if (!$product || !$product->is_type('licensed')) {
                continue;
            }

            // Check if license already exists
            $existing = $this->licenseManager->getLicenseByOrderAndProduct($orderId, $product->get_id());
            if ($existing) {
                $skipped++;
                continue;
            }

            $license = $this->licenseManager->generateLicense(
                $orderId,
                $product->get_id(),
                $customerId,
                $domain
            );

            if ($license) {
                $generated++;
            }
        }

        return ['generated' => $generated, 'skipped' => $skipped];
    }
}
