<?php

namespace CommerceBird\Admin\Actions\Sync;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use CMBIRD_API_Handler_Zoho;
use CMBIRD_Auth_Zoho;
use WP_Error;

/**
 * Handles synchronization actions with Zoho CRM, including fetching fields and refreshing tokens.
 */
class ZohoCRMSync {

	/*
	create API Get call to Zoho CRM to get all custom fields
	 *
	 * @param module $module - module name
	 * @return array | \WP_Error
	 */
	public static function get_custom_fields( $module ) {
		$zoho_crm_url             = get_option( 'cmbird_zoho_crm_url' );
		$url                      = $zoho_crm_url . 'crm/v7/settings/fields?module=' . $module;
		$execute_curl_call_handle = new CMBIRD_API_Handler_Zoho();
		$json                     = $execute_curl_call_handle->execute_curl_call_get( $url );
		if ( is_wp_error( $json ) ) {
			return $json;
		} else {
			// Parse the response.
			$parsed_fields = array();

			foreach ( $json->fields as $field ) {
				if (
					! empty( $field->custom_field ) &&
					( empty( $field->read_only ) || $field->read_only === false )
				) {
					$parsed_fields[] = array(
						'id'           => $field->id,
						'apiName'      => $field->api_name,
						'visible'      => (bool) $field->visible,
						'fieldLabel'   => $field->field_label,
						'displayLabel' => $field->display_label,
						'customField'  => true,
						'dataType'     => $field->data_type,
					);
				}
			}

			return $parsed_fields;
		}
	}

	/*
	create API Get call to Zoho CRM to get ALL fields (standard + custom)
	 *
	 * @param module $module - module name
	 * @return array | \WP_Error
	 */
	public static function get_all_fields( $module ) {
		$zoho_crm_url             = get_option( 'cmbird_zoho_crm_url' );
		$url                      = $zoho_crm_url . 'crm/v7/settings/fields?module=' . $module;
		$execute_curl_call_handle = new CMBIRD_API_Handler_Zoho();
		$json                     = $execute_curl_call_handle->execute_curl_call_get( $url );
		if ( is_wp_error( $json ) ) {
			return $json;
		} else {
			// Parse the response to get ALL fields (both standard and custom).
			$parsed_fields = array();

			// Fields to exclude for Deals module.
			$excluded_fields = array( 'Account_Name', 'Contact_Name', 'Stage' );

			foreach ( $json->fields as $field ) {
				// Include all fields that are not read-only and are visible.
				// For Deals module, also exclude Account Name, Contact Name and Stage.
				if ( ( empty( $field->read_only ) || $field->read_only === false ) && $field->visible ) {
					// Skip excluded fields for Deals module.
					if ( 'Deals' === $module && in_array( $field->api_name, $excluded_fields ) ) {
						continue;
					}
					$parsed_fields[ $field->api_name ] = $field->field_label;
				}
			}

			return $parsed_fields;
		}
	}

	/**
	 * Refresh the access token of Zoho CRM.
	 *
	 * @since 1.0.0
	 * @return void | \WP_Error
	 */
	public static function refresh_token() {
		// return if there is no access token.
		if ( empty( get_option( 'cmbird_zoho_crm_access_token' ) ) ) {
			return;
		}
		$zoho_refresh_token = get_option( 'cmbird_zoho_crm_refresh_token' );
		$zoho_timestamp     = get_option( 'cmbird_zoho_crm_timestamp' );
		$current_time       = strtotime( gmdate( 'Y-m-d H:i:s' ) );
		if ( $zoho_timestamp < $current_time ) {
			$handlefunction = new CMBIRD_Auth_Zoho();
			$respo_at_js    = $handlefunction->get_zoho_refresh_token( $zoho_refresh_token, 'zoho_crm' );

			if ( is_wp_error( $respo_at_js ) ) {
				return $respo_at_js;
			}

			$access_token = '';
			$expires_in   = 0;

			if ( is_array( $respo_at_js ) ) {
				$access_token = isset( $respo_at_js['access_token'] ) ? (string) $respo_at_js['access_token'] : '';
				$expires_in   = isset( $respo_at_js['expires_in'] ) ? (int) $respo_at_js['expires_in'] : 0;
			} elseif ( is_object( $respo_at_js ) ) {
				$access_token = isset( $respo_at_js->access_token ) ? (string) $respo_at_js->access_token : '';
				$expires_in   = isset( $respo_at_js->expires_in ) ? (int) $respo_at_js->expires_in : 0;
			}

			if ( '' === $access_token ) {
				return new WP_Error( 403, 'Access denied!' );
			}

			update_option( 'cmbird_zoho_crm_access_token', $access_token );
			update_option( 'cmbird_zoho_crm_timestamp', strtotime( gmdate( 'Y-m-d H:i:s' ) ) + $expires_in );
		}
	}

	/**
	 * Sync a WooCommerce customer to Zoho CRM as a contact.
	 *
	 * Called via Action Scheduler.
	 *
	 * @param int $customer_id The customer ID to sync.
	 *
	 * @return void
	 */
	public static function cmbird_zcrm_contact_sync( $customer_id ) {
		// Refresh token before making API calls.
		$token_refresh_result = self::refresh_token();
		if ( is_wp_error( $token_refresh_result ) ) {
			( 'Zoho CRM Contact Sync: Token refresh failed for customer ID ' . $customer_id . ': ' . $token_refresh_result->get_error_message() );
			return;
		}

		$customer = get_user_by( 'id', $customer_id );
		if ( ! $customer ) {
			( 'Zoho CRM Contact Sync: Customer not found with ID ' . $customer_id );
			return;
		}

		// Get billing address data.
		$billing_address_1 = get_user_meta( $customer_id, 'billing_address_1', true );
		$billing_address_2 = get_user_meta( $customer_id, 'billing_address_2', true );
		$mailing_street    = trim( $billing_address_1 . ' ' . $billing_address_2 );

		// Format customer data to match Zoho CRM contact fields.
		$contact_data = array(
			'First_Name' => ! empty( $customer->first_name ) ? $customer->first_name : '',
			'Last_Name'  => ! empty( $customer->last_name ) ? $customer->last_name : ( ! empty( $customer->display_name ) ? $customer->display_name : 'Customer' ),
			'Email'      => $customer->user_email,
		);

		// Add optional fields only if they have values.
		$optional_fields = array(
			'Phone'           => get_user_meta( $customer_id, 'billing_phone', true ),
			'Mobile'          => get_user_meta( $customer_id, 'billing_phone', true ),
			'Mailing_Street'  => $mailing_street,
			'Mailing_City'    => get_user_meta( $customer_id, 'billing_city', true ),
			'Mailing_State'   => get_user_meta( $customer_id, 'billing_state', true ),
			'Mailing_Zip'     => get_user_meta( $customer_id, 'billing_postcode', true ),
			'Mailing_Country' => get_user_meta( $customer_id, 'billing_country', true ),
		);

		foreach ( $optional_fields as $field => $value ) {
			if ( ! empty( $value ) ) {
				$contact_data[ $field ] = $value;
			}
		}

		// Add description with customer ID.
		$contact_data['Description'] = 'WooCommerce Customer ID: ' . $customer_id;

		// Apply selected contact layout if available.
		$selected_layout = get_option( 'zcrm_contact_layout', '' );
		if ( ! empty( $selected_layout ) ) {
			$contact_data['Layout'] = array( 'id' => $selected_layout );
		}

		$zoho_crm_url = get_option( 'cmbird_zoho_crm_url' );
		if ( empty( $zoho_crm_url ) ) {
			( 'Zoho CRM Contact Sync: Zoho CRM URL not configured for customer ID ' . $customer_id );
			return;
		}

		$execute_curl_call_handle = new CMBIRD_API_Handler_Zoho();

		// Check if customer already has a Zoho CRM contact ID stored.
		$existing_contact_id = get_user_meta( $customer_id, 'zcrm_contact_id', true );

		// Prepare data in Zoho CRM format.
		$zoho_data = array( 'data' => array( $contact_data ) );

		if ( ! empty( $existing_contact_id ) ) {
			// Customer already has a Zoho CRM contact ID, update the existing contact.
			$contact_id = $existing_contact_id;

			$update_url    = $zoho_crm_url . 'crm/v7/Contacts/' . $contact_id;
			$update_result = $execute_curl_call_handle->execute_curl_call_put( $update_url, $zoho_data );

			if ( is_wp_error( $update_result ) ) {
				( 'Zoho CRM Contact Sync: Failed to update existing contact - Customer ID ' . $customer_id . ', Contact ID ' . $contact_id . ': ' . $update_result->get_error_message() );
				return;
			}

			( 'Zoho CRM Contact Sync: Successfully updated contact - Customer ID ' . $customer_id . ', Contact ID ' . $contact_id );
		} else {
			// No existing contact ID, need to check if contact exists by email.
			$email = $customer->user_email;
			if ( empty( $email ) ) {
				( 'Zoho CRM Contact Sync: Customer has no email address - ID ' . $customer_id );
				return;
			}

			$search_url    = $zoho_crm_url . 'crm/v7/Contacts/search?criteria=(Email:equals:' . urlencode( $email ) . ')';
			$search_result = $execute_curl_call_handle->execute_curl_call_get( $search_url );

			if ( is_wp_error( $search_result ) ) {
				( 'Zoho CRM Contact Sync: Failed to search for existing contact - Customer ID ' . $customer_id . ': ' . $search_result->get_error_message() );
				return;
			}

			// Check if contact exists by email - at this point $search_result is not a WP_Error.
			/** @var object $search_result */
			if ( isset( $search_result->data ) && ! empty( $search_result->data ) ) {
				// Contact found by email, update it and store the contact ID.
				$existing_contact = $search_result->data[0];
				$contact_id       = $existing_contact->id;

				// Store the contact ID for future syncs.
				update_user_meta( $customer_id, 'zcrm_contact_id', $contact_id );

				$update_url    = $zoho_crm_url . 'crm/v7/Contacts/' . $contact_id;
				$update_result = $execute_curl_call_handle->execute_curl_call_put( $update_url, $zoho_data );

				if ( is_wp_error( $update_result ) ) {
					( 'Zoho CRM Contact Sync: Failed to update existing contact found by email - Customer ID ' . $customer_id . ', Contact ID ' . $contact_id . ': ' . $update_result->get_error_message() );
					return;
				}

				( 'Zoho CRM Contact Sync: Successfully updated contact found by email - Customer ID ' . $customer_id . ', Contact ID ' . $contact_id );
			} else {
				// Contact does not exist, create a new one.
				$create_url    = $zoho_crm_url . 'crm/v7/Contacts';
				$create_result = $execute_curl_call_handle->execute_curl_call_post( $create_url, $zoho_data );

				if ( is_wp_error( $create_result ) ) {
					( 'Zoho CRM Contact Sync: Failed to create new contact - Customer ID ' . $customer_id . ': ' . $create_result->get_error_message() );
					return;
				}

				if (
					isset( $create_result->data )
					&& is_array( $create_result->data )
					&& isset( $create_result->data[0] )
					&& is_object( $create_result->data[0] )
					&& isset( $create_result->data[0]->details )
					&& is_object( $create_result->data[0]->details )
					&& ! empty( $create_result->data[0]->details->id )
				) {
					$new_contact_id = $create_result->data[0]->details->id;

					// Store the new contact ID for future syncs.
					update_user_meta( $customer_id, 'zcrm_contact_id', $new_contact_id );

					( 'Zoho CRM Contact Sync: Successfully created new contact - Customer ID ' . $customer_id . ', Contact ID ' . $new_contact_id );
				} else {
					( 'Zoho CRM Contact Sync: Contact created but ID not returned - Customer ID ' . $customer_id );
				}
			}
		}
	}
}
