<?php

namespace CommerceBird\Admin\Actions\Ajax;

use CMBIRD_Auth_Zoho;
use CMBIRD_API_Handler_Zoho;
use CommerceBird\Admin\Actions\Sync\ZohoCRMSync;
use CommerceBird\Admin\Template;
use CommerceBird\Admin\Traits\AjaxRequest;
use CommerceBird\Admin\Traits\OptionStatus;
use CommerceBird\Admin\Traits\Singleton;
use CommerceBird\Admin\Traits\LogWriter;
use WC_Tax;
use Throwable;


if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
/**
 * Initializes the Zoho CRM class.
 *
 * @since 1.0.0
 * @return void
 */
final class ZohoCRMAjax {

	use Singleton;
	use AjaxRequest;
	use OptionStatus;
	use LogWriter;



	private const FORMS   = array(
		// 'connect' => array(.
		// 'token',.
		// ),.
		'product'                    => array(
			'importProducts',
		),
		'order'                      => array( 'range' ),
		'order_settings'             => array(
			'syncAsDeals',
		),
		'order_field_mapping'        => array(
			'dealFields',
		),
		'order_status_stage_mapping' => array(
			'mapping',
		),
		'customer'                   => array(
			'importCustomers',
		),
		'contact_settings'           => array(
			'syncCustomers',
			'syncOnRegistration',
			'syncOnUpdate',
		),
		'contact_layout'             => array(
			'layoutId',
		),
		'fields'                     => array(
			'form',
			'module',
		),
		'tax'                        => array(
			'selectedTaxRates',
		),
	);
	private const ACTIONS = array(
		'get_zcrm_connect'                 => 'connection_get',
		'save_zcrm_connect'                => 'connection_set',
		'reset_zcrm_connect'               => 'connection_reset',
		'is_zcrm_connected'                => 'connection_done',
		'import_zcrm_product'              => 'product_import',
		'map_zcrm_product'                 => 'product_map',
		'map_zcrm_customer'                => 'customer_map',
		'map_zcrm_order'                   => 'order_map',
		'export_zcrm_order'                => 'order_export',
		'get_zcrm_order_settings'          => 'order_settings_get',
		'save_zcrm_order_settings'         => 'order_settings_save',
		'get_zcrm_deal_fields'             => 'deal_fields_get',
		'get_zcrm_deal_field_mapping'      => 'deal_field_mapping_get',
		'save_zcrm_deal_field_mapping'     => 'deal_field_mapping_save',
		'get_wc_order_statuses'            => 'wc_order_statuses_get',
		'get_zcrm_deal_stages'             => 'deal_stages_get',
		'get_order_status_stage_mapping'   => 'order_status_stage_mapping_get',
		'save_order_status_stage_mapping'  => 'order_status_stage_mapping_save',
		'refresh_zcrm_fields'              => 'refresh_zcrm_fields',
		'zcrm_get_custom_fields'           => 'zcrm_get_custom_fields',
		'zcrm_save_custom_fields'          => 'zcrm_save_custom_fields',
		'zcrm_reset_custom_fields'         => 'zcrm_reset_custom_fields',
		'zcrm_fields'                      => 'get_zcrm_fields',
		'zcrm_handle_code'                 => 'handle_code',
		'get_zcrm_tax'                     => 'tax_get',
		'save_zcrm_tax'                    => 'tax_set',
		'reset_zcrm_tax'                   => 'tax_reset',
		'get_wc_taxes'                     => 'wc_tax_collect',
		'get_zcrm_taxes'                   => 'zoho_tax_rates_collect',
		'get_zcrm_layouts'                 => 'layouts_get',
		'save_zcrm_layout'                 => 'layout_save',
		'get_zcrm_selected_layout'         => 'layout_get_selected',
		'export_zcrm_contact'              => 'contact_export',
		'get_zcrm_contact_layouts'         => 'contact_layouts_get',
		'save_zcrm_contact_layout'         => 'contact_layout_save',
		'get_zcrm_selected_contact_layout' => 'contact_layout_get_selected',
	);
	private const OPTIONS = array(
		// 'connect' => array(.
		// 'token' => 'commercebird-exact-online-token',.
		// ),.
		'zcrm_sales_orders_fields' => 'zcrm_sales_orders_fields',
		'zcrm_contacts_fields'     => 'zcrm_contacts_fields',
		'zcrm_products_fields'     => 'zcrm_products_fields',
		'zcrm_sales_order_layout'  => 'zcrm_sales_order_layout',
		'zcrm_contact_layout'      => 'zcrm_contact_layout',
	);

	public function __construct() {
		$this->load_actions();
	}

	/**
	 * Sets the connection for the Zoho crm API.
	 */
	public function connection_set(): void {
		$this->verify(
			array(
				'account_domain',
				'client_id',
				'client_secret',
				'redirect_uri',
			),
		);
		try {
			$domain     = CMBIRD_Auth_Zoho::normalize_domain( $this->data['account_domain'] );
			$crm_url    = sprintf( 'https://www.zohoapis.%s/', $domain );
			$oauth_args = array(
				'response_type' => 'code',
				'client_id'     => $this->data['client_id'],
				'scope'         => 'ZohoCRM.users.ALL,ZohoCRM.bulk.ALL,ZohoCRM.modules.ALL,ZohoCRM.settings.ALL,ZohoCRM.org.ALL,profile.userphoto.READ,ZohoFiles.files.CREATE',
				'redirect_uri'  => $this->data['redirect_uri'],
				'prompt'        => 'consent',
				'access_type'   => 'offline',
				'state'         => wp_create_nonce( Template::NAME ),
			);

			update_option( 'cmbird_zoho_crm_domain', $domain );
			update_option( 'cmbird_zoho_crm_cid', $this->data['client_id'] );
			update_option( 'cmbird_zoho_crm_cs', $this->data['client_secret'] );
			update_option( 'cmbird_zoho_crm_url', $crm_url );
			update_option( 'cmbird_authorization_redirect_uri', $this->data['redirect_uri'] );
			$account_base   = CMBIRD_Auth_Zoho::get_accounts_base_url( $domain );
			$redirect       = esc_url_raw( add_query_arg( $oauth_args, $account_base . '/oauth/v2/auth' ) );
			$this->response = array(
				'redirect' => $redirect,
				'message'  => 'We are redirecting you to zoho. please wait...',
			);
		} catch ( Throwable $throwable ) {
			$this->errors = array( 'message' => $throwable->getMessage() );
		}

		$this->serve();
	}

	/**
	 * Retrieves the connection details.
	 *
	 * @return void
	 */
	public function connection_get(): void {
		$this->verify();
		$this->response['account_domain'] = get_option( 'cmbird_zoho_crm_domain', '' );
		$this->response['client_id']      = get_option( 'cmbird_zoho_crm_cid', '' );
		$this->response['client_secret']  = get_option( 'cmbird_zoho_crm_cs', '' );
		$this->response['crm_url']        = get_option( 'cmbird_zoho_crm_url', '' );
		$this->response['redirect_uri']   = get_option( 'cmbird_authorization_redirect_uri', '' );
		$this->serve();
	}

	/**
	 * Handles the oAuth code.
	 */
	public function handle_code(): void {
		$this->verify();
		if ( array_key_exists( 'code', $this->request ) ) {
			$class_functions = new CMBIRD_Auth_Zoho();
			$code            = $this->request['code'];
			$state           = $this->request['state'] ?? '';

			if ( empty( $state ) || ! wp_verify_nonce( $state, Template::NAME ) ) {
				$this->errors = array( 'message' => 'Invalid OAuth state. Please try connecting again.' );
				$this->serve();
				return;
			}

			try {
				$access_token = $class_functions->get_zoho_access_token( $code, 'zoho_crm' );
				if ( is_wp_error( $access_token ) ) {
					$this->errors = array( 'message' => $access_token->get_error_message() );
				} elseif ( is_array( $access_token ) && array_key_exists( 'access_token', $access_token ) ) {
					update_option( 'cmbird_zoho_crm_auth_code', $code );
					update_option( 'cmbird_zoho_crm_access_token', $access_token['access_token'] );
					update_option( 'cmbird_zoho_crm_refresh_token', $access_token['refresh_token'] );
					update_option( 'cmbird_zoho_crm_timestamp', strtotime( gmdate( 'Y-m-d H:i:s' ) ) + $access_token['expires_in'] );
					$this->response = (array) $access_token;
				} else {
					$this->errors = array( 'message' => 'Unable to retrieve Zoho CRM access token.' );
				}
			} catch ( Throwable $throwable ) {
				$this->errors = array( 'message' => $throwable->getMessage() );
			}
		}
		$this->serve();
	}

	/**
	 * Resets the connection by deleting specific options from the database.
	 */
	public function connection_reset(): void {
		$this->verify();
		try {
			$options = array(
				'cmbird_zoho_crm_domain',
				'cmbird_zoho_crm_cid',
				'cmbird_zoho_crm_cs',
				'cmbird_zoho_crm_url',
				'cmbird_zoho_crm_access_token',
			);
			foreach ( $options as $zi_option ) {
				delete_option( $zi_option );
			}
			$this->response = array( 'message' => 'Reset successfully!' );
		} catch ( Throwable $throwable ) {
			$this->errors = array( 'message' => $throwable->getMessage() );
		}

		$this->serve();
	}


	public function connection_done() {
		$this->verify();
		$zoho_crm_url             = get_option( 'cmbird_zoho_crm_url' );
		$url                      = $zoho_crm_url . 'crm/v7/org';
		$execute_curl_call_handle = new CMBIRD_API_Handler_Zoho();
		$json                     = $execute_curl_call_handle->execute_curl_call_get( $url );
		if ( is_wp_error( $json ) ) {
			$this->errors = array( 'message' => $json->get_error_message() );
		} elseif ( empty( $json ) ) {
			$this->errors = array( 'message' => 'We lost connection with zoho. please refresh page.' );
		} else {
			$this->response = ! empty( $json->org ) ? (array) $json->org[0] : array();
			// schedule a wp cron to refresh the token after one hour from now.
			if ( ! wp_next_scheduled( 'zcrm_refresh_token' ) ) {
				wp_schedule_event( time() + 3600, 'hourly', 'zcrm_refresh_token' );
			} else {
				// unschedule first and reschedule.
				wp_unschedule_event( wp_next_scheduled( 'zcrm_refresh_token' ), 'zcrm_refresh_token' );
				wp_schedule_event( time() + 3600, 'hourly', 'zcrm_refresh_token' );
			}
		}
		$this->serve();
	}

	/**
	 * Get Zoho CRM custom fields.
	 *
	 * @since 1.0.0
	 * @return void
	 */
	public function refresh_zcrm_fields() {
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Admin-only AJAX call, nonce verified in parent.
		$module = isset( $_GET['module'] ) ? sanitize_text_field( wp_unslash( $_GET['module'] ) ) : '';
		if ( empty( $module ) ) {
			$this->errors['message'] = 'Module name is required.';
		} else {
			$fields = ( new ZohoCRMSync() )->get_custom_fields( $module );
			if ( is_wp_error( $fields ) ) {
				$this->errors['message'] = $fields->get_error_message();
			} else {
				$option_name = 'zcrm_' . strtolower( $module ) . '_fields';
				update_option( self::OPTIONS[ $option_name ], $fields );
				$this->response           = array( 'message' => 'Refresh successfully!' );
				$this->response['fields'] = $fields;
			}
			$this->serve();
		}
	}

	/**
	 * Get Zoho CRM fields from WordPress database.
	 */
	public function get_zcrm_fields() {
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Admin-only AJAX call, nonce verified in parent.
		$module = isset( $_GET['module'] ) ? sanitize_text_field( wp_unslash( $_GET['module'] ) ) : '';
		if ( empty( $module ) ) {
			$this->errors['message'] = 'Module name is required.';
		} else {
			$fields                   = get_option( 'zcrm_' . strtolower( $module ) . '_fields', array() );
			$this->response['fields'] = $fields;
			$this->serve();
		}
	}

	/**
	 * Retrieves the fields and serves the response.
	 *
	 * @return object
	 */
	public function zcrm_get_custom_fields(): void {

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Admin-only AJAX call, nonce verified in parent.
		$module = isset( $_GET['module'] ) ? sanitize_text_field( wp_unslash( $_GET['module'] ) ) : '';

		if ( empty( $module ) ) {
			$this->errors['message'] = 'Module name is required.';
		} else {
			$this->verify();
			$option_name            = 'zcrm_' . strtolower( $module ) . '_custom_fields';
			$this->response['form'] = get_option( $option_name, array() );
			$this->serve();
		}
	}

	/**
	 * Sets the custom fields for the form.
	 *
	 * @return void
	 */
	public function zcrm_save_custom_fields(): void {
		$this->verify( self::FORMS['fields'] );
		$module = isset( $this->data['module'] ) ? $this->data['module'] : '';
		if ( empty( $module ) ) {
			$this->errors['message'] = 'Module name is required.';
		} else {
			try {
				$option_name = 'zcrm_' . strtolower( $module ) . '_custom_fields';
				update_option( $option_name, $this->data['form'] );
				$this->response = array( 'message' => 'saved' );
			} catch ( Throwable $throwable ) {
				$this->errors = array( 'message' => $throwable->getMessage() );
			}
			$this->serve();
		}
	}

	/**
	 * Resets the fields.
	 *
	 * @return void
	 */
	public function zcrm_reset_custom_fields(): void {
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Admin-only AJAX call, nonce verified in parent.
		$module = isset( $_GET['module'] ) ? sanitize_text_field( wp_unslash( $_GET['module'] ) ) : '';
		if ( empty( $module ) ) {
			$this->errors['message'] = 'Module name is required.';
		} else {
			$this->verify();
			$option_name = 'zcrm_' . strtolower( $module ) . '_custom_fields';
			delete_option( $option_name );
			$this->response = array( 'message' => 'Reset successfully!' );
			$this->serve();
		}
	}

	/**
	 * Export Orders to Zoho CRM.
	 *
	 * @param int $start_date_raw The start date.
	 * @param int $end_date_raw The end date.
	 */
	public function export_order( $start_date_raw, $end_date_raw ) {
		// $fd = fopen( __DIR__ . '/export_order.log', 'a+' );

		$start_date = gmdate( 'Y-m-d H:i:s', $start_date_raw );
		$end_date   = gmdate( 'Y-m-d H:i:s', $end_date_raw );
		// Define the order statuses to exclude.
		$exclude_statuses   = array( 'wc-failed', 'wc-cancelled', 'wc-checkout-draft' );
		$posts_per_page     = 20;
		$paged              = 1;
		$max_execution_time = ini_get( 'max_execution_time' );

		// Extend execution time for bulk operations.
		if ( $max_execution_time > 0 && $max_execution_time < 300 ) {
			set_time_limit( 300 ); // phpcs:ignore Squiz.PHP.DiscouragedFunctions.Discouraged -- Required for bulk order sync.

		}

		do {
			// Reset execution time for each batch to prevent timeout.
			if ( function_exists( 'set_time_limit' ) ) {
				set_time_limit( 60 ); // phpcs:ignore Squiz.PHP.DiscouragedFunctions.Discouraged -- Required for bulk order sync.
			}

			// Query to get orders.
			$args   = array(
				'date_created' => $start_date . '...' . $end_date,
				'status'       => array_diff( array_keys( wc_get_order_statuses() ), $exclude_statuses ),
				'limit'        => $posts_per_page,
				'paged'        => $paged,
				'orderby'      => 'date',
				'order'        => 'ASC',
				'return'       => 'ids',
				'meta_query'   => array(
					array(
						'key'     => 'zcrm_sales_order_id',
						'compare' => 'NOT EXISTS',
					),
				),
			);
			$orders = wc_get_orders( $args );
			// Loop through orders and schedule them for Zoho CRM sync.
			foreach ( $orders as $order_id ) {
				// Use WC Action Scheduler to sync the order to Zoho CRM.
				$existing_schedule = as_has_scheduled_action( 'sync_zcrm_order', array( $order_id ) );
				if ( ! $existing_schedule ) {
					as_schedule_single_action( time(), 'sync_zcrm_order', array( $order_id ) );
				}
			}

			// Check if we have more orders to process before cleanup.
			$has_more_orders = ! empty( $orders );

			// Memory management - clean up variables.
			unset( $orders, $args );

			// Optional: garbage collection to free memory.
			if ( function_exists( 'gc_collect_cycles' ) ) {
				gc_collect_cycles();
			}

			// Increment the offset for the next batch.
			++$paged;

			// Safety check to prevent infinite loops (max 1000 pages = 20,000 orders).
			if ( $paged > 1000 ) {
				break;
			}
		} while ( $has_more_orders );
		// fclose( $fd );
	}

	/**
	 * AJAX endpoint to export WooCommerce orders to Zoho CRM.
	 */
	public function order_export() {
		$this->verify( self::FORMS['order'] );
		if ( empty( $this->data ) || empty( $this->data['range'] ) ) {
			$this->response['success'] = false;
			$this->response['message'] = __( 'Select dates', 'commercebird' );
			$this->serve();
		}
		// Set the date range to last 30 days.
		$start_date            = strtotime( $this->data['range'][0] );
		$end_date              = strtotime( $this->data['range'][1] );
		$zoho_crm_access_token = get_option( 'cmbird_zoho_crm_access_token' );
		if ( empty( $zoho_crm_access_token ) ) {
			$this->response['success'] = false;
			$this->response['message'] = __( 'Zoho CRM is not Connected.', 'commercebird' );
			$this->serve();
		}
		$this->export_order( $start_date, $end_date );
		$this->response['success'] = true;
		$this->response['message'] = __( 'Exported', 'commercebird' );
		$this->serve();
	}

	/**
	 * Retrieves an array of all tax rates from WooCommerce.
	 *
	 * @return array An array of all tax rates.
	 */
	public function wc_taxes(): array {
		$wc_tax_array = array();
		$tax_classes  = WC_Tax::get_tax_classes(); // Retrieve all tax classes.
		if ( ! in_array( '', $tax_classes ) ) { // Make sure "Standard rate" (empty class name) is present.
			array_unshift( $tax_classes, '' );
		}

		foreach ( $tax_classes as $tax_class ) { // For each tax class, get all rates.
			$taxes = WC_Tax::get_rates_for_tax_class( $tax_class );

			foreach ( $taxes as $key => $tax ) {
				$taxarray       = (array) $tax;
				$taxarray['id'] = $key;
				$wc_tax_array[] = $taxarray;
			}
		}

		return $wc_tax_array;
	}
	/**
	 * Executes the wc_tax_collect function.
	 *
	 * This function verifies the current state, retrieves the taxes using the
	 * wc_taxes method, and serves the response.
	 */
	public function wc_tax_collect(): void {
		$this->verify();
		$this->response = $this->wc_taxes();
		$this->serve();
	}

	/**
	 * Retrieves the tax information.
	 *
	 * @return void
	 */
	public function tax_get(): void {
		$this->verify();
		$this->response = array();
		foreach ( $this->wc_taxes() as $tax ) {
			$this->response['selectedTaxRates'][] = $tax['id'] . '^^' . get_option( 'cmbird_zoho_crm_tax_rate_' . $tax['id'] );
		}
		$this->serve();
	}


	/**
	 * Saves tax rates to the database.
	 */
	public function tax_set(): void {
		$this->verify( self::FORMS['tax'] );
		$rates = array_filter( $this->data['selectedTaxRates'] );
		try {
			foreach ( $rates as $value ) {
				$valarray = explode( '^^', $value );
				update_option( 'cmbird_zoho_crm_tax_rate_' . $valarray[0], $valarray[1] );
			}
			$this->response = array( 'message' => 'Saved' );
		} catch ( Throwable $throwable ) {
			$this->errors = array( 'message' => $throwable->getMessage() );
		}

		$this->serve();
	}

	/**
	 * Resets the tax settings.
	 *
	 * This function verifies the tax settings and then deletes the options
	 * related to the tax rates
	 *
	 * @return void
	 */
	public function tax_reset(): void {
		$this->verify();
		foreach ( $this->wc_taxes() as $tax ) {
			delete_option( 'cmbird_zoho_crm_tax_rate_' . $tax['id'] );
		}
		$this->response = array( 'message' => 'Reset successfully!' );
		$this->serve();
	}

	/**
	 * Retrieves the Zoho tax rates for the organization.
	 *
	 * This function verifies the request, retrieves the organization ID and URL
	 * from the options, constructs the URL for the API request, and executes
	 * the cURL call to fetch the tax rates. If the response contains the
	 * 'taxes' key, it sets the response to the tax rates. Otherwise, it sets
	 * the errors to a default message.
	 */
	public function zoho_tax_rates_collect(): void {
		$this->verify();
		$zoho_crm_url = get_option( 'cmbird_zoho_crm_url' );
		$url          = $zoho_crm_url . 'crm/v7/org/taxes';
		try {
			$execute_curl_call_handle = new CMBIRD_API_Handler_Zoho();
			$json                     = (array) $execute_curl_call_handle->execute_curl_call_get( $url );

			// error_log('Data: ' . print_r($response, true));
			if (
				is_array( $json ) &&
				isset( $json['org_taxes'] ) &&
				isset( $json['org_taxes']->taxes )
			) {
				$this->response = $json['org_taxes']->taxes;
			} else {
				$this->errors = array( 'message' => 'Something went wrong!' );
			}
		} catch ( Throwable $throwable ) {
			$this->errors = array( 'message' => $throwable->getMessage() );
		}
		$this->serve();
	}

	/**
	 * Get Zoho CRM Sales Order layouts.
	 */
	public function layouts_get(): void {
		$this->verify();
		$zoho_crm_url = get_option( 'cmbird_zoho_crm_url' );
		$url          = $zoho_crm_url . 'crm/v7/settings/layouts?module=Sales_Orders';
		try {
			$execute_curl_call_handle = new CMBIRD_API_Handler_Zoho();
			$json                     = (array) $execute_curl_call_handle->execute_curl_call_get( $url );

			if (
				is_array( $json ) &&
				isset( $json['layouts'] ) &&
				is_array( $json['layouts'] )
			) {
				// Format the layouts for frontend dropdown.
				$formatted_layouts = array();
				foreach ( $json['layouts'] as $layout ) {
					if ( isset( $layout->id ) && isset( $layout->name ) ) {
						$formatted_layouts[] = array(
							'id'       => $layout->id,
							'name'     => $layout->name,
							'api_name' => $layout->api_name ?? '',
							'status'   => $layout->status ?? '',
						);
					}
				}
				$this->response = $formatted_layouts;
			} else {
				$this->errors = array( 'message' => 'Unable to fetch layouts!' );
			}
		} catch ( Throwable $throwable ) {
			$this->errors = array( 'message' => $throwable->getMessage() );
		}
		$this->serve();
	}

	/**
	 * Save selected Zoho CRM Sales Order layout.
	 */
	public function layout_save(): void {
		$this->verify( array( 'layout_id' ) );
		if ( empty( $this->data['layout_id'] ) ) {
			$this->errors = array( 'message' => 'Layout ID is required!' );
			$this->serve();
			return;
		}

		$updated = update_option( self::OPTIONS['zcrm_sales_order_layout'], sanitize_text_field( $this->data['layout_id'] ) );

		if ( $updated ) {
			$this->response = array( 'message' => 'Layout saved successfully!' );
		} else {
			$this->errors = array( 'message' => 'Failed to save layout!' );
		}
		$this->serve();
	}

	/**
	 * Get selected Zoho CRM Sales Order layout.
	 */
	public function layout_get_selected(): void {
		$this->verify();
		$saved_layout   = get_option( self::OPTIONS['zcrm_sales_order_layout'], '' );
		$this->response = array( 'selected_layout' => $saved_layout );
		$this->serve();
	}

	/**
	 * Get order settings for Zoho CRM sync.
	 */
	public function order_settings_get(): void {
		$this->verify();
		$sync_as_deals  = get_option( 'cmbird_zcrm_sync_as_deals', false );
		$this->response = array( 'syncAsDeals' => (bool) $sync_as_deals );
		$this->serve();
	}

	/**
	 * Save order settings for Zoho CRM sync.
	 */
	public function order_settings_save(): void {
		$this->verify( self::FORMS['order_settings'] );
		try {
			$sync_as_deals = isset( $this->data['syncAsDeals'] ) ? (bool) $this->data['syncAsDeals'] : false;
			update_option( 'cmbird_zcrm_sync_as_deals', $sync_as_deals );
			$this->response = array(
				'success' => true,
				'message' => __( 'Order settings saved successfully!', 'commercebird' ),
			);
		} catch ( Throwable $throwable ) {
			$this->errors = array( 'message' => $throwable->getMessage() );
		}
		$this->serve();
	}

	/**
	 * Get Zoho CRM Deals fields.
	 */
	public function deal_fields_get(): void {
		$this->verify();
		$refresh = isset( $this->data['refresh'] ) && $this->data['refresh'];

		$fields = get_option( 'zcrm_deals_fields', array() );

		// If refresh is requested or no fields exist, try to refresh them from Zoho.
		if ( $refresh || empty( $fields ) ) {
			$sync         = new ZohoCRMSync();
			$fresh_fields = $sync->get_all_fields( 'Deals' );
			if ( ! is_wp_error( $fresh_fields ) ) {
				// Convert to simple key-value format, excluding hardcoded fields.
				$formatted_fields = array();
				foreach ( $fresh_fields as $field_key => $field_label ) {
					// Skip hardcoded fields (Deal_Name, Amount, Currency).
					if ( in_array( $field_key, array( 'Deal_Name', 'Amount', 'Currency' ) ) ) {
						continue;
					}
					$formatted_fields[ $field_key ] = $field_label;
				}

				// Add empty option at the beginning.
				$formatted_fields = array_merge( array( '' => 'Select a field...' ), $formatted_fields );

				update_option( 'zcrm_deals_fields', $formatted_fields );
				$fields = $formatted_fields;
			}
		} else {
			// Ensure empty option exists.
			if ( ! isset( $fields[''] ) ) {
				$fields = array_merge( array( '' => 'Select a field...' ), $fields );
			}
		}

		$this->response = array( 'fields' => $fields );
		$this->serve();
	}

	/**
	 * Get deal field mapping settings.
	 */
	public function deal_field_mapping_get(): void {
		$this->verify();
		$mapping        = get_option( 'cmbird_zcrm_deal_field_mapping', array() );
		$this->response = array( 'dealFields' => $mapping );
		$this->serve();
	}

	/**
	 * Save deal field mapping settings.
	 */
	public function deal_field_mapping_save(): void {
		$this->verify( self::FORMS['order_field_mapping'] );
		try {
			$deal_fields = isset( $this->data['dealFields'] ) ? $this->data['dealFields'] : array();
			update_option( 'cmbird_zcrm_deal_field_mapping', $deal_fields );
			$this->response = array(
				'success' => true,
				'message' => __( 'Deal field mapping saved successfully!', 'commercebird' ),
			);
		} catch ( Throwable $throwable ) {
			$this->errors = array( 'message' => $throwable->getMessage() );
		}
		$this->serve();
	}

	/**
	 * Get WooCommerce order statuses.
	 */
	public function wc_order_statuses_get(): void {
		$this->verify();
		$order_statuses     = wc_get_order_statuses();
		$formatted_statuses = array();

		// Add empty option.
		$formatted_statuses[''] = 'Select order status...';

		foreach ( $order_statuses as $status_key => $status_label ) {
			$formatted_statuses[ $status_key ] = $status_label;
		}

		$this->response = array( 'statuses' => $formatted_statuses );
		$this->serve();
	}

	/**
	 * Get Zoho Deal stages.
	 */
	public function deal_stages_get(): void {
		$this->verify();
		$cached_stages = get_option( 'zcrm_deal_stages', array() );

		// Check if we have cached stages and they're not empty.
		if ( ! empty( $cached_stages ) && is_array( $cached_stages ) && count( $cached_stages ) > 1 ) {
			$this->response = array( 'stages' => $cached_stages );
			$this->serve();
			return;
		}

		try {
			// Directly get the Stage field pick list values without calling get_all_fields.
			$zoho_crm_url             = get_option( 'cmbird_zoho_crm_url' );
			$url                      = $zoho_crm_url . 'crm/v7/settings/fields?module=Deals';
			$execute_curl_call_handle = new CMBIRD_API_Handler_Zoho();
			$json                     = $execute_curl_call_handle->execute_curl_call_get( $url );

			$stage_options = array( '' => 'Select stage...' );

			if ( ! is_wp_error( $json ) && ! empty( $json->fields ) ) {
				foreach ( $json->fields as $field ) {
					if ( $field->api_name === 'Stage' && ! empty( $field->pick_list_values ) ) {
						foreach ( $field->pick_list_values as $option ) {
							$stage_options[ $option->actual_value ] = $option->display_value;
						}
						break;
					}
				}
			}

			// Cache the stages.
			update_option( 'zcrm_deal_stages', $stage_options );
			$this->response = array( 'stages' => $stage_options );
		} catch ( \Exception $e ) {
			$this->response = array( 'stages' => array( '' => 'Select stage...' ) );
		}

		$this->serve();
	}

	/**
	 * Get order status to stage mapping settings.
	 */
	public function order_status_stage_mapping_get(): void {
		$this->verify();
		$mapping        = get_option( 'cmbird_zcrm_order_status_stage_mapping', array() );
		$this->response = array( 'mapping' => $mapping );
		$this->serve();
	}

	/**
	 * Save order status to stage mapping settings.
	 */
	public function order_status_stage_mapping_save(): void {
		$this->verify( self::FORMS['order_status_stage_mapping'] );
		try {
			$mapping = isset( $this->data['mapping'] ) ? $this->data['mapping'] : array();
			update_option( 'cmbird_zcrm_order_status_stage_mapping', $mapping );
			$this->response = array(
				'success' => true,
				'message' => __( 'Order status to stage mapping saved successfully!', 'commercebird' ),
			);
		} catch ( Throwable $throwable ) {
			$this->errors = array( 'message' => $throwable->getMessage() );
		}
		$this->serve();
	}

	/**
	 * Export all existing WooCommerce customers to Zoho CRM as contacts.
	 */
	public function contact_export(): void {
		$this->verify();

		$zoho_crm_access_token = get_option( 'cmbird_zoho_crm_access_token' );
		if ( empty( $zoho_crm_access_token ) ) {
			$this->response['success'] = false;
			$this->response['message'] = __( 'Zoho CRM is not Connected.', 'commercebird' );
			$this->serve();
		}

		try {
			// Get all customers in batches.
			$posts_per_page = 20;
			$paged          = 1;
			$total_exported = 0;

			do {
				$customers = get_users(
					array(
						'role'    => 'customer',
						'number'  => $posts_per_page,
						'paged'   => $paged,
						'fields'  => 'ID',
						'orderby' => 'registered',
						'order'   => 'ASC',
					)
				);

				// Loop through customers and schedule them for Zoho CRM sync.
				foreach ( $customers as $customer_id ) {
					// Use WC Action Scheduler to sync the customer to Zoho CRM.
					$existing_schedule = as_has_scheduled_action( 'sync_zcrm_contact', array( $customer_id ) );
					if ( ! $existing_schedule ) {
						as_schedule_single_action( time(), 'sync_zcrm_contact', array( $customer_id ) );
						++$total_exported;
					}
				}

				// Increment the page for the next batch.
				++$paged;
			} while ( ! empty( $customers ) );

			$this->response = array(
				'success' => true,
				'message' => sprintf(
					/* translators: %d: number of customers */
					__( '%d customers scheduled for export to Zoho CRM.', 'commercebird' ),
					$total_exported
				),
			);

		} catch ( Throwable $throwable ) {
			$this->errors = array( 'message' => $throwable->getMessage() );
		}

		$this->serve();
	}

	/**
	 * Get Zoho CRM Contact layouts.
	 */
	public function contact_layouts_get(): void {
		$this->verify();
		$zoho_crm_url = get_option( 'cmbird_zoho_crm_url' );
		$url          = $zoho_crm_url . 'crm/v7/settings/layouts?module=Contacts';

		try {
			$execute_curl_call_handle = new CMBIRD_API_Handler_Zoho();
			$json                     = (array) $execute_curl_call_handle->execute_curl_call_get( $url );

			if (
				is_array( $json ) &&
				isset( $json['layouts'] ) &&
				is_array( $json['layouts'] )
			) {
				// Format the layouts for frontend dropdown.
				$formatted_layouts = array();
				foreach ( $json['layouts'] as $layout ) {
					if ( isset( $layout->id ) && isset( $layout->name ) ) {
						$formatted_layouts[] = array(
							'id'       => $layout->id,
							'name'     => $layout->name,
							'api_name' => $layout->api_name ?? '',
							'status'   => $layout->status ?? '',
						);
					}
				}
				$this->response = array( 'layouts' => $formatted_layouts );
			} else {
				$this->errors = array( 'message' => 'Unable to fetch contact layouts!' );
			}
		} catch ( Throwable $throwable ) {
			$this->errors = array( 'message' => $throwable->getMessage() );
		}
		$this->serve();
	}

	/**
	 * Save selected Zoho CRM Contact layout.
	 */
	public function contact_layout_save(): void {
		$this->verify( self::FORMS['contact_layout'] );

		if ( empty( $this->data['layoutId'] ) ) {
			$this->errors = array( 'message' => 'Contact Layout ID is required!' );
			$this->serve();
			return;
		}

		$updated = update_option( self::OPTIONS['zcrm_contact_layout'], sanitize_text_field( $this->data['layoutId'] ) );

		if ( false !== $updated ) {
			$this->response = array( 'message' => 'Contact layout saved successfully!' );
		} else {
			$this->errors = array( 'message' => 'Failed to save contact layout!' );
		}
		$this->serve();
	}

	/**
	 * Get selected Zoho CRM Contact layout.
	 */
	public function contact_layout_get_selected(): void {
		$this->verify();
		$saved_layout   = get_option( self::OPTIONS['zcrm_contact_layout'], '' );
		$this->response = array( 'selectedLayout' => $saved_layout );
		$this->serve();
	}
}
