<?php
/**
 * Reward Settings REST API Controller.
 *
 * @package Ugcify\Admin\API
 */

namespace Ugcify\Admin\API;

use WP_REST_Controller;
use WP_REST_Server;
use WP_REST_Request;
use WP_REST_Response;
use WP_Error;

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

/**
 * Class RewardSettingsAPI
 */
class RewardSettingsAPI extends WP_REST_Controller {

	/**
	 * Namespace.
	 *
	 * @var string
	 */
	protected $namespace = 'ugcify/v1';

	/**
	 * Rest base.
	 *
	 * @var string
	 */
	protected $rest_base = 'settings/rewards';

	/**
	 * Option name for reward settings.
	 *
	 * @var string
	 */
	const OPTION_NAME = 'ugcify_reward_settings';

	/**
	 * Allowed coupon types.
	 *
	 * @var array
	 */
	private $allowed_coupon_types = array( 'fixed_cart', 'percent' );

	/**
	 * Register routes.
	 */
	public function register_routes() {
		register_rest_route(
			$this->namespace,
			'/' . $this->rest_base,
			array(
				array(
					'methods'             => WP_REST_Server::READABLE,
					'callback'            => array( $this, 'get_settings' ),
					'permission_callback' => array( $this, 'check_permission' ),
				),
				array(
					'methods'             => WP_REST_Server::EDITABLE,
					'callback'            => array( $this, 'update_settings' ),
					'permission_callback' => array( $this, 'check_permission' ),
				),
			)
		);

		register_rest_route(
			$this->namespace,
			'/' . $this->rest_base . '/recalculate',
			array(
				array(
					'methods'             => WP_REST_Server::CREATABLE,
					'callback'            => array( $this, 'recalculate_all' ),
					'permission_callback' => array( $this, 'check_permission' ),
				),
			)
		);
	}

	/**
	 * Recalculate all user rewards from approved reviews.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response
	 */
	public function recalculate_all( $request ) {
		require_once UGCIFY_PATH . 'includes/Points/RewardRecalculator.php';

		$result = \Ugcify\Points\RewardRecalculator::recalculate_all();

		return rest_ensure_response(
			array(
				'success' => true,
				'message' => sprintf(
					/* translators: 1: number of users, 2: total points */
					__( 'Recalculated rewards for %1$d users. Total points awarded: %2$d.', 'ugcify' ),
					$result['users_processed'],
					$result['total_points_awarded']
				),
				'data'    => $result,
			)
		);
	}

	/**
	 * Check permission — requires manage_options.
	 *
	 * @return bool|WP_Error
	 */
	public function check_permission() {
		if ( ! current_user_can( 'manage_options' ) ) {
			return new WP_Error(
				'rest_forbidden',
				__( 'Sorry, you are not allowed to access this resource.', 'ugcify' ),
				array( 'status' => 403 )
			);
		}
		return true;
	}

	/**
	 * Get reward settings.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response
	 */
	public function get_settings( $request ) {
		$settings = self::get_reward_settings();

		// Add currency information for WooCommerce.
		$settings['currency_symbol'] = function_exists( 'get_woocommerce_currency_symbol' )
			? get_woocommerce_currency_symbol()
			: '$';

		return rest_ensure_response(
			array(
				'success' => true,
				'data'    => $settings,
			)
		);
	}

	/**
	 * Update reward settings.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error
	 */
	public function update_settings( $request ) {
		$params = $request->get_json_params();

		if ( empty( $params ) ) {
			return new WP_Error(
				'invalid_data',
				__( 'Invalid data.', 'ugcify' ),
				array( 'status' => 400 )
			);
		}

		$current  = self::get_reward_settings();
		$settings = array(
			'enabled'             => isset( $params['enabled'] ) ? (bool) $params['enabled'] : (bool) $current['enabled'],
			'reward_type'         => $current['reward_type'] ?? 'coupon',
			'coupon_type'         => isset( $params['coupon_type'] ) && in_array( $params['coupon_type'], $this->allowed_coupon_types, true )
				? $params['coupon_type']
				: $current['coupon_type'],
			'coupon_value'        => isset( $params['coupon_value'] ) ? abs( floatval( $params['coupon_value'] ) ) : $current['coupon_value'],
			// Global Settings — Point Distribution.
			'pts_text_review'        => absint( $params['pts_text_review'] ?? $current['pts_text_review'] ),
			'pts_review_attachment'  => absint( $params['pts_review_attachment'] ?? $current['pts_review_attachment'] ),
			'pts_video'              => absint( $params['pts_video'] ?? $current['pts_video'] ),
			'pts_featured_bonus'     => absint( $params['pts_featured_bonus'] ?? $current['pts_featured_bonus'] ),
			'pts_lightbox_purchase'  => absint( $params['pts_lightbox_purchase'] ?? $current['pts_lightbox_purchase'] ),
			'min_redeem_amount'      => abs( floatval( $params['min_redeem_amount'] ?? $current['min_redeem_amount'] ) ),
			'max_redeem_threshold'   => absint( $params['max_redeem_threshold'] ?? $current['max_redeem_threshold'] ),
			// Legacy point keys (kept for backward compat).
			'pts_photo'             => absint( $params['pts_photo'] ?? $current['pts_photo'] ),
			'pts_referral'          => absint( $params['pts_referral'] ?? $current['pts_referral'] ),
			'pts_social_share'      => absint( $params['pts_social_share'] ?? $current['pts_social_share'] ),
			// Social sharing.
			'social_share_enabled'  => ! empty( $params['social_share_enabled'] ?? $current['social_share_enabled'] ),
			'pts_share_click'       => absint( $params['pts_share_click'] ?? $current['pts_share_click'] ),
			'pts_share_conversion'  => absint( $params['pts_share_conversion'] ?? $current['pts_share_conversion'] ),
			'max_discount_cap'    => isset( $params['max_discount_cap'] ) ? min( 100, absint( $params['max_discount_cap'] ) ) : $current['max_discount_cap'],
			'retry_delay_seconds' => isset( $params['retry_delay_seconds'] ) ? max( 10, absint( $params['retry_delay_seconds'] ) ) : $current['retry_delay_seconds'],
			'tiers_enabled'       => ! empty( $params['tiers_enabled'] ?? $current['tiers_enabled'] ),
			'badges_enabled'      => ! empty( $params['badges_enabled'] ?? $current['badges_enabled'] ),
			'leaderboard_enabled' => ! empty( $params['leaderboard_enabled'] ?? $current['leaderboard_enabled'] ),
			'tier_thresholds'        => self::sanitize_tier_thresholds( $params['tier_thresholds'] ?? $current['tier_thresholds'] ),
			'tier_discount_rates'    => self::sanitize_tier_discount_rates( $params['tier_discount_rates'] ?? $current['tier_discount_rates'] ),
			'free_product_threshold' => absint( $params['free_product_threshold'] ?? $current['free_product_threshold'] ),
			'free_product_sku'       => sanitize_text_field( $params['free_product_sku'] ?? $current['free_product_sku'] ),
			// Badge settings.
			'badges'              => array_key_exists( 'badges', $params ) && is_array( $params['badges'] )
				? self::sanitize_badges( $params['badges'] )
				: $current['badges'],
		);

		$result = update_option( self::OPTION_NAME, $settings, true );

		if ( false === $result && get_option( self::OPTION_NAME ) !== $settings ) {
			return new WP_Error(
				'update_failed',
				__( 'Failed to update reward settings.', 'ugcify' ),
				array( 'status' => 500 )
			);
		}

		return rest_ensure_response(
			array(
				'success' => true,
				'message' => __( 'Reward settings updated successfully.', 'ugcify' ),
				'data'    => $settings,
			)
		);
	}

	/**
	 * Get reward settings from database.
	 *
	 * @return array
	 */
	public static function get_reward_settings() {
		$defaults = self::default_settings();
		$settings = get_option( self::OPTION_NAME, $defaults );
		if ( isset( $settings['pts_social_share'] ) && ! isset( $settings['pts_share_click'] ) ) {
			$settings['pts_share_click'] = absint( $settings['pts_social_share'] );
		}

		return wp_parse_args( $settings, $defaults );
	}

	/**
	 * Default settings array.
	 *
	 * @return array
	 */
	private static function default_settings(): array {
		return array(
			// Existing.
			'enabled'               => false,
			'reward_type'           => 'coupon',
			'coupon_type'           => 'fixed_cart',
			'coupon_value'          => 0,
			// Global Settings — Point Distribution.
			'pts_text_review'       => 5,
			'pts_review_attachment' => 15,
			'pts_video'             => 30,
			'pts_featured_bonus'    => 10,
			'pts_lightbox_purchase' => 20,
			'min_redeem_amount'     => 50,
			'max_redeem_threshold'  => 500,
			// Legacy point keys.
			'pts_photo'             => 20,
			'pts_referral'          => 15,
			'pts_social_share'      => 5,
			// Social sharing.
			'social_share_enabled'  => false,
			'pts_share_click'       => 0,
			'pts_share_conversion'  => 0,
			// Safety.
			'max_discount_cap'      => 20,
			'retry_delay_seconds'   => 60,
			// Tiers on/off.
			'tiers_enabled'         => true,
			'badges_enabled'        => true,
			'leaderboard_enabled'   => false,
			// Per-tier thresholds — each entry: [uploads_required, points_required].
			'tier_thresholds'       => [
				'newcomer'    => [ 'uploads' => 1,  'points' => 20  ],
				'contributor' => [ 'uploads' => 3,  'points' => 100 ],
				'advocate'    => [ 'uploads' => 6,  'points' => 200 ],
				'champion'    => [ 'uploads' => 10, 'points' => 300 ],
			],
			// Per-tier discount % (used when reward_type = 'coupon').
			'tier_discount_rates'   => [
				'newcomer'    => 10,
				'contributor' => 12,
				'advocate'    => 14,
				'champion'    => 15,
			],
			// Free product reward settings (Sprint 5 backend).
			'free_product_threshold' => 500,
			'free_product_sku'       => '',
			// Badge settings.
			'badges'                => [],
		);
	}

	/**
	 * Sanitize tier thresholds array.
	 *
	 * @param array $raw Raw input.
	 * @return array
	 */
	private static function sanitize_tier_thresholds( array $raw ): array {
		$defaults = self::default_settings()['tier_thresholds'];
		$result   = [];
		foreach ( $defaults as $tier => $def ) {
			$result[ $tier ] = [
				'uploads' => absint( $raw[ $tier ]['uploads'] ?? $def['uploads'] ),
				'points'  => absint( $raw[ $tier ]['points']  ?? $def['points'] ),
			];
		}
		return $result;
	}

	/**
	 * Sanitize tier discount rates array.
	 *
	 * @param array $raw Raw input.
	 * @return array
	 */
	private static function sanitize_tier_discount_rates( array $raw ): array {
		$defaults = self::default_settings()['tier_discount_rates'];
		$result   = [];
		foreach ( $defaults as $tier => $default_rate ) {
			$result[ $tier ] = min( 100, absint( $raw[ $tier ] ?? $default_rate ) );
		}
		return $result;
	}

	/**
	 * Sanitize badges array.
	 *
	 * @param mixed $raw Raw input.
	 * @return array
	 */
	private static function sanitize_badges( $raw ): array {
		if ( ! is_array( $raw ) ) {
			return [];
		}

		$allowed_types = array( 'flat', 'discount' );
		$sanitized     = [];

		foreach ( $raw as $badge ) {
			if ( ! is_array( $badge ) || empty( $badge['name'] ) ) {
				continue;
			}

			$discount_type = isset( $badge['discount_type'] ) && in_array( $badge['discount_type'], $allowed_types, true )
				? $badge['discount_type']
				: 'flat';

			$amount = abs( floatval( $badge['amount'] ?? 1 ) );
			if ( 'discount' === $discount_type ) {
				$amount = min( 100, $amount );
			}

			$sanitized[] = array(
				'id'                => absint( $badge['id'] ?? count( $sanitized ) + 1 ),
				'name'              => sanitize_text_field( $badge['name'] ),
				'min_contribution'  => absint( $badge['min_contribution'] ?? 0 ),
				'conversion_points' => max( 1, absint( $badge['conversion_points'] ?? 1 ) ),
				'discount_type'     => $discount_type,
				'amount'            => $amount,
				'icon_url'          => esc_url_raw( $badge['icon_url'] ?? '' ),
				'icon_id'           => absint( $badge['icon_id'] ?? 0 ),
				'active'            => ! empty( $badge['active'] ),
			);
		}

		return $sanitized;
	}

	/**
	 * Check if rewards are enabled.
	 *
	 * @return bool
	 */
	public static function is_enabled(): bool {
		$settings = self::get_reward_settings();
		return ! empty( $settings['enabled'] );
	}

	/**
	 * Check if social sharing is enabled.
	 *
	 * @return bool
	 */
	public static function is_social_share_enabled(): bool {
		$settings = self::get_reward_settings();
		return ! empty( $settings['social_share_enabled'] );
	}
}
