<?php

/**
 * My Account Hooks
 *
 * Registers WooCommerce My Account endpoints and hooks.
 *
 * @package ArraySubs\Features\CustomerPortal\Services
 * @since 1.0.0
 */

namespace ArraySubs\Features\CustomerPortal\Services;

defined('ABSPATH') || exit;

use ArraySubs\Supports\Config;

/**
 * My Account hooks integration
 */
class MyAccountHooks
{
    private const SUPPORT_MENU_ENDPOINT = 'support';
    private const SUPPORT_MENU_URL = 'https://support.arrayhash.com/';

    /**
     * Enable auto-loading via AbstractLoader
     *
     * @var bool
     */
    public static $loadable = true;

    /**
     * Initialize hooks
     */
    public function __construct()
    {
        // Register endpoints
        add_action('init', [$this, 'registerEndpoints']);
        add_action('parse_request', [$this, 'routePrettyEndpointFallback'], 0);

        // Register custom My Account endpoints with WooCommerce so helpers
        // such as is_wc_endpoint_url() can detect them reliably.
        add_filter('woocommerce_get_query_vars', [$this, 'registerWooCommerceQueryVars']);

        // Add menu items
        add_filter('woocommerce_account_menu_items', [$this, 'addMenuItems'], 10, 1);
        add_filter('woocommerce_get_endpoint_url', [$this, 'getEndpointUrl'], 10, 4);

        // Add badge class to menu item
        add_filter('woocommerce_account_menu_item_classes', [$this, 'addMenuBadgeClass'], 10, 2);

        // Template content
        add_action('woocommerce_account_subscriptions_endpoint', [$this, 'subscriptionsEndpointContent']);
        add_action('woocommerce_account_view-subscription_endpoint', [$this, 'viewSubscriptionEndpointContent']);

        // Enqueue assets
        add_action('wp_enqueue_scripts', [$this, 'enqueueAssets']);

        // Flush rewrite rules on activation (run once)
        if (get_option('arraysubs_flush_rewrite_rules') !== 'done') {
            add_action('init', function () {
                flush_rewrite_rules();
                update_option('arraysubs_flush_rewrite_rules', 'done');
            }, 99);
        }
    }

    /**
     * Register WooCommerce endpoints
     *
     * @return void
     */
    public function registerEndpoints(): void
    {
        add_rewrite_endpoint('subscriptions', EP_ROOT | EP_PAGES);
        add_rewrite_endpoint('view-subscription', EP_ROOT | EP_PAGES);
    }

    /**
     * Register ArraySubs account endpoints with WooCommerce query vars.
     *
     * WooCommerce helpers such as is_wc_endpoint_url() only detect endpoints
     * that are present in WC()->query->get_query_vars(). The customer portal
     * renders from WordPress rewrite endpoints, so keep both registries aligned.
     *
     * @param array $query_vars WooCommerce endpoint query vars.
     * @return array Modified endpoint query vars.
     */
    public function registerWooCommerceQueryVars(array $query_vars): array
    {
        $query_vars['subscriptions'] = 'subscriptions';
        $query_vars['view-subscription'] = 'view-subscription';

        return $query_vars;
    }

    /**
     * Route pretty My Account endpoint URLs when the site has no rewrite rules.
     *
     * The QA environment can run with plain permalinks, where
     * /my-account/subscriptions/ reaches WordPress but does not populate the
     * WooCommerce endpoint query vars. Map only the ArraySubs account endpoints
     * back to the configured My Account page.
     *
     * @param \WP $wp WordPress request object.
     * @return void
     */
    public function routePrettyEndpointFallback(\WP $wp): void
    {
        if (is_admin()) {
            return;
        }

        if (array_key_exists('subscriptions', $wp->query_vars) || array_key_exists('view-subscription', $wp->query_vars)) {
            return;
        }

        $account_page_id = function_exists('wc_get_page_id') ? (int) wc_get_page_id('myaccount') : 0;
        if ($account_page_id <= 0) {
            return;
        }

        $account_path = trim((string) get_page_uri($account_page_id), '/');
        if ('' === $account_path) {
            return;
        }

        $request_path = $this->getRequestPath();
        if ('' === $request_path || !str_starts_with($request_path, $account_path . '/')) {
            return;
        }

        $endpoint_path = trim(substr($request_path, strlen($account_path)), '/');
        if ('' === $endpoint_path) {
            return;
        }

        $parts = array_values(array_filter(explode('/', $endpoint_path), 'strlen'));
        $endpoint = $parts[0] ?? '';

        if (!in_array($endpoint, ['subscriptions', 'view-subscription'], true)) {
            return;
        }

        $endpoint_value = isset($parts[1]) ? sanitize_text_field($parts[1]) : '';

        $wp->query_vars['page_id'] = $account_page_id;
        $wp->query_vars['pagename'] = $account_path;
        $wp->query_vars[$endpoint] = $endpoint_value;

        unset($wp->query_vars['name'], $wp->query_vars['error']);
    }

    /**
     * Get the current request path relative to the WordPress home path.
     *
     * @return string
     */
    private function getRequestPath(): string
    {
        $request_uri = isset($_SERVER['REQUEST_URI']) ? (string) wp_unslash($_SERVER['REQUEST_URI']) : '';
        $path = trim((string) parse_url($request_uri, PHP_URL_PATH), '/');
        $home_path = trim((string) parse_url(home_url('/'), PHP_URL_PATH), '/');

        if ('' !== $home_path && str_starts_with($path, $home_path . '/')) {
            $path = trim(substr($path, strlen($home_path)), '/');
        }

        return $path;
    }

    /**
     * Add menu items to My Account
     *
     * @param array $items Menu items
     * @return array Modified menu items
     */
    public function addMenuItems(array $items): array
    {
        // Provide the default Subscriptions item.
        // Label and ordering customization are handled by the My Account Editor.
        $new_items = [];
        $support_added = false;

        foreach ($items as $key => $label) {
            if ($key === 'customer-logout' && !isset($items[self::SUPPORT_MENU_ENDPOINT])) {
                $new_items[self::SUPPORT_MENU_ENDPOINT] = __('Support', 'arraysubs');
                $support_added = true;
            }

            $new_items[$key] = $label;
            $support_added = $support_added || $key === self::SUPPORT_MENU_ENDPOINT;

            if ($key === 'orders') {
                $new_items['subscriptions'] = __('Subscriptions', 'arraysubs');
            }
        }

        if (!$support_added) {
            $new_items[self::SUPPORT_MENU_ENDPOINT] = __('Support', 'arraysubs');
        }

        return $new_items;
    }

    /**
     * Point the Support account menu item to ArrayHash support.
     *
     * @param mixed $url       Generated endpoint URL.
     * @param mixed $endpoint  Endpoint slug.
     * @param mixed $value     Endpoint value.
     * @param mixed $permalink My Account permalink.
     * @return string Modified endpoint URL.
     */
    public function getEndpointUrl($url, $endpoint, $value, $permalink): string
    {
        if (self::SUPPORT_MENU_ENDPOINT === (string) $endpoint) {
            return self::SUPPORT_MENU_URL;
        }

        return (string) $url;
    }

    /**
     * Add data attribute to subscriptions menu item for badge
     *
     * @param array  $classes Menu item classes
     * @param string $endpoint Endpoint slug
     * @return array Modified classes
     */
    public function addMenuBadgeClass(array $classes, string $endpoint): array
    {
        if ($endpoint === 'subscriptions') {
            $classes[] = 'arraysubs-menu-item';
        }
        return $classes;
    }

    /**
     * Get statuses shown in the customer portal subscriptions list.
     *
     * @return string[]
     */
    private function getCustomerPortalSubscriptionStatuses(): array
    {
        return [
            'arraysubs-pending',
            'arraysubs-active',
            'arraysubs-on-hold',
            'arraysubs-cancelled',
            'arraysubs-expired',
            'arraysubs-trial',
        ];
    }

    /**
     * Subscriptions list endpoint content
     *
     * @return void
     */
    public function subscriptionsEndpointContent(): void
    {
        $arraysubs_customer_id = get_current_user_id();
        $arraysubs_per_page = 10;
        $arraysubs_current_page = max(1, absint(get_query_var('paged', 1)));
        $arraysubs_endpoint_value = get_query_var('subscriptions', '');

        if ($arraysubs_current_page === 1 && $arraysubs_endpoint_value !== '') {
            if (is_numeric($arraysubs_endpoint_value)) {
                $arraysubs_current_page = max(1, absint($arraysubs_endpoint_value));
            } elseif (preg_match('#(?:^|/)page/([0-9]+)(?:/|$)#', (string) $arraysubs_endpoint_value, $arraysubs_matches)) {
                $arraysubs_current_page = max(1, absint($arraysubs_matches[1]));
            }
        }

        // Query user's subscriptions - include ALL statuses with pagination
        $arraysubs_args = [
            'post_type' => 'arraysubs_data',
            'post_status' => $this->getCustomerPortalSubscriptionStatuses(),
            'posts_per_page' => $arraysubs_per_page,
            'paged' => $arraysubs_current_page,
            'meta_query' => [
                [
                    'key' => '_customer_id',
                    'value' => $arraysubs_customer_id,
                    'compare' => '=',
                    'type' => 'NUMERIC',
                ],
            ],
            'orderby' => 'date',
            'order' => 'DESC',
        ];

        $arraysubs_query = new \WP_Query($arraysubs_args);
        $arraysubs_subscriptions = $arraysubs_query->posts;
        $arraysubs_total_subscriptions = $arraysubs_query->found_posts;
        $arraysubs_total_pages = $arraysubs_query->max_num_pages;

        include dirname(__DIR__) . '/views/my-account-subscriptions.php';
    }

    /**
     * View single subscription endpoint content
     *
     * @param mixed $subscription_id Subscription ID from URL
     * @return void
     */
    public function viewSubscriptionEndpointContent($subscription_id): void
    {
        $arraysubs_customer_id = get_current_user_id();

        // WooCommerce endpoint values may include malformed trailing segments (e.g. "178/undefined...").
        // Parse defensively and keep only the first numeric segment.
        $arraysubs_subscription_id_raw = is_scalar($subscription_id)
            ? sanitize_text_field(wp_unslash((string) $subscription_id))
            : '';
        $arraysubs_subscription_id_segment = strtok($arraysubs_subscription_id_raw, '/');
        $arraysubs_subscription_id = absint($arraysubs_subscription_id_segment ?: 0);

        if ($arraysubs_subscription_id <= 0) {
            wc_print_notice(__('Invalid subscription ID.', 'arraysubs'), 'error');
            return;
        }

        $arraysubs_subscription_post = arraysubs_get_subscription($arraysubs_subscription_id);

        // Verify ownership
        $arraysubs_subscription_customer_id = (int) get_post_meta($arraysubs_subscription_id, '_customer_id', true);
        if (!$arraysubs_subscription_post || $arraysubs_subscription_customer_id !== $arraysubs_customer_id) {
            wc_print_notice(__('Subscription not found or you do not have permission to view it.', 'arraysubs'), 'error');
            return;
        }

        // Build subscription data array for the view
        $arraysubs_active_retention_discount = function_exists('arraysubs_get_subscription_active_retention_discount')
            ? arraysubs_get_subscription_active_retention_discount($arraysubs_subscription_id)
            : null;
        $arraysubs_base_recurring_amount = (float) ($arraysubs_active_retention_discount['base_amount'] ?? get_post_meta($arraysubs_subscription_id, '_recurring_amount', true));
        $arraysubs_effective_recurring_amount = function_exists('arraysubs_get_subscription_effective_recurring_amount')
            ? arraysubs_get_subscription_effective_recurring_amount($arraysubs_subscription_id)
            : $arraysubs_base_recurring_amount;

        $arraysubs_is_waiting_cancellation = function_exists('arraysubs_is_waiting_cancellation')
            && arraysubs_is_waiting_cancellation($arraysubs_subscription_id);
        $arraysubs_scheduled_cancel_date = function_exists('arraysubs_get_scheduled_cancel_date')
            ? arraysubs_get_scheduled_cancel_date($arraysubs_subscription_id)
            : null;
        $arraysubs_can_undo_cancellation = function_exists('arraysubs_can_undo_cancellation')
            && arraysubs_can_undo_cancellation($arraysubs_subscription_id);

        $arraysubs_subscription_data = [
            'id' => $arraysubs_subscription_id,
            'product_id' => get_post_meta($arraysubs_subscription_id, '_product_id', true),
            'variation_id' => get_post_meta($arraysubs_subscription_id, '_variation_id', true),
            'customer_id' => $arraysubs_subscription_customer_id,
            'customer_email' => get_post_meta($arraysubs_subscription_id, '_customer_email', true),
            'start_date' => get_post_meta($arraysubs_subscription_id, '_start_date', true),
            'end_date' => get_post_meta($arraysubs_subscription_id, '_end_date', true),
            'next_payment_date' => get_post_meta($arraysubs_subscription_id, '_next_payment_date', true),
            'trial_end_date' => get_post_meta($arraysubs_subscription_id, '_trial_end_date', true),
            'billing_period' => get_post_meta($arraysubs_subscription_id, '_billing_period', true),
            'billing_interval' => get_post_meta($arraysubs_subscription_id, '_billing_interval', true),
            'recurring_amount' => $arraysubs_effective_recurring_amount,
            'base_recurring_amount' => $arraysubs_base_recurring_amount,
            'effective_recurring_amount' => $arraysubs_effective_recurring_amount,
            'active_retention_discount' => $arraysubs_active_retention_discount,
            'subscription_price' => get_post_meta($arraysubs_subscription_id, '_subscription_price', true),
            'signup_fee' => get_post_meta($arraysubs_subscription_id, '_signup_fee', true),
            'currency' => get_post_meta($arraysubs_subscription_id, '_currency', true),
            'payment_method' => get_post_meta($arraysubs_subscription_id, '_payment_method', true),
            'payment_method_title' => get_post_meta($arraysubs_subscription_id, '_payment_method_title', true),
            'is_waiting_cancellation' => $arraysubs_is_waiting_cancellation,
            'scheduled_cancel_date' => $arraysubs_scheduled_cancel_date,
            'can_undo_cancellation' => $arraysubs_can_undo_cancellation,
        ];

        $arraysubs_script_data = [
            'subscriptionId' => $arraysubs_subscription_id,
            'currency' => $arraysubs_subscription_data['currency'] ?: get_woocommerce_currency(),
            'nonce' => wp_create_nonce('wp_rest'),
            'restUrl' => rest_url('arraysubs/v1/'),
            'retentionEnabled' => function_exists('arraysubs_is_retention_offers_enabled')
                && arraysubs_is_retention_offers_enabled()
                && function_exists('arraysubs_can_customer_cancel_by_subs_id')
                && arraysubs_can_customer_cancel_by_subs_id($arraysubs_subscription_id),
            'retentionOffersSupported' => function_exists('arraysubs_subscription_supports_retention_offers')
                ? arraysubs_subscription_supports_retention_offers($arraysubs_subscription_id)
                : true,
            'requireReason' => function_exists('arraysubs_require_cancel_reason')
                ? arraysubs_require_cancel_reason()
                : false,
            'allowedSwitchTypes' => [
                'upgrade' => function_exists('arraysubs_get_setting')
                    ? (bool) arraysubs_get_setting('plan_switching.allow_upgrades', true)
                    : true,
                'downgrade' => function_exists('arraysubs_get_setting')
                    ? (bool) arraysubs_get_setting('plan_switching.allow_downgrades', true)
                    : true,
                'crossgrade' => function_exists('arraysubs_get_setting')
                    ? (bool) arraysubs_get_setting('plan_switching.allow_crossgrades', true)
                    : true,
            ],
            'defaultProrationType' => function_exists('arraysubs_get_setting')
                ? (string) arraysubs_get_setting('plan_switching.proration_type', 'prorate_immediately')
                : 'prorate_immediately',
            'i18n' => [
                'confirmSwitch' => __('Are you sure you want to change your plan?', 'arraysubs'),
                'switchSuccess' => __('Your plan has been changed successfully!', 'arraysubs'),
                'switchError' => __('Failed to change plan. Please try again.', 'arraysubs'),
                'offerAccepted' => __('Offer accepted! Your subscription has been updated.', 'arraysubs'),
                'offerError' => __('Failed to apply offer. Please try again.', 'arraysubs'),
                'loading' => __('Loading...', 'arraysubs'),
                'continueCancelFlow' => __('Continue', 'arraysubs'),
                'finalCancelConfirm' => __('This will cancel your subscription. Are you absolutely sure you want to continue?', 'arraysubs'),
                'retentionModalTitle' => __('Before You Go...', 'arraysubs'),
                'retentionModalIntro' => __('We\'d hate to see you leave! Here are some options that might help:', 'arraysubs'),
                'unsupportedRetentionTitle' => __('Please confirm your cancellation', 'arraysubs'),
                'unsupportedRetentionIntro' => __('No retention options are available for this subscription. You can keep your subscription or continue to cancel.', 'arraysubs'),
                'upgrade' => __('Upgrade', 'arraysubs'),
                'downgrade' => __('Downgrade', 'arraysubs'),
                'crossgrade' => __('Switch', 'arraysubs'),
                'reasonRequired' => __('Please select a reason for cancelling.', 'arraysubs'),
                'reactivateConfirm' => __('Reactivate this subscription? You will be billed again on the next renewal date.', 'arraysubs'),
                'reactivateSuccess' => __('Subscription reactivated successfully!', 'arraysubs'),
                'reactivateError' => __('Failed to reactivate subscription. Please try again.', 'arraysubs'),
                'undoCancelConfirm' => __('Remove the scheduled cancellation? Your subscription will continue renewing normally.', 'arraysubs'),
                'undoCancelSuccess' => __('Scheduled cancellation removed. Your subscription will continue renewing.', 'arraysubs'),
                'undoCancelError' => __('Failed to remove scheduled cancellation. Please try again.', 'arraysubs'),
                'acceptOffer' => __('Accept Offer', 'arraysubs'),
                'contactSupport' => __('Contact Support', 'arraysubs'),
                'noOffersAvailable' => __('No special offers available at this time.', 'arraysubs'),
                'noOffersConfirmMessage' => __('Are you sure you want to cancel your subscription?', 'arraysubs'),
                'keepSubscription' => __('Keep Subscription', 'arraysubs'),
                'continueToCancel' => __('No thanks, continue to cancel', 'arraysubs'),
                'confirmCancel' => __('Yes, Cancel Subscription', 'arraysubs'),
                'viewDetails' => __('View Details', 'arraysubs'),
            ],
        ];

        $arraysubs_json_flags = JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT;

        wp_add_inline_script(
            'arraysubs-customer-portal',
            'window.arraySubsSubscription = ' . wp_json_encode($arraysubs_script_data, $arraysubs_json_flags) . ';',
            'before'
        );

        include dirname(__DIR__) . '/views/view-subscription.php';
    }

    /**
     * Enqueue assets for My Account pages
     *
     * @return void
     */
    public function enqueueAssets(): void
    {
        if (!function_exists('is_account_page') || !is_account_page()) {
            return;
        }

        // Load dependencies from webpack asset file
        $asset_file = Config::get('plugin.public_path') . 'build/customer-portal.asset.php';
        $asset = file_exists($asset_file)
            ? require $asset_file
            : ['dependencies' => ['jquery'], 'version' => ARRAYSUBS_VERSION];

        wp_enqueue_style(
            'arraysubs-customer-portal',
            Config::get('plugin.public_url') . 'build/customer-portal.css',
            [],
            $asset['version']
        );

        // Ensure jQuery and wp-util are always included as dependencies
        $dependencies = array_unique(array_merge($asset['dependencies'], ['jquery', 'wp-util']));

        wp_enqueue_script(
            'arraysubs-customer-portal',
            Config::get('plugin.public_url') . 'build/customer-portal.js',
            $dependencies,
            $asset['version'],
            true
        );

        // Check if cancellation is immediate or end-of-period
        $cancel_immediately = function_exists('arraysubs_cancel_immediately')
            ? arraysubs_cancel_immediately()
            : true;

        $subscription_count = 0;
        if (is_user_logged_in() && function_exists('arraysubs_get_customer_subscription_count')) {
            $subscription_count = arraysubs_get_customer_subscription_count(
                get_current_user_id(),
                $this->getCustomerPortalSubscriptionStatuses()
            );
        }

        // Localize script with API data
        wp_localize_script('arraysubs-customer-portal', 'arraySubsPortal', [
            'apiBaseUrl' => rest_url('arraysubs/v1/'),
            'nonce' => wp_create_nonce('wp_rest'),
            'subscriptionCount' => $subscription_count,
            'cancelImmediately' => $cancel_immediately,
            'i18n' => [
                'cancel_title' => __('Cancel Subscription', 'arraysubs'),
                'cancel_message' => $cancel_immediately
                    ? __('Are you sure you want to cancel this subscription? Your subscription will be cancelled immediately and you will lose access to your subscription benefits.', 'arraysubs')
                    : __('Are you sure you want to cancel this subscription? Your subscription will remain active until the end of your current billing period, after which you will lose access to your subscription benefits.', 'arraysubs'),
                'cancel_reason_label' => __('Please tell us why you\'re cancelling (optional):', 'arraysubs'),
                'cancel_reason_placeholder' => __('Select a reason...', 'arraysubs'),
                'cancel_reason_too_expensive' => __('Too expensive', 'arraysubs'),
                'cancel_reason_not_using' => __('Not using anymore', 'arraysubs'),
                'cancel_reason_found_alternative' => __('Found an alternative', 'arraysubs'),
                'cancel_reason_missing_features' => __('Missing features', 'arraysubs'),
                'cancel_reason_technical_issues' => __('Technical issues', 'arraysubs'),
                'cancel_reason_other' => __('Other', 'arraysubs'),
                'cancel_other_placeholder' => __('Please provide more details...', 'arraysubs'),
                'keep_subscription' => __('Keep Subscription', 'arraysubs'),
                'continue_action' => __('Continue', 'arraysubs'),
                'yes_cancel' => __('Yes, Cancel Subscription', 'arraysubs'),
                'cancelling' => __('Cancelling...', 'arraysubs'),
                'final_cancel_confirm' => __('This will cancel your subscription. Are you absolutely sure you want to continue?', 'arraysubs'),
                'cancelled_success' => $cancel_immediately
                    ? __('Subscription cancelled successfully.', 'arraysubs')
                    : __('Subscription scheduled for cancellation at the end of your current billing period.', 'arraysubs'),
                'cancelled_error' => __('Failed to cancel subscription. Please try again.', 'arraysubs'),
                'processing' => __('Processing...', 'arraysubs'),
            ],
        ]);
    }
}
