<?php
/**
 * Customer portal class
 * Provides self-service subscription management for customers
 */

// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

class STRP_SUB_Customer_Portal {
    
    /**
     * Single instance
     */
    private static $instance = null;
    
    /**
     * Get instance
     */
    public static function get_instance() {
        if ( null === self::$instance ) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    /**
     * Constructor
     */
    private function __construct() {
        // Add subscriptions tab to My Account
        add_filter( 'woocommerce_account_menu_items', array( $this, 'add_subscriptions_menu_item' ) );
        add_action( 'init', array( $this, 'add_subscriptions_endpoint' ) );
        add_action( 'woocommerce_account_subscriptions_endpoint', array( $this, 'render_subscriptions_page' ) );

        // AJAX handler for frontend subscription cancellation.
        add_action( 'wp_ajax_strp_sub_cancel_subscription', array( $this, 'ajax_cancel_subscription' ) );

        // Prefer Stripe-hosted customer portal for self-service billing
        add_action( 'admin_post_strp_sub_open_billing_portal', array( $this, 'open_billing_portal' ) );
    }

    private function __clone() {}

    public function __wakeup() {
        throw new \RuntimeException( 'Cannot unserialize singleton.' );
    }

    /**
     * Add subscriptions menu item to My Account
     */
    public function add_subscriptions_menu_item( $items ) {
        // Insert subscriptions after orders
        $new_items = array();
        foreach ( $items as $key => $value ) {
            $new_items[ $key ] = $value;
            if ( $key === 'orders' ) {
                $new_items['subscriptions'] = __( 'Subscriptions', 'subscription-manager-for-stripe' );
            }
        }
        return $new_items;
    }
    
    /**
     * Add subscriptions endpoint
     */
    public function add_subscriptions_endpoint() {
        add_rewrite_endpoint( 'subscriptions', EP_ROOT | EP_PAGES );
    }
    
    /**
     * Render subscriptions page
     */
    public function render_subscriptions_page() {
        $user_id = get_current_user_id();
        
        if ( $user_id <= 0 ) {
            echo '<p>' . esc_html__( 'You must be logged in to view your subscriptions.', 'subscription-manager-for-stripe' ) . '</p>';
            return;
        }
        
        // Check for lifetime access
        $has_lifetime = STRP_SUB_Subscription_Manager::has_lifetime_access( $user_id );
        
        if ( $has_lifetime ) {
            $this->render_lifetime_access_notice();
        }
        
        // Get user's subscriptions
        $stripe_customer_id = get_user_meta( $user_id, '_strp_sub_stripe_customer_id', true );
        
        if ( empty( $stripe_customer_id ) ) {
            echo '<p>' . esc_html__( 'You have no subscriptions yet.', 'subscription-manager-for-stripe' ) . '</p>';
            return;
        }

        $this->render_billing_portal_button();

        $stripe_api = STRP_SUB_Stripe_API::get_instance();
        // Stripe API defaults to 10 items. Pagination UI should be added for customers with many subscriptions.
        $subscriptions = $stripe_api->list_customer_subscriptions( $stripe_customer_id );
        
        if ( empty( $subscriptions ) ) {
            echo '<p>' . esc_html__( 'You have no subscriptions yet.', 'subscription-manager-for-stripe' ) . '</p>';
            return;
        }
        
        $this->render_subscriptions_table( $subscriptions );
    }
    
    /**
     * Render lifetime access notice
     */
    private function render_lifetime_access_notice() {
        ?>
        <div class="woocommerce-message strp-sub-lifetime-notice">
            <strong><?php esc_html_e( 'You have Lifetime Access!', 'subscription-manager-for-stripe' ); ?></strong>
            <p><?php esc_html_e( 'You have lifetime access to our dashboard. No further payments are required.', 'subscription-manager-for-stripe' ); ?></p>
        </div>
        <?php
    }
    
    /**
     * Render subscriptions table
     */
    private function render_subscriptions_table( $subscriptions ) {
        ?>
        <h2><?php esc_html_e( 'My Subscriptions', 'subscription-manager-for-stripe' ); ?></h2>
        <table class="woocommerce-orders-table woocommerce-MyAccount-orders shop_table shop_table_responsive my_account_orders account-orders-table">
            <thead>
                <tr>
                    <th><?php esc_html_e( 'Subscription', 'subscription-manager-for-stripe' ); ?></th>
                    <th><?php esc_html_e( 'Status', 'subscription-manager-for-stripe' ); ?></th>
                    <th><?php esc_html_e( 'Next Payment', 'subscription-manager-for-stripe' ); ?></th>
                    <th><?php esc_html_e( 'Amount', 'subscription-manager-for-stripe' ); ?></th>
                    <th><?php esc_html_e( 'Self-service', 'subscription-manager-for-stripe' ); ?></th>
                    <?php if ( class_exists( 'STRP_SUB_Cancellation_Flow' ) && STRP_SUB_Cancellation_Flow::get_instance()->is_enabled() ) : ?>
                        <th><?php esc_html_e( 'Cancel', 'subscription-manager-for-stripe' ); ?></th>
                    <?php endif; ?>
                </tr>
            </thead>
            <tbody>
                <?php foreach ( $subscriptions as $subscription ) : ?>
                    <tr>
                        <td data-title="<?php esc_attr_e( 'Subscription', 'subscription-manager-for-stripe' ); ?>">
                            <?php echo esc_html( $subscription->id ); ?>
                        </td>
                        <td data-title="<?php esc_attr_e( 'Status', 'subscription-manager-for-stripe' ); ?>">
                            <?php echo esc_html( $this->get_status_label( $subscription->status ) ); ?>
                        </td>
                        <td data-title="<?php esc_attr_e( 'Next Payment', 'subscription-manager-for-stripe' ); ?>">
                            <?php
                            if ( in_array( $subscription->status, array( 'active', 'trialing' ) ) && ! $subscription->cancel_at_period_end ) {
                                echo esc_html( date_i18n( get_option( 'date_format' ), $subscription->current_period_end ) );
                            } elseif ( $subscription->cancel_at_period_end ) {
                                echo esc_html__( 'Cancels on ', 'subscription-manager-for-stripe' ) . esc_html( date_i18n( get_option( 'date_format' ), $subscription->current_period_end ) );
                            } else {
                                echo 'â€”';
                            }
                            ?>
                        </td>
                        <td data-title="<?php esc_attr_e( 'Amount', 'subscription-manager-for-stripe' ); ?>">
                            <?php
                            // FIX: Check if plan exists before accessing its properties
                            if ( isset( $subscription->plan ) && isset( $subscription->plan->amount ) && isset( $subscription->plan->currency ) ) {
                                $zero_decimal_currencies = array( 'bif', 'clp', 'djf', 'gnf', 'jpy', 'kmf', 'krw', 'mga', 'pyg', 'rwf', 'ugx', 'vnd', 'vuv', 'xaf', 'xof', 'xpf' );
                                $currency_lower = strtolower( $subscription->plan->currency ?? 'usd' );
                                $amount = in_array( $currency_lower, $zero_decimal_currencies, true )
                                    ? $subscription->plan->amount
                                    : $subscription->plan->amount / 100;
                                $currency = strtoupper( $subscription->plan->currency );
                                echo esc_html( $currency . ' ' . number_format( $amount, 2 ) );

                                if ( isset( $subscription->plan->interval ) ) {
                                    echo ' / ' . esc_html( $this->get_interval_label( $subscription->plan->interval ) );
                                }
                            } else {
                                echo 'â€”';
                            }
                            ?>
                        </td>
                        <td data-title="<?php esc_attr_e( 'Self-service', 'subscription-manager-for-stripe' ); ?>">
                            <?php esc_html_e( 'Manage in Stripe Customer Portal', 'subscription-manager-for-stripe' ); ?>
                        </td>
                        <?php if ( class_exists( 'STRP_SUB_Cancellation_Flow' ) && STRP_SUB_Cancellation_Flow::get_instance()->is_enabled() && in_array( $subscription->status, array( 'active', 'trialing' ), true ) ) : ?>
                            <td data-title="<?php esc_attr_e( 'Cancel', 'subscription-manager-for-stripe' ); ?>">
                                <a href="#" class="strp-sub-cancel-retention" data-subscription-id="<?php echo esc_attr( $subscription->id ); ?>">
                                    <?php esc_html_e( 'Cancel Subscription', 'subscription-manager-for-stripe' ); ?>
                                </a>
                            </td>
                        <?php elseif ( class_exists( 'STRP_SUB_Cancellation_Flow' ) && STRP_SUB_Cancellation_Flow::get_instance()->is_enabled() ) : ?>
                            <td data-title="<?php esc_attr_e( 'Cancel', 'subscription-manager-for-stripe' ); ?>">
                                &mdash;
                            </td>
                        <?php endif; ?>
                    </tr>
                <?php endforeach; ?>
            </tbody>
        </table>
        <?php
    }
    

    /**
     * Render button that redirects customer to Stripe-hosted billing portal.
     */
    private function render_billing_portal_button() {
        $portal_url = wp_nonce_url(
            admin_url( 'admin-post.php?action=strp_sub_open_billing_portal' ),
            'strp_sub_open_billing_portal'
        );
        ?>
        <div class="woocommerce-info" style="margin-bottom:20px;">
            <p style="margin:0 0 10px 0;"><?php esc_html_e( 'Manage your payment method, invoices, and subscription securely via the Stripe Customer Portal.', 'subscription-manager-for-stripe' ); ?></p>
            <a class="button" href="<?php echo esc_url( $portal_url ); ?>"><?php esc_html_e( 'Open Stripe Customer Portal', 'subscription-manager-for-stripe' ); ?></a>
        </div>
        <?php
    }

    /**
     * Redirect logged-in customers to a short-lived Stripe Billing Portal session.
     */
    public function open_billing_portal() {
        if ( ! is_user_logged_in() ) {
            wp_safe_redirect( wc_get_page_permalink( 'myaccount' ) );
            exit;
        }

        check_admin_referer( 'strp_sub_open_billing_portal' );

        $user_id = get_current_user_id();
        $stripe_customer_id = get_user_meta( $user_id, '_strp_sub_stripe_customer_id', true );

        if ( empty( $stripe_customer_id ) ) {
            wc_add_notice( __( 'No Stripe customer found for your account.', 'subscription-manager-for-stripe' ), 'error' );
            wp_safe_redirect( wc_get_account_endpoint_url( 'subscriptions' ) );
            exit;
        }

        $stripe_api = STRP_SUB_Stripe_API::get_instance();
        $session = $stripe_api->create_billing_portal_session(
            $stripe_customer_id,
            wc_get_account_endpoint_url( 'subscriptions' )
        );

        if ( ! $session || empty( $session->url ) ) {
            STRP_SUB_Logger::error( 'Failed to create billing portal session for user #' . $user_id );
            wc_add_notice( __( 'Could not open Stripe Customer Portal. Please try again.', 'subscription-manager-for-stripe' ), 'error' );
            wp_safe_redirect( wc_get_account_endpoint_url( 'subscriptions' ) );
            exit;
        }

        if ( ! preg_match( '#^https://(billing|checkout)\.stripe\.com(/|$)#', $session->url ) ) {
            STRP_SUB_Logger::error( 'Unexpected billing portal URL: ' . sanitize_url( $session->url ) );
            wp_die( esc_html__( 'Unexpected redirect URL from Stripe.', 'subscription-manager-for-stripe' ) );
        }
        wp_redirect( $session->url );
        exit;
    }

    /**
     * Get human-readable status label.
     */
    private function get_status_label( $status ) {
        $labels = array(
            'active' => __( 'Active', 'subscription-manager-for-stripe' ),
            'trialing' => __( 'Trialing', 'subscription-manager-for-stripe' ),
            'past_due' => __( 'Past Due', 'subscription-manager-for-stripe' ),
            'canceled' => __( 'Cancelled', 'subscription-manager-for-stripe' ),
            'cancelled' => __( 'Cancelled', 'subscription-manager-for-stripe' ),
            'unpaid' => __( 'Unpaid', 'subscription-manager-for-stripe' ),
            'incomplete' => __( 'Incomplete', 'subscription-manager-for-stripe' ),
            'incomplete_expired' => __( 'Expired', 'subscription-manager-for-stripe' ),
        );
        
        return isset( $labels[ $status ] ) ? $labels[ $status ] : $status;
    }
    
    /**
     * Get human-readable interval label.
     */
    private function get_interval_label( $interval ) {
        $labels = array(
            'day' => __( 'day', 'subscription-manager-for-stripe' ),
            'week' => __( 'week', 'subscription-manager-for-stripe' ),
            'month' => __( 'month', 'subscription-manager-for-stripe' ),
            'year' => __( 'year', 'subscription-manager-for-stripe' ),
        );
        
        return isset( $labels[ $interval ] ) ? $labels[ $interval ] : $interval;
    }
    
    /**
     * Legacy AJAX cancellation endpoint (deprecated).
     * Kept for backward compatibility with old frontend scripts.
     */
    public function ajax_cancel_subscription() {
        // Check nonce
        check_ajax_referer( 'strp_sub_nonce', 'nonce' );
        
        // Check user is logged in
        $user_id = get_current_user_id();
        if ( $user_id <= 0 ) {
            wp_send_json_error( array( 'message' => __( 'You must be logged in.', 'subscription-manager-for-stripe' ) ) );
            return;
        }

        // Get subscription ID
        $subscription_id = isset( $_POST['subscription_id'] ) ? sanitize_text_field( wp_unslash( $_POST['subscription_id'] ) ) : '';

        if ( empty( $subscription_id ) ) {
            wp_send_json_error( array( 'message' => __( 'Invalid subscription.', 'subscription-manager-for-stripe' ) ) );
            return;
        }

        if ( ! preg_match( '/^sub_[a-zA-Z0-9]+$/', $subscription_id ) ) {
            wp_send_json_error( array( 'message' => __( 'Invalid subscription ID format.', 'subscription-manager-for-stripe' ) ) );
            return;
        }

        // Verify subscription belongs to user
        $stripe_customer_id = get_user_meta( $user_id, '_strp_sub_stripe_customer_id', true );
        if ( empty( $stripe_customer_id ) ) {
            wp_send_json_error( array( 'message' => __( 'No customer found.', 'subscription-manager-for-stripe' ) ) );
            return;
        }

        // Verify subscription ownership before cancelling
        $stripe_api = STRP_SUB_Stripe_API::get_instance();
        $subscription = $stripe_api->get_subscription( $subscription_id );

        if ( ! $subscription ) {
            STRP_SUB_Logger::error( 'User #' . $user_id . ' attempted to cancel non-existent subscription: ' . $subscription_id );
            wp_send_json_error( array( 'message' => __( 'Subscription not found.', 'subscription-manager-for-stripe' ) ) );
            return;
        }

        if ( $subscription->customer !== $stripe_customer_id ) {
            STRP_SUB_Logger::error( 'SECURITY: User #' . $user_id . ' attempted to cancel subscription belonging to another customer: ' . $subscription_id );
            wp_send_json_error( array( 'message' => __( 'This subscription does not belong to your account.', 'subscription-manager-for-stripe' ) ) );
            return;
        }

        // Cancel subscription
        $result = $stripe_api->cancel_subscription( $subscription_id, true );

        if ( ! $result ) {
            wp_send_json_error( array( 'message' => __( 'Error cancelling subscription.', 'subscription-manager-for-stripe' ) ) );
            return;
        }
        
        STRP_SUB_Logger::log( 'User #' . $user_id . ' cancelled subscription: ' . $subscription_id );
        
        wp_send_json_success( array( 'message' => __( 'Subscription successfully cancelled.', 'subscription-manager-for-stripe' ) ) );
    }
}
