<?php
/**
 * Checkout Controller
 *
 * @package Jeremias\WcLicensedProduct\Checkout
 */

declare(strict_types=1);

namespace Jeremias\WcLicensedProduct\Checkout;

use Jeremias\WcLicensedProduct\License\LicenseManager;

/**
 * Handles checkout modifications for licensed products
 */
final class CheckoutController
{
    private LicenseManager $licenseManager;

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

    /**
     * Register WordPress hooks
     */
    private function registerHooks(): void
    {
        // Add domain field to checkout
        add_action('woocommerce_after_order_notes', [$this, 'addDomainField']);

        // Validate domain field
        add_action('woocommerce_checkout_process', [$this, 'validateDomainField']);

        // Save domain field to order meta
        add_action('woocommerce_checkout_update_order_meta', [$this, 'saveDomainField']);

        // Display domain in order details (admin)
        add_action('woocommerce_admin_order_data_after_billing_address', [$this, 'displayDomainInAdmin']);

        // Display domain in order email
        add_action('woocommerce_email_after_order_table', [$this, 'displayDomainInEmail'], 10, 3);
    }

    /**
     * Check if cart contains licensed products
     */
    private function cartHasLicensedProducts(): bool
    {
        if (!WC()->cart) {
            return false;
        }

        foreach (WC()->cart->get_cart() as $cartItem) {
            $product = $cartItem['data'];
            if ($product && $product->is_type('licensed')) {
                return true;
            }
        }

        return false;
    }

    /**
     * Add domain field to checkout form
     */
    public function addDomainField(): void
    {
        if (!$this->cartHasLicensedProducts()) {
            return;
        }

        ?>
        <div id="licensed-product-domain-field">
            <h3><?php esc_html_e('License Domain', 'wc-licensed-product'); ?></h3>
            <p class="form-row form-row-wide">
                <label for="licensed_product_domain">
                    <?php esc_html_e('Domain for License Activation', 'wc-licensed-product'); ?>
                    <abbr class="required" title="<?php esc_attr_e('required', 'wc-licensed-product'); ?>">*</abbr>
                </label>
                <input
                    type="text"
                    class="input-text"
                    name="licensed_product_domain"
                    id="licensed_product_domain"
                    placeholder="<?php esc_attr_e('example.com', 'wc-licensed-product'); ?>"
                    value="<?php echo esc_attr(WC()->checkout->get_value('licensed_product_domain')); ?>"
                />
                <span class="description">
                    <?php esc_html_e('Enter the domain where you will use this license (without http:// or www).', 'wc-licensed-product'); ?>
                </span>
            </p>
        </div>
        <?php
    }

    /**
     * Validate domain field during checkout
     */
    public function validateDomainField(): void
    {
        if (!$this->cartHasLicensedProducts()) {
            return;
        }

        $domain = isset($_POST['licensed_product_domain'])
            ? sanitize_text_field($_POST['licensed_product_domain'])
            : '';

        if (empty($domain)) {
            wc_add_notice(
                __('Please enter a domain for your license activation.', 'wc-licensed-product'),
                'error'
            );
            return;
        }

        // Validate domain format
        $normalizedDomain = $this->licenseManager->normalizeDomain($domain);
        if (!$this->isValidDomain($normalizedDomain)) {
            wc_add_notice(
                __('Please enter a valid domain name.', 'wc-licensed-product'),
                'error'
            );
        }
    }

    /**
     * Save domain field to order meta
     */
    public function saveDomainField(int $orderId): void
    {
        if (!$this->cartHasLicensedProducts()) {
            return;
        }

        if (isset($_POST['licensed_product_domain']) && !empty($_POST['licensed_product_domain'])) {
            $domain = sanitize_text_field($_POST['licensed_product_domain']);
            $normalizedDomain = $this->licenseManager->normalizeDomain($domain);

            $order = wc_get_order($orderId);
            if ($order) {
                $order->update_meta_data('_licensed_product_domain', $normalizedDomain);
                $order->save();
            }
        }
    }

    /**
     * Display domain in admin order view
     */
    public function displayDomainInAdmin(\WC_Order $order): void
    {
        $domain = $order->get_meta('_licensed_product_domain');
        if (!$domain) {
            return;
        }

        ?>
        <p>
            <strong><?php esc_html_e('License Domain:', 'wc-licensed-product'); ?></strong>
            <?php echo esc_html($domain); ?>
        </p>
        <?php
    }

    /**
     * Display domain in order emails
     */
    public function displayDomainInEmail(\WC_Order $order, bool $sentToAdmin, bool $plainText): void
    {
        $domain = $order->get_meta('_licensed_product_domain');
        if (!$domain) {
            return;
        }

        if ($plainText) {
            echo "\n" . esc_html__('License Domain:', 'wc-licensed-product') . ' ' . esc_html($domain) . "\n";
        } else {
            ?>
            <p>
                <strong><?php esc_html_e('License Domain:', 'wc-licensed-product'); ?></strong>
                <?php echo esc_html($domain); ?>
            </p>
            <?php
        }
    }

    /**
     * Validate domain format
     */
    private function isValidDomain(string $domain): bool
    {
        // Basic domain validation
        if (strlen($domain) > 255) {
            return false;
        }

        // Check for valid domain pattern
        $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);
    }
}
