<?php
/**
 * Class EmailController
 *
 * This class handles all the email-related API endpoints, serving as a controller for managing emails
 * in the application. It provides methods to retrieve, update, and manipulate email settings and data.
 */

namespace RadiusTheme\RadiusBooking\Controllers;

use RadiusTheme\RadiusBooking\Core\Api\ApiResponse;
use RadiusTheme\RadiusBooking\Emails\EmailManager;
use RadiusTheme\RadiusBooking\Helpers\SettingsHelper;
use WP_REST_Request;
use RadiusTheme\RadiusBooking\Abstracts\BaseController;
use RadiusTheme\RadiusBooking\Repositories\EmailRepository;
use RadiusTheme\RadiusBooking\Resources\EmailResource;
if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly
}

/**
 * Api/Controllers/EmailController.php
 * Email API controller
 */
class EmailController extends BaseController {

	/**
	 * Constructor method for initializing the class with a new EmailRepository instance.
	 *
	 * @return void
	 */
	public function __construct() {
		parent::__construct( new EmailRepository() );
	}

	/**
	 * Transforms the given item into a specific format using the EmailResource.
	 *
	 * @param mixed $item The item to be transformed.
	 *
	 * @return array The transformed representation of the item.
	 */
	protected function transformItem( $item ): array {
		return ( new EmailResource() )->transform( $item );
	}

	/**
	 * Transforms a collection of items into a collection of email resources.
	 *
	 * @param array $items The array of items to be transformed.
	 *
	 * @return array The transformed collection of email resources.
	 */
	protected function transformCollection( array $items ): array {
		return EmailResource::collection( $items );
	}

	/**
	 * Retrieves the validation rules based on the given request and context.
	 *
	 * @param mixed $request The request data to validate.
	 * @param string $context The context in which the validation rules are applied, such as 'create' or 'update'. Default is 'create'.
	 *
	 * @return array An array of validation rules.
	 */
	protected function getValidationRules( $request, string $context = 'create' ): array {
		$rules = array();

		return $rules;
	}

	/**
	 * Retrieves the resource type for this controller.
	 *
	 * @return string The resource type, which is 'user' in this case.
	 */
	protected function getResourceType(): string {
		return 'email';
	}

	/**
	 * Handles the retrieval of emails by processing the given request
	 * and applying necessary middleware.
	 *
	 * @param WP_REST_Request $request The REST request object containing request parameters.
	 *
	 * @return mixed The processed response containing email data.
	 */
	public function get_emails( WP_REST_Request $request ) {
		return $this->applyMiddleware(
			$request,
			function () {
				$email_classes = $this->get_email_classes();
				$emails        = array();

				foreach ( $email_classes as $email_class ) {
					if ( class_exists( $email_class ) ) {
						$email    = new $email_class();
						$emails[] = $this->transform_email_to_array( $email );
					}
				}

				return ApiResponse::success( $emails )->send();
			}
		);
	}

	/**
	 * Handles the retrieval of an email based on the provided email ID.
	 *
	 * @param WP_REST_Request $request The REST request containing the parameters for the email lookup.
	 *
	 * @return void|array The response is sent directly using the ApiResponse utility.
	 */
	public function get_email( WP_REST_Request $request ) {
		return $this->applyMiddleware(
			$request,
			function ( $request ) {
				$email_id = $request->get_param( 'email_id' );

				if ( empty( $email_id ) ) {
					return ApiResponse::error( 'Invalid Email ID', 400 )->send();
				}

				$email = $this->find_email_by_id( $email_id );

				if ( ! $email ) {
					return ApiResponse::error( 'Email not found', 404 )->send();
				}

				$data = $this->transform_email_to_array( $email, true );

				return ApiResponse::success( $data )->send();
			}
		);
	}

	/**
	 * Updates the email settings for a specific email record.
	 *
	 * @param WP_REST_Request $request The REST request object containing the email ID and new settings data.
	 *
	 * @return mixed The API response indicating the success or failure of the email settings update.
	 */
	public function update_email_settings( WP_REST_Request $request ) {
		return $this->applyMiddleware(
			$request,
			function ( $request ) {
				$email_id = $request->get_param( 'email_id' );
				$settings = $request->get_json_params();

				if ( empty( $email_id ) ) {
					return ApiResponse::error( 'Invalid Email ID', 400 )->send();
				}

				$email = $this->find_email_by_id( $email_id );

				if ( ! $email ) {
					return ApiResponse::error( 'Email not found', 404 )->send();
				}

				// Validate and map settings
				$updated_settings = $this->map_frontend_to_backend_settings( $settings );

				// Save settings
				$result = $email->update_settings( $updated_settings );

				if ( ! $result ) {
					return ApiResponse::error( 'Failed to update email settings', 500 )->send();
				}

				return ApiResponse::success(
					$this->transform_email_to_array( $email ),
					__( 'Email settings updated successfully', 'radius-booking' )
				)->send();
			}
		);
	}

	/**
	 * Retrieves the email classes using the EmailManager.
	 *
	 * @return array The list of email classes provided by the EmailManager.
	 */
	private function get_email_classes() {
		$emails_manager = new EmailManager();
		return $emails_manager->get_email_classes();
	}

	/**
	 * Finds and retrieves an email instance by its ID.
	 *
	 * @param mixed $email_id The ID of the email to find.
	 *
	 * @return object|null The email instance if found, or null if no matching email is found.
	 */
	private function find_email_by_id( $email_id ) {
		$email_classes = $this->get_email_classes();

		foreach ( $email_classes as $email_class ) {
			if ( class_exists( $email_class ) ) {
				$email = new $email_class();

				if ( $email->get_id() === $email_id ) {
					return $email;
				}
			}
		}

		return null;
	}

	/**
	 * Helper: Transform email object to array
	 *
	 * @param object $email Email instance
	 * @param bool $include_extra Include extra fields (description, tooltip, etc.)
	 * @return array
	 */
	private function transform_email_to_array( $email, $include_extra = false ) {
		$settings = $email->get_settings();

		$data = array(
			'id'                 => $email->get_id(),
			'name'               => $email->title,
			'type'               => $email->recipient_type,
			'event'              => $email->get_trigger_action(),
			'status'             => $email->status,
			'subject'            => $settings['subject'] ?? '',
			'heading'            => $settings['heading'] ?? '',
			'additional_content' => $settings['additional_content'] ?? '',
			'footer_text'        => $settings['footer_text'] ?? '',
			'button_text'        => $settings['button_text'] ?? '',
			'button_url'         => $settings['button_url'] ?? '',
			'enabled'            => $settings['enabled'] ?? false,
			'cc_staff'           => $settings['cc_staff'] ?? false,
			'bcc_emails'         => $settings['bcc_emails'] ?? array(),
			'use_queue'          => $settings['use_queue'] ?? false,
			'send_reminder'      => $settings['send_reminder'] ?? false,
			'reminder_minutes'   => $settings['reminder_minutes'] ?? 30,
			'reminder_times'     => $settings['reminder_times'] ?? array(),
			'business_settings'  => SettingsHelper::get_setting( 'business' ) ?? array(),

		);

		// Add extra fields for single email view
		if ( $include_extra ) {
			$data['description'] = $email->description ?? '';
			$data['tooltip']     = $email->tooltip ?? '';
			$data['attachments'] = $settings['attachments'] ?? array();
		}

		return $data;
	}

	/**
	 * Helper: Map frontend settings to backend format
	 *
	 * @param array $settings Frontend settings
	 * @return array Backend settings
	 */
	private function map_frontend_to_backend_settings( $settings ) {
		return array(
			'enabled'            => $settings['enabled'] ?? $settings['is_active'] ?? true,
			'subject'            => sanitize_text_field( $settings['subject'] ?? '' ),
			'heading'            => sanitize_text_field( $settings['heading'] ?? '' ),
			'additional_content' => wp_kses_post( $settings['additional_content'] ?? $settings['content'] ?? '' ),
			'footer_text'        => sanitize_text_field( $settings['footer_text'] ?? '' ),
			'button_text'        => sanitize_text_field( $settings['button_text'] ?? '' ),
			'button_url'         => esc_url_raw( $settings['button_url'] ?? '' ),
			'cc_staff'           => (bool) ( $settings['cc_staff'] ?? false ),
			'bcc_emails'         => $this->sanitize_email_array( $settings['bcc_emails'] ?? array() ),
			'use_queue'          => (bool) ( $settings['use_queue'] ?? false ),
			'send_reminder'      => (bool) ( $settings['send_reminder'] ?? false ),
			'reminder_minutes'   => absint( $settings['reminder_minutes'] ?? 30 ),
			'reminder_times'     => array_map( 'absint', $settings['reminder_times'] ?? array() ),
			'attachments'        => $settings['attachments'] ?? array(),
		);
	}

	/**
	 * Sanitizes an array of email addresses, ensuring each entry is valid.
	 *
	 * @param array|string $emails Input data that should be an array of email addresses. If not an array, an empty array is returned.
	 *
	 * @return array An array of sanitized email addresses, containing only valid emails.
	 */
	private function sanitize_email_array( $emails ) {
		if ( ! is_array( $emails ) ) {
			return array();
		}

		return array_filter(
			array_map( 'sanitize_email', $emails ),
			function ( $email ) {
				return is_email( $email );
			}
		);
	}
}
