<?php

namespace Dobare\Checkout\API;

use Dobare\Abstracts\Dobare_REST_Controller;
use Dobare\Core\Dobare_Core;
use Dobare\Utils\Dobare_Utils;
use WP_REST_Request;
use WP_REST_Response;

class Dobare_Checkout_REST_Controller extends Dobare_REST_Controller
{
	public function __construct()
	{
		$this->resource_name = 'checkout';
	}

	public function register_routes()
	{
		register_rest_route($this->namespace, '/' . $this->resource_name . '/apply-credit', array(
			'methods'             => 'POST',
			'callback'            => array($this, 'do_checkout_logic'),
			// This endpoint is intentionally public: it only persists a normalized phone
			// in the WooCommerce session to enable gift credit revalidation client-side.
			// It does not expose sensitive data or alter server-side state beyond session.
			'permission_callback' => array($this, 'checkout_permissions_check'),
		));

		// Immediate apply endpoint used by manual button on checkout
		register_rest_route($this->namespace, '/' . $this->resource_name . '/apply-credit-now', array(
			'methods'             => 'POST',
			'callback'            => array($this, 'apply_credit_now'),
			// This endpoint is intentionally public: guests can apply credit during checkout.
			// Nonce verification is performed within checkout_permissions_check for logged-in users.
			'permission_callback' => array($this, 'checkout_permissions_check'),
		));
	}

	public function checkout_permissions_check(WP_REST_Request $request)
	{
		// For checkout endpoints, we allow public access but verify nonce for logged-in users
		// This is intentional as checkout can be used by guests
		if (is_user_logged_in()) {
			// Verify nonce for logged-in users to prevent CSRF
			$nonce = $request->get_header('X-WP-Nonce');
			if ($nonce && !wp_verify_nonce($nonce, 'wp_rest')) {
				return new \WP_Error(
					'rest_forbidden',
					esc_html__('Invalid security token.', 'dobare'),
					array('status' => 403)
				);
			}
		}

		return true;
	}

	public function do_checkout_logic(WP_REST_Request $request)
	{
		$params   = $request->get_json_params();
		// Sanitize phone number input
		$phone    = isset($params['phone']) ? sanitize_text_field($params['phone']) : null;
		$response = array('data' => "", "status" => 500);
		if (! empty($phone) && ! empty(Dobare_Utils::validate_and_normalize_phone_number($phone))) {
			$normalized = Dobare_Utils::validate_and_normalize_phone_number($phone);
			// Persist for unified revalidation flow; do not apply directly here
			if (function_exists('WC') && \WC()->session) {
				\WC()->session->set('dobare_credit_applied_for_phone', $normalized);
			}
			$response["data"]   = array('success' => true);
			$response['status'] = 200;
		}


		return is_wp_error($response) ? $response : new WP_REST_Response($response["data"], $response["status"]);
	}

	/**
	 * Immediately apply credit for the provided or inferred phone number
	 *
	 * @param WP_REST_Request $request
	 * @return WP_REST_Response
	 */
	public function apply_credit_now(WP_REST_Request $request)
	{
		$timer_total = 0.0;
		if (Dobare_Utils::credit_perf_is_enabled()) {
			$timer_total = Dobare_Utils::credit_perf_start('checkout_apply_credit_now');
		}

		$params = $request->get_json_params();
		// Sanitize phone number input
		$phone  = isset($params['phone']) ? sanitize_text_field($params['phone']) : '';

		if (Dobare_Utils::is_credit_temporarily_disabled()) {
			$response = new WP_REST_Response(
				array(
					'success'          => false,
					'applied'          => false,
					'minimum_cart_met' => false,
					'message'          => 'credit_temporarily_disabled',
				),
				200
			);

			if (Dobare_Utils::credit_perf_is_enabled()) {
				Dobare_Utils::credit_perf_end('checkout_apply_credit_now', (float) $timer_total, array('result' => 'credit_disabled'));
				$response = Dobare_Utils::credit_perf_attach_rest_headers($response);
			}

			return $response;
		}

		$normalized = Dobare_Utils::validate_and_normalize_phone_number($phone);

		// Try to infer from session/checkout data if not provided or invalid
		if (empty($normalized) && function_exists('WC') && \WC()->session) {
			$session_phone = (string) \WC()->session->get('dobare_credit_applied_for_phone', '');
			if (empty($session_phone)) {
				$checkout_data = \WC()->session->get('checkout_data');
				if (!empty($checkout_data)) {
					$session_phone = (string) ($checkout_data['billing_phone'] ?? ($checkout_data['shipping_phone'] ?? ''));
				}
			}
			$normalized = Dobare_Utils::validate_and_normalize_phone_number($session_phone);
		}

		if (empty($normalized)) {
			$response = new WP_REST_Response(array('success' => false, 'applied' => false, 'message' => 'invalid_phone'), 400);
			if (Dobare_Utils::credit_perf_is_enabled()) {
				Dobare_Utils::credit_perf_end('checkout_apply_credit_now', (float) $timer_total, array('result' => 'invalid_phone'));
				$response = Dobare_Utils::credit_perf_attach_rest_headers($response);
			}
			return $response;
		}

		// Ensure WooCommerce session is initialized for REST requests
		if (function_exists('WC') && !WC()->session) {
			$timer_session = 0.0;
			if (Dobare_Utils::credit_perf_is_enabled()) {
				$timer_session = Dobare_Utils::credit_perf_start('wc_session_init_rest');
			}

			WC()->session = new \WC_Session_Handler();
			WC()->session->init();

			if (Dobare_Utils::credit_perf_is_enabled()) {
				Dobare_Utils::credit_perf_end('wc_session_init_rest', (float) $timer_session);
			}
		}

		if (function_exists('WC') && \WC()->session) {
			\WC()->session->set('dobare_credit_applied_for_phone', $normalized);
			// Manual apply is an explicit user opt-in to re-apply credit on the next checkout update.
			Dobare_Utils::set_auto_apply_suppression(false);

			// One-shot flag: ensure the next checkout update tries to apply credit.
			\WC()->session->set('dobare_manual_apply_credit_until', time() + 120);

			// If perf was enabled via query/header, persist it now that session is initialized.
			if (Dobare_Utils::credit_perf_is_enabled()) {
				Dobare_Utils::credit_perf_enable_for_session();
			}
		}

		$applied = false;
		$minimum_met = false;
		if (function_exists('WC') && \WC()->cart && \WC()->session) {
			$applied_coupons = \WC()->cart->get_applied_coupons();
			foreach ($applied_coupons as $coupon_code) {
				if (Dobare_Utils::is_dobare_coupon($coupon_code)) {
					$applied = true;
					break;
				}
			}
			$minimum_met = (bool) \WC()->session->get('dobare_minimum_cart_met', false);
		}

		$response_body = array(
			'success'           => true,
			'applied'           => $applied,
			'queued'            => !$applied,
			'minimum_cart_met'  => $minimum_met,
			'user_phone'        => $normalized,
		);

		$response = new WP_REST_Response($response_body, 200);

		if (Dobare_Utils::credit_perf_is_enabled()) {
			Dobare_Utils::credit_perf_end('checkout_apply_credit_now', (float) $timer_total, array('result' => 'ok'));
			$response_body['perf'] = Dobare_Utils::credit_perf_export();
			$response = new WP_REST_Response($response_body, 200);
			$response = Dobare_Utils::credit_perf_attach_rest_headers($response);
			Dobare_Utils::credit_perf_maybe_log('checkout/apply-credit-now', array('phone' => $normalized));
		}

		return $response;
	}
}
