<?php

namespace SplitPay\Frontend;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Front-end shortcode [split_pay_vendor_connect].
 *
 * Renders a "Connect with Stripe" button on any public page so vendors can
 * complete Stripe Connect onboarding without needing wp-admin access. Reuses
 * the same Stripe account + accountLink onboarding flow that the admin-side
 * vendor onboarding screen uses (see includes/admin/class-bsd-sca.php).
 *
 * Usage:
 *   [split_pay_vendor_connect]
 *   [split_pay_vendor_connect button_label="Become a Vendor" connected_label="Stripe connected"]
 *
 * @since 3.7.0
 */
class VendorConnectShortcode {

	public function register(): void {
		add_shortcode( 'split_pay_vendor_connect', [ $this, 'render' ] );
		add_action( 'init', [ $this, 'maybeHandleConnect' ], 20 );
	}

	public function render( $atts = [] ): string {
		$atts = shortcode_atts(
			[
				'button_label'      => __( 'Connect with Stripe', 'bsd-split-pay-stripe-connect-woo' ),
				'connected_label'   => __( 'Your Stripe account is connected.', 'bsd-split-pay-stripe-connect-woo' ),
				'login_label'       => __( 'Please log in to connect your Stripe account.', 'bsd-split-pay-stripe-connect-woo' ),
				'pending_label'     => __( 'Stripe onboarding is in progress. Complete the steps with Stripe to finish.', 'bsd-split-pay-stripe-connect-woo' ),
			],
			is_array( $atts ) ? $atts : [],
			'split_pay_vendor_connect'
		);

		if ( ! is_user_logged_in() ) {
			$login_url = wp_login_url( get_permalink() ?: home_url( '/' ) );
			return '<div class="spp-vendor-connect spp-vendor-connect--logged-out">'
				. '<p>' . esc_html( $atts['login_label'] ) . '</p>'
				. '<a class="button" href="' . esc_url( $login_url ) . '">'
				. esc_html__( 'Log In', 'bsd-split-pay-stripe-connect-woo' )
				. '</a>'
				. '</div>';
		}

		$user_id    = get_current_user_id();
		$account_id = (string) get_user_meta( $user_id, 'account_id', true );
		$is_onboard = (string) get_user_meta( $user_id, 'is_onboard', true );

		if ( $account_id !== '' && $is_onboard === '1' ) {
			return '<div class="spp-vendor-connect spp-vendor-connect--connected">'
				. '<p>' . esc_html( $atts['connected_label'] ) . '</p>'
				. '</div>';
		}

		if ( $account_id !== '' && $is_onboard !== '1' ) {
			$action_url = esc_url(
				add_query_arg(
					[
						'spp_action'       => 'vendor_connect',
						'_spp_connect_nonce' => wp_create_nonce( 'spp_vendor_connect' ),
					],
					get_permalink() ?: home_url( '/' )
				)
			);
			return '<div class="spp-vendor-connect spp-vendor-connect--pending">'
				. '<p>' . esc_html( $atts['pending_label'] ) . '</p>'
				. '<a class="button button-primary" href="' . $action_url . '">'
				. esc_html__( 'Resume Stripe Onboarding', 'bsd-split-pay-stripe-connect-woo' )
				. '</a>'
				. '</div>';
		}

		$action_url = esc_url(
			add_query_arg(
				[
					'spp_action'         => 'vendor_connect',
					'_spp_connect_nonce' => wp_create_nonce( 'spp_vendor_connect' ),
				],
				get_permalink() ?: home_url( '/' )
			)
		);

		return '<div class="spp-vendor-connect spp-vendor-connect--connect">'
			. '<a class="button button-primary" href="' . $action_url . '">'
			. esc_html( $atts['button_label'] )
			. '</a>'
			. '</div>';
	}

	public function maybeHandleConnect(): void {
		if ( is_admin() ) {
			return;
		}
		if ( empty( $_GET['spp_action'] ) || $_GET['spp_action'] !== 'vendor_connect' ) {
			return;
		}
		if ( ! is_user_logged_in() ) {
			wp_safe_redirect( wp_login_url( home_url( '/' ) ) );
			exit;
		}
		if ( empty( $_GET['_spp_connect_nonce'] )
			|| ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_spp_connect_nonce'] ) ), 'spp_vendor_connect' )
		) {
			wp_die( esc_html__( 'Invalid request. Please refresh and try again.', 'bsd-split-pay-stripe-connect-woo' ), '', [ 'response' => 400 ] );
		}

		$current_user = wp_get_current_user();
		// 3.7.5 static-analysis: wp_get_current_user() always returns WP_User,
		// so the redundant null/falsy check was dropped. ID===0 covers
		// anonymous visitors.
		if ( 0 === $current_user->ID ) {
			wp_safe_redirect( home_url( '/' ) );
			exit;
		}

		$return_url  = get_permalink() ?: home_url( '/' );
		$secret_key  = $this->resolveStripeSecretKey();
		if ( $secret_key === '' ) {
			wp_die(
				esc_html__( 'Stripe is not yet configured by the site administrator.', 'bsd-split-pay-stripe-connect-woo' ),
				'',
				[ 'response' => 500 ]
			);
		}

		try {
			$stripe   = new \Stripe\StripeClient( $secret_key );
			$existing = (string) get_user_meta( $current_user->ID, 'account_id', true );

			if ( $existing === '' ) {
				/**
				 * Filter the arguments passed to Stripe's accounts->create() when a
				 * new vendor connects via the front-end shortcode.
				 *
				 * Pre-3.7.5 (sc-7186) this hard-coded ['type' => 'standard']. Stripe
				 * has since reframed Standard / Express / Custom as legacy categories
				 * and recommends Accounts v2 with `controller` properties for new
				 * platforms. v1 'standard' accounts continue to work indefinitely —
				 * Stripe is NOT turning them off — so the default is unchanged and
				 * no existing install is affected. Site operators who want to opt
				 * into Accounts v2 today can return v2 controller-property args:
				 *
				 *     add_filter( 'spp_account_create_args', function ( $args, $context ) {
				 *         return [
				 *             'controller' => [
				 *                 'losses'                 => [ 'payments' => 'application' ],
				 *                 'fees'                   => [ 'payer'    => 'application' ],
				 *                 'requirement_collection' => 'application',
				 *                 'stripe_dashboard'       => [ 'type' => 'none' ],
				 *             ],
				 *         ];
				 *     }, 10, 2 );
				 *
				 * @since 3.7.5
				 *
				 * @param array  $args    Args passed to $stripe->accounts->create().
				 * @param string $context 'shortcode' (front-end self-service) or
				 *                        'admin' (admin "Onboard new account" button).
				 *
				 * @link https://docs.stripe.com/connect/accounts-v2 Stripe Accounts v2 docs.
				 * @todo SPP 3.8.0 (sc-7190) — full v1 → v2 migration with capability negotiation.
				 */
				$account_args = apply_filters( 'spp_account_create_args', [ 'type' => 'standard' ], 'shortcode' );
				$account      = $stripe->accounts->create( $account_args );
				if ( empty( $account->id ) ) {
					wp_die( esc_html__( 'Could not start Stripe onboarding. Please try again.', 'bsd-split-pay-stripe-connect-woo' ), '', [ 'response' => 500 ] );
				}
				update_user_meta( $current_user->ID, 'account_id', $account->id );
				$account_id = $account->id;
			} else {
				$account_id = $existing;
			}

			$account_link = $stripe->accountLinks->create( [
				'account'     => $account_id,
				'refresh_url' => add_query_arg( [ 'spp_action' => 'vendor_connect', '_spp_connect_nonce' => wp_create_nonce( 'spp_vendor_connect' ) ], $return_url ),
				'return_url'  => add_query_arg( [ 'spp_event' => 'vendor_connect_return', 'acc_id' => $account_id ], $return_url ),
				'type'        => 'account_onboarding',
			] );

			if ( ! empty( $account_link->url ) ) {
				// Whitelist Stripe-hosted onboarding hosts so wp_safe_redirect()
				// doesn't reject them (Stripe rotates between connect.stripe.com
				// and hooks.stripe.com depending on flow).
				$stripe_redirect_hosts = function ( $hosts ) {
					$hosts[] = 'connect.stripe.com';
					$hosts[] = 'hooks.stripe.com';
					$hosts[] = 'dashboard.stripe.com';
					return $hosts;
				};
				add_filter( 'allowed_redirect_hosts', $stripe_redirect_hosts );
				wp_safe_redirect( esc_url_raw( $account_link->url ) );
				remove_filter( 'allowed_redirect_hosts', $stripe_redirect_hosts );
				exit;
			}
		} catch ( \Exception $e ) {
			// Use the global safe-log helper so the IntegrationLogGuardTest
			// regression assertion stays clean. Falls through to error_log()
			// internally when WC Stripe is absent.
			if ( function_exists( '\\BSD_Split_Pay_Stripe_Connect_Woo\\spp_safe_wcs_log' ) ) {
				\BSD_Split_Pay_Stripe_Connect_Woo\spp_safe_wcs_log(
					'[Split Pay Vendor Connect Shortcode] ' . $e->getMessage()
				);
			} else {
				if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { error_log( '[Split Pay Vendor Connect Shortcode] ' . $e->getMessage() ); } // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
			}
			wp_die(
				esc_html__( 'Could not start Stripe onboarding. Please try again later.', 'bsd-split-pay-stripe-connect-woo' ),
				'',
				[ 'response' => 500 ]
			);
		}
	}

	private function resolveStripeSecretKey(): string {
		$woocommerce_stripe_settings = get_option( 'woocommerce_stripe_settings' );
		$is_test                     = is_array( $woocommerce_stripe_settings )
			&& isset( $woocommerce_stripe_settings['testmode'] )
			&& $woocommerce_stripe_settings['testmode'] === 'yes';

		if ( $is_test ) {
			$key = (string) get_option( 'stripe_test_api_secret_key', '' );
		} else {
			$key = (string) get_option( 'stripe_api_secret_key', '' );
		}

		if ( $key === '' && is_array( $woocommerce_stripe_settings ) ) {
			$key = (string) ( $is_test
				? ( $woocommerce_stripe_settings['test_secret_key'] ?? '' )
				: ( $woocommerce_stripe_settings['secret_key'] ?? '' ) );
		}

		return $key;
	}
}
