<?php
/**
 * General Settings REST API endpoints.
 *
 * @package SureDonation
 */

namespace SureDonation\Inc\API;

use SureDonation\Inc\Emails\Email_Template;
use SureDonation\Inc\Helper;
use SureDonation\Inc\Payments\Payment_Helper;
use WP_Error;
use WP_REST_Request;
use WP_REST_Response;
use WP_REST_Server;

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

/**
 * Settings API class.
 *
 * @since 0.0.1
 */
class Settings_API {
	/**
	 * Option key for email notifications within consolidated options.
	 *
	 * @since 0.0.1
	 */
	public const EMAIL_OPTION_KEY = 'email_notifications';

	/**
	 * Get settings endpoints.
	 *
	 * @return array<string, mixed>
	 * @since 0.0.1
	 */
	public function get_endpoints() {
		return [
			// Get currency data for block editor (public endpoint).
			'/settings'            => [
				'methods'             => WP_REST_Server::READABLE,
				'callback'            => [ $this, 'get_currency_settings' ],
				'permission_callback' => '__return_true',
			],

			// Get and update general settings.
			'/settings/general'    => [
				[
					'methods'             => WP_REST_Server::READABLE,
					'callback'            => [ $this, 'get_settings' ],
					'permission_callback' => [ $this, 'check_permissions' ],
				],
				[
					'methods'             => WP_REST_Server::EDITABLE,
					'callback'            => [ $this, 'update_settings' ],
					'permission_callback' => [ $this, 'check_permissions' ],
				],
			],

			// Get available currencies.
			'/settings/currencies' => [
				'methods'             => WP_REST_Server::READABLE,
				'callback'            => [ $this, 'get_currencies' ],
				'permission_callback' => [ $this, 'check_permissions' ],
			],

			// Email settings.
			'/settings/email'      => [
				[
					'methods'             => WP_REST_Server::READABLE,
					'callback'            => [ $this, 'get_email_settings' ],
					'permission_callback' => [ $this, 'check_permissions' ],
				],
				[
					'methods'             => WP_REST_Server::EDITABLE,
					'callback'            => [ $this, 'update_email_settings' ],
					'permission_callback' => [ $this, 'check_permissions' ],
				],
			],

			// Send test email.
			'/settings/email/test' => [
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => [ $this, 'send_test_email' ],
				'permission_callback' => [ $this, 'check_permissions' ],
			],
		];
	}

	/**
	 * Get currency settings for block editor.
	 *
	 * Returns minimal currency data needed for frontend/block previews.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response Response object.
	 * @since 0.0.1
	 */
	public function get_currency_settings( $request ) {
		unset( $request ); // Unused parameter.

		$currency = Payment_Helper::get_currency();

		return new WP_REST_Response(
			[
				'currency'       => $currency,
				'currencySymbol' => Payment_Helper::get_currency_symbol( $currency ),
				'isZeroDecimal'  => Payment_Helper::is_zero_decimal_currency( $currency ),
			],
			200
		);
	}

	/**
	 * Get general settings.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response Response object.
	 * @since 0.0.1
	 */
	public function get_settings( $request ) {
		unset( $request ); // Unused parameter.

		$settings = Payment_Helper::get_all_payment_settings();

		return new WP_REST_Response(
			[
				'success'  => true,
				'settings' => [
					'currency'     => $settings['currency'] ?? 'USD',
					'payment_mode' => $settings['payment_mode'] ?? 'test',
				],
			],
			200
		);
	}

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

		if ( empty( $params ) ) {
			return new WP_Error(
				'invalid_settings',
				__( 'Invalid settings provided', 'suredonation' ),
				[ 'status' => 400 ]
			);
		}

		$current_settings = Payment_Helper::get_all_payment_settings();

		// Update currency if provided.
		if ( isset( $params['currency'] ) ) {
			$currency = strtoupper( sanitize_text_field( $params['currency'] ) );

			// Validate currency.
			$valid_currencies = array_keys( Payment_Helper::get_all_currencies_data() );
			if ( in_array( $currency, $valid_currencies, true ) ) {
				$current_settings['currency'] = $currency;
			}
		}

		// Update payment mode if provided.
		if ( isset( $params['payment_mode'] ) ) {
			$mode = sanitize_text_field( $params['payment_mode'] );
			if ( in_array( $mode, [ 'test', 'live' ], true ) ) {
				$current_settings['payment_mode'] = $mode;
			}
		}

		$success = Payment_Helper::update_all_payment_settings( $current_settings );

		if ( ! $success ) {
			return new WP_Error(
				'update_failed',
				__( 'Failed to update settings', 'suredonation' ),
				[ 'status' => 500 ]
			);
		}

		return new WP_REST_Response(
			[
				'success' => true,
				'message' => __( 'Settings updated successfully', 'suredonation' ),
			],
			200
		);
	}

	/**
	 * Get available currencies.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response Response object.
	 * @since 0.0.1
	 */
	public function get_currencies( $request ) {
		unset( $request ); // Unused parameter.

		$currencies_data = Payment_Helper::get_all_currencies_data();

		// Format for frontend: "CODE - Name".
		$currencies = [];
		foreach ( $currencies_data as $code => $data ) {
			$currencies[ $code ] = $code . ' - ' . $data['name'];
		}

		return new WP_REST_Response(
			[
				'success'    => true,
				'currencies' => $currencies,
			],
			200
		);
	}

	/**
	 * Get email settings.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response Response object.
	 * @since 0.0.1
	 */
	public function get_email_settings( $request ) {
		unset( $request ); // Unused parameter.

		$saved_notifications   = Helper::get_array_value( Helper::get_suredonation_option( self::EMAIL_OPTION_KEY, [] ) );
		$default_notifications = $this->get_default_notifications();

		// Merge saved settings with defaults.
		$notifications = [];
		foreach ( $default_notifications as $key => $default ) {
			$saved_value           = isset( $saved_notifications[ $key ] ) && is_array( $saved_notifications[ $key ] ) ? $saved_notifications[ $key ] : [];
			$notifications[ $key ] = wp_parse_args(
				$saved_value,
				$default
			);
		}

		return new WP_REST_Response(
			[
				'success'       => true,
				'notifications' => $notifications,
			],
			200
		);
	}

	/**
	 * Update email settings.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error Response object.
	 * @since 0.0.1
	 */
	public function update_email_settings( $request ) {
		$params = $request->get_json_params();

		if ( empty( $params ) || ! isset( $params['notifications'] ) ) {
			return new WP_Error(
				'invalid_settings',
				__( 'Invalid settings provided', 'suredonation' ),
				[ 'status' => 400 ]
			);
		}

		$current_notifications = Helper::get_array_value( Helper::get_suredonation_option( self::EMAIL_OPTION_KEY, [] ) );
		$valid_keys            = array_keys( $this->get_default_notifications() );

		foreach ( $params['notifications'] as $key => $notification ) {
			// Only allow known notification types.
			if ( ! in_array( $key, $valid_keys, true ) ) {
				continue;
			}

			$current_notifications[ $key ] = [
				'enabled'    => isset( $notification['enabled'] ) ? (bool) $notification['enabled'] : false,
				'subject'    => isset( $notification['subject'] ) ? sanitize_text_field( $notification['subject'] ) : '',
				'from_name'  => isset( $notification['from_name'] ) ? sanitize_text_field( $notification['from_name'] ) : '',
				'from_email' => isset( $notification['from_email'] ) ? sanitize_email( $notification['from_email'] ) : '',
				'reply_to'   => isset( $notification['reply_to'] ) ? sanitize_email( $notification['reply_to'] ) : '',
				'email_body' => isset( $notification['email_body'] ) ? wp_kses_post( $notification['email_body'] ) : '',
			];
		}

		Helper::update_suredonation_option( self::EMAIL_OPTION_KEY, $current_notifications );

		return new WP_REST_Response(
			[
				'success' => true,
				'message' => __( 'Email settings saved', 'suredonation' ),
			],
			200
		);
	}

	/**
	 * Send a test email.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error Response object.
	 * @since 0.0.1
	 */
	public function send_test_email( $request ) {
		$params = $request->get_json_params();

		if ( empty( $params['notification_id'] ) ) {
			return new WP_Error(
				'missing_notification_id',
				__( 'Notification ID is required', 'suredonation' ),
				[ 'status' => 400 ]
			);
		}

		$notification_id = sanitize_text_field( $params['notification_id'] );
		$admin_email     = get_option( 'admin_email' );
		$test_email      = ! empty( $params['test_email'] ) ? sanitize_email( $params['test_email'] ) : ( is_string( $admin_email ) ? $admin_email : '' );

		if ( ! is_email( $test_email ) ) {
			return new WP_Error(
				'invalid_email',
				__( 'Invalid email address', 'suredonation' ),
				[ 'status' => 400 ]
			);
		}

		// Get notification settings.
		$saved_notifications   = Helper::get_array_value( Helper::get_suredonation_option( self::EMAIL_OPTION_KEY, [] ) );
		$default_notifications = $this->get_default_notifications();

		if ( ! isset( $default_notifications[ $notification_id ] ) ) {
			return new WP_Error(
				'invalid_notification',
				__( 'Invalid notification type', 'suredonation' ),
				[ 'status' => 400 ]
			);
		}

		$saved_notification_value = isset( $saved_notifications[ $notification_id ] ) && is_array( $saved_notifications[ $notification_id ] ) ? $saved_notifications[ $notification_id ] : [];
		$notification             = wp_parse_args(
			$saved_notification_value,
			$default_notifications[ $notification_id ]
		);

		// Use current form data if provided (for preview before save).
		if ( ! empty( $params['notification_data'] ) && is_array( $params['notification_data'] ) ) {
			$raw            = $params['notification_data'];
			$sanitized_data = [];
			if ( isset( $raw['subject'] ) ) {
				$sanitized_data['subject'] = sanitize_text_field( $raw['subject'] );
			}
			if ( isset( $raw['from_name'] ) ) {
				$sanitized_data['from_name'] = sanitize_text_field( $raw['from_name'] );
			}
			if ( isset( $raw['from_email'] ) ) {
				$sanitized_data['from_email'] = sanitize_email( $raw['from_email'] );
			}
			if ( isset( $raw['reply_to'] ) ) {
				$sanitized_data['reply_to'] = sanitize_email( $raw['reply_to'] );
			}
			if ( isset( $raw['email_body'] ) ) {
				$sanitized_data['email_body'] = wp_kses_post( $raw['email_body'] );
			}
			if ( isset( $raw['enabled'] ) ) {
				$sanitized_data['enabled'] = (bool) $raw['enabled'];
			}
			$notification = wp_parse_args( $sanitized_data, $notification );
		}

		// Create sample donation data for smart tags.
		$sample_data = $this->get_sample_donation_data();

		// Process smart tags.
		$subject    = $this->process_test_smart_tags( $notification['subject'] ?? '', $sample_data );
		$email_body = $this->process_test_smart_tags( $notification['email_body'] ?? '', $sample_data );

		// Get from name and email.
		$from_name  = ! empty( $notification['from_name'] ) ? $notification['from_name'] : get_bloginfo( 'name' );
		$from_email = ! empty( $notification['from_email'] ) ? $notification['from_email'] : get_option( 'admin_email' );
		$reply_to   = ! empty( $notification['reply_to'] ) ? $notification['reply_to'] : $from_email;

		// Process smart tags in from name.
		$from_name = $this->process_test_smart_tags( $from_name, $sample_data );

		// Set email headers.
		$headers = [
			'Content-Type: text/html; charset=UTF-8',
			sprintf( 'From: %s <%s>', $from_name, $from_email ),
			sprintf( 'Reply-To: %s', $reply_to ),
		];

		// Format email body with HTML wrapper.
		$email_body = $this->format_test_email_body( $email_body );

		// Send email.
		$sent = wp_mail( $test_email, $subject, $email_body, $headers );

		if ( ! $sent ) {
			return new WP_Error(
				'email_failed',
				__( 'Failed to send test email. Please check your email configuration.', 'suredonation' ),
				[ 'status' => 500 ]
			);
		}

		return new WP_REST_Response(
			[
				'success' => true,
				'message' => sprintf(
					/* translators: %s: email address */
					__( 'Test email sent to %s', 'suredonation' ),
					$test_email
				),
			],
			200
		);
	}

	/**
	 * Check if user has permission to manage settings.
	 *
	 * @return bool True if user has permission.
	 * @since 0.0.1
	 */
	public function check_permissions() {
		return current_user_can( 'manage_options' );
	}

	/**
	 * Get default notification configurations.
	 *
	 * @return array<string, array<string, mixed>> Default notifications.
	 * @since 0.0.1
	 */
	private function get_default_notifications() {
		return [
			'donation_receipt'   => [
				'id'          => 'donation_receipt',
				'name'        => __( 'Donation Receipt', 'suredonation' ),
				'description' => __( 'Sent to donor after a successful donation.', 'suredonation' ),
				'recipient'   => 'donor',
				'enabled'     => true,
				'subject'     => __( 'Thank you for your donation!', 'suredonation' ),
				'from_name'   => '',
				'from_email'  => '',
				'reply_to'    => '',
				'email_body'  => $this->get_donation_receipt_body(),
			],
			'admin_new_donation' => [
				'id'          => 'admin_new_donation',
				'name'        => __( 'New Donation (Admin)', 'suredonation' ),
				'description' => __( 'Sent to admin when a new donation is received.', 'suredonation' ),
				'recipient'   => 'admin',
				'enabled'     => true,
				'subject'     => __( 'New donation received!', 'suredonation' ),
				'from_name'   => '',
				'from_email'  => '',
				'reply_to'    => '',
				'email_body'  => $this->get_admin_new_donation_body(),
			],
		];
	}

	/**
	 * Get donation receipt email body.
	 *
	 * @return string Email body in HTML format.
	 * @since 0.0.1
	 */
	private function get_donation_receipt_body() {
		ob_start();
		?>
		<p><strong><span style="font-size: 18px;"><?php esc_html_e( 'Thank You for Your Donation!', 'suredonation' ); ?></span></strong></p>
		<p><?php esc_html_e( 'Dear', 'suredonation' ); ?> {donor_name},</p>
		<p><?php esc_html_e( 'Thank you for your generous donation of', 'suredonation' ); ?> <strong>{amount}</strong> <?php esc_html_e( 'to', 'suredonation' ); ?> <strong>{campaign_name}</strong>.</p>
		<p><?php esc_html_e( 'Your support means the world to us and helps us continue our mission.', 'suredonation' ); ?></p>
		<p><strong><?php esc_html_e( 'Donation Details:', 'suredonation' ); ?></strong></p>
		<ul>
			<li><?php esc_html_e( 'Amount:', 'suredonation' ); ?> {amount}</li>
			<li><?php esc_html_e( 'Campaign:', 'suredonation' ); ?> {campaign_name}</li>
			<li><?php esc_html_e( 'Date:', 'suredonation' ); ?> {donation_date}</li>
			<li><?php esc_html_e( 'Transaction ID:', 'suredonation' ); ?> {transaction_id}</li>
		</ul>
		<p><?php esc_html_e( 'Best regards,', 'suredonation' ); ?><br />{site_title}</p>
		<?php
		$output = ob_get_clean();
		return trim( false !== $output ? $output : '' );
	}

	/**
	 * Get admin new donation email body.
	 *
	 * @return string Email body in HTML format.
	 * @since 0.0.1
	 */
	private function get_admin_new_donation_body() {
		ob_start();
		?>
		<p><strong><span style="font-size: 18px;"><?php esc_html_e( 'New Donation Received!', 'suredonation' ); ?></span></strong></p>
		<p><?php esc_html_e( 'A new donation has been received for your campaign.', 'suredonation' ); ?></p>
		<p><strong><?php esc_html_e( 'Donation Details:', 'suredonation' ); ?></strong></p>
		<ul>
			<li><?php esc_html_e( 'Donor:', 'suredonation' ); ?> {donor_name} ({donor_email})</li>
			<li><?php esc_html_e( 'Amount:', 'suredonation' ); ?> {amount}</li>
			<li><?php esc_html_e( 'Campaign:', 'suredonation' ); ?> {campaign_name}</li>
			<li><?php esc_html_e( 'Date:', 'suredonation' ); ?> {donation_date}</li>
			<li><?php esc_html_e( 'Transaction ID:', 'suredonation' ); ?> {transaction_id}</li>
		</ul>
		<?php
		$output = ob_get_clean();
		return trim( false !== $output ? $output : '' );
	}

	/**
	 * Get sample donation data for test emails.
	 *
	 * @return array<string, int|string> Sample data.
	 * @since 0.0.1
	 */
	private function get_sample_donation_data() {
		$currency        = Payment_Helper::get_currency();
		$currency_symbol = Payment_Helper::get_currency_symbol( $currency );
		$date_format     = get_option( 'date_format' );
		$admin_email     = get_option( 'admin_email' );

		return [
			'donor_name'     => __( 'John Doe', 'suredonation' ),
			'donor_email'    => 'john.doe@example.com',
			'amount'         => $currency_symbol . '50.00',
			'campaign_name'  => __( 'Sample Campaign', 'suredonation' ),
			'donation_date'  => current_time( is_string( $date_format ) ? $date_format : 'Y-m-d' ),
			'transaction_id' => 'pi_test_' . wp_generate_password( 16, false ),
			'site_title'     => get_bloginfo( 'name' ),
			'admin_email'    => is_string( $admin_email ) ? $admin_email : '',
			'site_url'       => home_url(),
			'admin_url'      => admin_url( 'admin.php?page=suredonation' ),
		];
	}

	/**
	 * Process smart tags for test emails.
	 *
	 * @param string                    $content     Content with smart tags.
	 * @param array<string, int|string> $sample_data Sample data for replacement.
	 * @return string Processed content.
	 * @since 0.0.1
	 */
	private function process_test_smart_tags( $content, $sample_data ) {
		$tags = [
			'{donor_name}'     => $sample_data['donor_name'],
			'{donor_email}'    => $sample_data['donor_email'],
			'{amount}'         => $sample_data['amount'],
			'{campaign_name}'  => $sample_data['campaign_name'],
			'{donation_date}'  => $sample_data['donation_date'],
			'{transaction_id}' => $sample_data['transaction_id'],
			'{site_title}'     => $sample_data['site_title'],
			'{admin_email}'    => $sample_data['admin_email'],
			'{site_url}'       => $sample_data['site_url'],
			'{admin_url}'      => $sample_data['admin_url'],
		];

		return str_replace( array_keys( $tags ), array_values( $tags ), $content );
	}

	/**
	 * Format test email body with HTML wrapper.
	 *
	 * @param string $body Email body content.
	 * @return string Formatted HTML email.
	 * @since 0.0.1
	 */
	private function format_test_email_body( $body ) {
		$email_template = Email_Template::get_instance();
		return $email_template->render( $body );
	}
}
