<?php
/**
 * Frontend Account Controller
 *
 * @package Jeremias\WcLicensedProduct\Frontend
 */

declare(strict_types=1);

namespace Jeremias\WcLicensedProduct\Frontend;

use Jeremias\WcLicensedProduct\Api\ResponseSigner;
use Jeremias\WcLicensedProduct\License\LicenseManager;
use Jeremias\WcLicensedProduct\Product\VersionManager;
use Twig\Environment;

/**
 * Handles customer account pages for viewing licenses
 */
final class AccountController
{
    private Environment $twig;
    private LicenseManager $licenseManager;
    private VersionManager $versionManager;
    private DownloadController $downloadController;

    public function __construct(
        Environment $twig,
        LicenseManager $licenseManager,
        VersionManager $versionManager,
        DownloadController $downloadController
    ) {
        $this->twig = $twig;
        $this->licenseManager = $licenseManager;
        $this->versionManager = $versionManager;
        $this->downloadController = $downloadController;
        $this->registerHooks();
    }

    /**
     * Register WordPress hooks
     */
    private function registerHooks(): void
    {
        // Add licenses endpoint
        add_action('init', [$this, 'addLicensesEndpoint']);

        // Register endpoint query var with WooCommerce
        add_filter('woocommerce_get_query_vars', [$this, 'addLicensesQueryVar']);

        // Add licenses menu item
        add_filter('woocommerce_account_menu_items', [$this, 'addLicensesMenuItem']);

        // Add licenses endpoint content
        add_action('woocommerce_account_licenses_endpoint', [$this, 'displayLicensesContent']);

        // Enqueue frontend styles and scripts
        add_action('wp_enqueue_scripts', [$this, 'enqueueAssets']);

        // AJAX handler for license transfer request
        add_action('wp_ajax_wclp_customer_transfer_license', [$this, 'handleTransferRequest']);
    }

    /**
     * Add licenses endpoint for My Account
     */
    public function addLicensesEndpoint(): void
    {
        add_rewrite_endpoint('licenses', EP_ROOT | EP_PAGES);
    }

    /**
     * Register licenses query var with WooCommerce
     */
    public function addLicensesQueryVar(array $vars): array
    {
        $vars['licenses'] = 'licenses';
        return $vars;
    }

    /**
     * Add licenses menu item to My Account navigation
     */
    public function addLicensesMenuItem(array $items): array
    {
        // Insert licenses after orders
        $newItems = [];
        foreach ($items as $key => $value) {
            $newItems[$key] = $value;
            if ($key === 'orders') {
                $newItems['licenses'] = __('Licenses', 'wc-licensed-product');
            }
        }

        return $newItems;
    }

    /**
     * Display licenses content in My Account
     */
    public function displayLicensesContent(): void
    {
        $customerId = get_current_user_id();
        if (!$customerId) {
            echo '<p>' . esc_html__('Please log in to view your licenses.', 'wc-licensed-product') . '</p>';
            return;
        }

        $licenses = $this->licenseManager->getLicensesByCustomer($customerId);

        // Group licenses by product+order into "packages"
        $packages = $this->groupLicensesIntoPackages($licenses);

        try {
            echo $this->twig->render('frontend/licenses.html.twig', [
                'packages' => $packages,
                'has_packages' => !empty($packages),
                'signing_enabled' => ResponseSigner::isSigningEnabled(),
            ]);
        } catch (\Exception $e) {
            // Fallback to PHP template if Twig fails
            $this->displayLicensesFallback($packages);
        }
    }

    /**
     * Group licenses into packages by product+order
     *
     * @param array $licenses Array of License objects
     * @return array Array of package data
     */
    private function groupLicensesIntoPackages(array $licenses): array
    {
        $grouped = [];

        foreach ($licenses as $license) {
            $productId = $license->getProductId();
            $orderId = $license->getOrderId();
            $key = $productId . '_' . $orderId;

            if (!isset($grouped[$key])) {
                $product = wc_get_product($productId);
                $order = wc_get_order($orderId);

                $grouped[$key] = [
                    'product_id' => $productId,
                    'order_id' => $orderId,
                    'product_name' => $product ? $product->get_name() : __('Unknown Product', 'wc-licensed-product'),
                    'product_url' => $product ? $product->get_permalink() : '',
                    'order_number' => $order ? $order->get_order_number() : '',
                    'order_url' => $order ? $order->get_view_order_url() : '',
                    'licenses' => [],
                    'downloads' => [],
                    'has_active_license' => false,
                ];
            }

            // Add license to package
            $grouped[$key]['licenses'][] = [
                'id' => $license->getId(),
                'license_key' => $license->getLicenseKey(),
                'domain' => $license->getDomain(),
                'status' => $license->getStatus(),
                'expires_at' => $license->getExpiresAt(),
                'is_transferable' => in_array($license->getStatus(), ['active', 'inactive'], true),
                'customer_secret' => ResponseSigner::getCustomerSecretForLicense($license->getLicenseKey()),
            ];

            // Track if package has at least one active license
            if ($license->getStatus() === 'active') {
                $grouped[$key]['has_active_license'] = true;
            }
        }

        // Add downloads for packages with active licenses
        foreach ($grouped as $key => &$package) {
            if ($package['has_active_license']) {
                $package['downloads'] = $this->getDownloadsForProduct(
                    $package['product_id'],
                    $package['licenses'][0]['id'] // Use first license for download URL
                );
            }
        }

        // Sort by order date (newest first) - re-index array
        return array_values($grouped);
    }

    /**
     * Get downloads for a product
     */
    private function getDownloadsForProduct(int $productId, int $licenseId): array
    {
        $downloads = [];
        $versions = $this->versionManager->getVersionsByProduct($productId);

        foreach ($versions as $version) {
            if ($version->isActive() && ($version->getAttachmentId() || $version->getDownloadUrl())) {
                $downloads[] = [
                    'version' => $version->getVersion(),
                    'version_id' => $version->getId(),
                    'filename' => $version->getDownloadFilename(),
                    'download_url' => $this->downloadController->generateDownloadUrl(
                        $licenseId,
                        $version->getId()
                    ),
                    'release_notes' => $version->getReleaseNotes(),
                    'released_at' => $version->getReleasedAt()->format(get_option('date_format')),
                    'file_hash' => $version->getFileHash(),
                ];
            }
        }

        return $downloads;
    }

    /**
     * Fallback display method if Twig is unavailable
     */
    private function displayLicensesFallback(array $packages): void
    {
        if (empty($packages)) {
            echo '<p>' . esc_html__('You have no licenses yet.', 'wc-licensed-product') . '</p>';
            return;
        }

        ?>
        <div class="woocommerce-licenses">
            <?php foreach ($packages as $package): ?>
                <div class="license-package">
                    <div class="package-header">
                        <h3>
                            <?php if ($package['product_url']): ?>
                                <a href="<?php echo esc_url($package['product_url']); ?>">
                                    <?php echo esc_html($package['product_name']); ?>
                                </a>
                            <?php else: ?>
                                <?php echo esc_html($package['product_name']); ?>
                            <?php endif; ?>
                        </h3>
                        <span class="package-order">
                            <?php
                            printf(
                                /* translators: %s: order number */
                                esc_html__('Order #%s', 'wc-licensed-product'),
                                esc_html($package['order_number'])
                            );
                            ?>
                        </span>
                    </div>

                    <div class="package-licenses">
                        <?php foreach ($package['licenses'] as $license): ?>
                            <div class="license-entry license-entry-<?php echo esc_attr($license['status']); ?>">
                                <div class="license-row-primary">
                                    <div class="license-key-group">
                                        <code class="license-key"><?php echo esc_html($license['license_key']); ?></code>
                                        <span class="license-status license-status-<?php echo esc_attr($license['status']); ?>">
                                            <?php echo esc_html(ucfirst($license['status'])); ?>
                                        </span>
                                    </div>
                                    <div class="license-actions">
                                        <button type="button" class="copy-license-btn" data-license-key="<?php echo esc_attr($license['license_key']); ?>" title="<?php esc_attr_e('Copy to clipboard', 'wc-licensed-product'); ?>">
                                            <span class="dashicons dashicons-clipboard"></span>
                                        </button>
                                        <?php if ($license['is_transferable']): ?>
                                            <button type="button" class="wclp-transfer-btn"
                                                    data-license-id="<?php echo esc_attr($license['id']); ?>"
                                                    data-current-domain="<?php echo esc_attr($license['domain']); ?>"
                                                    title="<?php esc_attr_e('Transfer to new domain', 'wc-licensed-product'); ?>">
                                                <span class="dashicons dashicons-randomize"></span>
                                            </button>
                                        <?php endif; ?>
                                    </div>
                                </div>
                                <div class="license-row-secondary">
                                    <span class="license-meta-item license-domain">
                                        <span class="dashicons dashicons-admin-site-alt3"></span>
                                        <?php echo esc_html($license['domain']); ?>
                                    </span>
                                    <span class="license-meta-item license-expiry">
                                        <span class="dashicons dashicons-calendar-alt"></span>
                                        <?php
                                        echo $license['expires_at']
                                            ? esc_html($license['expires_at']->format('Y-m-d'))
                                            : '<span class="lifetime">' . esc_html__('Lifetime', 'wc-licensed-product') . '</span>';
                                        ?>
                                    </span>
                                </div>
                            </div>
                        <?php endforeach; ?>
                    </div>

                    <?php if (!empty($package['downloads'])): ?>
                        <div class="package-downloads">
                            <h4><?php esc_html_e('Available Downloads', 'wc-licensed-product'); ?></h4>
                            <ul class="download-list">
                                <?php
                                $latest = $package['downloads'][0];
                                ?>
                                <li class="download-item download-item-latest">
                                    <div class="download-row-file">
                                        <a href="<?php echo esc_url($latest['download_url']); ?>" class="download-link">
                                            <span class="dashicons dashicons-download"></span>
                                            <?php echo esc_html($latest['filename'] ?: sprintf(__('Version %s', 'wc-licensed-product'), $latest['version'])); ?>
                                        </a>
                                        <span class="download-version-badge"><?php esc_html_e('Latest', 'wc-licensed-product'); ?></span>
                                    </div>
                                    <div class="download-row-meta">
                                        <span class="download-date"><?php echo esc_html($latest['released_at']); ?></span>
                                        <?php if (!empty($latest['file_hash'])): ?>
                                            <span class="download-hash" title="<?php echo esc_attr($latest['file_hash']); ?>">
                                                <span class="dashicons dashicons-shield"></span>
                                                <code><?php echo esc_html(substr($latest['file_hash'], 0, 12)); ?>...</code>
                                            </span>
                                        <?php endif; ?>
                                    </div>
                                </li>
                            </ul>

                            <?php if (count($package['downloads']) > 1): ?>
                                <div class="older-versions-section">
                                    <button type="button" class="older-versions-toggle" aria-expanded="false">
                                        <span class="dashicons dashicons-arrow-down-alt2"></span>
                                        <?php
                                        printf(
                                            esc_html__('Older versions (%d)', 'wc-licensed-product'),
                                            count($package['downloads']) - 1
                                        );
                                        ?>
                                    </button>
                                    <ul class="download-list older-versions-list" style="display: none;">
                                        <?php foreach (array_slice($package['downloads'], 1) as $download): ?>
                                            <li class="download-item">
                                                <div class="download-row-file">
                                                    <a href="<?php echo esc_url($download['download_url']); ?>" class="download-link">
                                                        <span class="dashicons dashicons-download"></span>
                                                        <?php echo esc_html($download['filename'] ?: sprintf(__('Version %s', 'wc-licensed-product'), $download['version'])); ?>
                                                    </a>
                                                </div>
                                                <div class="download-row-meta">
                                                    <span class="download-date"><?php echo esc_html($download['released_at']); ?></span>
                                                    <?php if (!empty($download['file_hash'])): ?>
                                                        <span class="download-hash" title="<?php echo esc_attr($download['file_hash']); ?>">
                                                            <span class="dashicons dashicons-shield"></span>
                                                            <code><?php echo esc_html(substr($download['file_hash'], 0, 12)); ?>...</code>
                                                        </span>
                                                    <?php endif; ?>
                                                </div>
                                            </li>
                                        <?php endforeach; ?>
                                    </ul>
                                </div>
                            <?php endif; ?>
                        </div>
                    <?php endif; ?>
                </div>
            <?php endforeach; ?>
        </div>

        <!-- Transfer Modal -->
        <div id="wclp-transfer-modal" class="wclp-modal" style="display:none;">
            <div class="wclp-modal-overlay"></div>
            <div class="wclp-modal-content">
                <button type="button" class="wclp-modal-close" aria-label="<?php esc_attr_e('Close', 'wc-licensed-product'); ?>">&times;</button>
                <h3><?php esc_html_e('Transfer License to New Domain', 'wc-licensed-product'); ?></h3>
                <form id="wclp-transfer-form">
                    <input type="hidden" name="license_id" id="transfer-license-id" value="">

                    <div class="wclp-form-row">
                        <label><?php esc_html_e('Current Domain', 'wc-licensed-product'); ?></label>
                        <p class="wclp-current-domain"><code id="transfer-current-domain"></code></p>
                    </div>

                    <div class="wclp-form-row">
                        <label for="transfer-new-domain"><?php esc_html_e('New Domain', 'wc-licensed-product'); ?></label>
                        <input type="text" name="new_domain" id="transfer-new-domain"
                               placeholder="example.com" required
                               pattern="[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)+">
                        <p class="wclp-field-description"><?php esc_html_e('Enter the new domain without http:// or www.', 'wc-licensed-product'); ?></p>
                    </div>

                    <div class="wclp-form-row wclp-form-actions">
                        <button type="submit" class="button wclp-btn-primary" id="wclp-transfer-submit">
                            <?php esc_html_e('Transfer License', 'wc-licensed-product'); ?>
                        </button>
                        <button type="button" class="button wclp-modal-cancel"><?php esc_html_e('Cancel', 'wc-licensed-product'); ?></button>
                    </div>

                    <div id="wclp-transfer-message" class="wclp-message" style="display:none;"></div>
                </form>
            </div>
        </div>
        <?php
    }

    /**
     * Enqueue frontend styles and scripts
     */
    public function enqueueAssets(): void
    {
        if (!is_account_page()) {
            return;
        }

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

        wp_enqueue_script(
            'wc-licensed-product-frontend',
            WC_LICENSED_PRODUCT_PLUGIN_URL . 'assets/js/frontend.js',
            ['jquery'],
            WC_LICENSED_PRODUCT_VERSION,
            true
        );

        wp_localize_script('wc-licensed-product-frontend', 'wcLicensedProduct', [
            'ajaxUrl' => admin_url('admin-ajax.php'),
            'transferNonce' => wp_create_nonce('wclp_customer_transfer'),
            'strings' => [
                'copied' => __('Copied!', 'wc-licensed-product'),
                'copyFailed' => __('Copy failed', 'wc-licensed-product'),
                'transferSuccess' => __('License transferred successfully!', 'wc-licensed-product'),
                'transferError' => __('Transfer failed. Please try again.', 'wc-licensed-product'),
                'transferConfirm' => __('Are you sure you want to transfer this license to a new domain? This action cannot be undone.', 'wc-licensed-product'),
                'invalidDomain' => __('Please enter a valid domain.', 'wc-licensed-product'),
            ],
        ]);
    }

    /**
     * Handle AJAX license transfer request from customer
     */
    public function handleTransferRequest(): void
    {
        // Verify nonce
        if (!check_ajax_referer('wclp_customer_transfer', 'nonce', false)) {
            wp_send_json_error(['message' => __('Security check failed.', 'wc-licensed-product')], 403);
        }

        // Verify user is logged in
        $customerId = get_current_user_id();
        if (!$customerId) {
            wp_send_json_error(['message' => __('Please log in to transfer a license.', 'wc-licensed-product')], 401);
        }

        // Get and validate license ID
        $licenseId = isset($_POST['license_id']) ? absint($_POST['license_id']) : 0;
        if (!$licenseId) {
            wp_send_json_error(['message' => __('Invalid license.', 'wc-licensed-product')], 400);
        }

        // Get and validate new domain
        $newDomain = isset($_POST['new_domain']) ? sanitize_text_field($_POST['new_domain']) : '';
        $newDomain = $this->normalizeDomain($newDomain);

        if (empty($newDomain)) {
            wp_send_json_error(['message' => __('Please enter a valid domain.', 'wc-licensed-product')], 400);
        }

        // Verify the license belongs to this customer
        $license = $this->licenseManager->getLicenseById($licenseId);
        if (!$license) {
            wp_send_json_error(['message' => __('License not found.', 'wc-licensed-product')], 404);
        }

        if ($license->getCustomerId() !== $customerId) {
            wp_send_json_error(['message' => __('You do not have permission to transfer this license.', 'wc-licensed-product')], 403);
        }

        // Check if license is in a transferable state
        if ($license->getStatus() === 'revoked') {
            wp_send_json_error(['message' => __('Revoked licenses cannot be transferred.', 'wc-licensed-product')], 400);
        }

        if ($license->getStatus() === 'expired') {
            wp_send_json_error(['message' => __('Expired licenses cannot be transferred.', 'wc-licensed-product')], 400);
        }

        // Check if domain is the same
        if ($license->getDomain() === $newDomain) {
            wp_send_json_error(['message' => __('The new domain is the same as the current domain.', 'wc-licensed-product')], 400);
        }

        // Perform the transfer
        $result = $this->licenseManager->transferLicense($licenseId, $newDomain);

        if ($result) {
            wp_send_json_success([
                'message' => __('License transferred successfully!', 'wc-licensed-product'),
                'new_domain' => $newDomain,
            ]);
        } else {
            wp_send_json_error(['message' => __('Failed to transfer license. Please try again.', 'wc-licensed-product')], 500);
        }
    }

    /**
     * Normalize domain for comparison and storage
     */
    private function normalizeDomain(string $domain): string
    {
        // Remove protocol if present
        $domain = preg_replace('#^https?://#i', '', $domain);

        // Remove www prefix
        $domain = preg_replace('#^www\.#i', '', $domain);

        // Remove trailing slash
        $domain = rtrim($domain, '/');

        // Remove path if present
        $domain = explode('/', $domain)[0];

        // Convert to lowercase
        $domain = strtolower($domain);

        // Basic validation - must contain at least one dot and valid characters
        if (!preg_match('/^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)+$/', $domain)) {
            return '';
        }

        return $domain;
    }
}
