<?php
/**
 * This file handles the import and export configurations of the plugin.
 *
 * @package object-data-sync-for-salesforce\Handler
 */

namespace MoSfSyncSalesforce\Handler;

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

use MoSfSyncSalesforce\Helper\Plugin_Constants;
use MoSfSyncSalesforce\Services\Utils;
use MoSfSyncSalesforce\Services\DB_Utils;
use MoSfSyncSalesforce\Services\User_Journey_Service;
use MoSfSyncSalesforce\Helper\Instance;
require_once ABSPATH . 'wp-admin/includes/file.php';

/**
 * This class is responsible for handling plugin configuration import and export.
 */
class Import_Export_Handler {

	use Instance;

	/**
	 * Instance variable for DB_Utils class.
	 *
	 * @var object
	 */
	private $db;

	/**
	 * Instance variable for WP_Filesystem class.
	 *
	 * @var object
	 */
	private $wp_filesystem;

	/**
	 * Instance variable for User_Journey_Service class.
	 *
	 * @var object
	 */
	private $user_journey_service;

	/**
	 * Creates instance of the class.
	 *
	 * @return Import_Export_Handler
	 */
	public static function instance() {
		if ( is_null( self::$instance ) ) {
			global $wp_filesystem;
			self::$instance     = new self();
			self::$instance->db = DB_Utils::instance();
			WP_Filesystem();
			self::$instance->wp_filesystem        = $wp_filesystem;
			self::$instance->user_journey_service = User_Journey_Service::instance();
		}
		return self::$instance;
	}

	/**
	 * Function that exports the plugin configuration.
	 *
	 * @return void
	 */
	public function mo_sf_sync_export_plugin_configuration() {
		$configuration_array                         = array();
		$mapping_object                              = Utils::mo_sf_sync_get_settings( 'mo_sf_sync_object' );
		$config_object                               = Utils::mo_sf_sync_get_settings( 'mo_sf_sync_config' );
		$configuration_array['PROVISION_OBJECT']     = Utils::mo_sf_sync_get_settings( 'mo_sf_sync_provision' );
		$mapping_object                              = $this->db->mo_sf_sync_get_all_mapping_data();
		$configuration_array['MAPPING_OBJECT']       = $mapping_object;
		$configuration_array['CONFIG_OBJECT']        = maybe_unserialize( $config_object );
		$configuration_array['Version_dependencies'] = $this->mo_sf_sync_get_version_information();
		$version                                     = phpversion();
		if ( substr( $version, 0, 3 ) === '5.3' ) {
			$json_string_escaped = ( wp_json_encode( $configuration_array, JSON_PRETTY_PRINT ) );
		} else {
			$json_string_escaped = ( wp_json_encode( $configuration_array, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES ) );
		}
		header( 'Content-Disposition: attachment; filename=miniorange-sf_sync-config.json' );
        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- It was giving an improper file while escaping.
		echo ( $json_string_escaped );
		exit;
	}

	/**
	 * Function that imports the plugin configuration.
	 *
	 * @return void
	 */
	public function mo_sf_sync_import_plugin_configuration() {
		if ( ! function_exists( 'wp_handle_upload' ) ) {
			require_once ABSPATH . 'wp-admin/includes/file.php';
		}

		if ( ! check_admin_referer( 'mo_sf_sync_import_configuration' ) ) {
			return;
		}

		if ( ! isset( $_FILES['configuration_file'] ) || empty( $_FILES['configuration_file']['tmp_name'] ) ) {
			Utils::mo_sf_sync_show_error_message( 'Please upload a valid JSON configuration file.' );
			return;
		}

		if ( isset( $_FILES['configuration_file'] ) && ! empty( $_FILES['configuration_file']['tmp_name'] ) ) {
			$file = array(
				'name'     => isset( $_FILES['configuration_file']['name'] ) ? sanitize_file_name( $_FILES['configuration_file']['name'] ) : '',
				'type'     => isset( $_FILES['configuration_file']['type'] ) ? sanitize_mime_type( $_FILES['configuration_file']['type'] ) : '',
				'tmp_name' => isset( $_FILES['configuration_file']['tmp_name'] ) ? sanitize_text_field( $_FILES['configuration_file']['tmp_name'] ) : '',
				'error'    => isset( $_FILES['configuration_file']['error'] ) ? absint( $_FILES['configuration_file']['error'] ) : '',
				'size'     => isset( $_FILES['configuration_file']['size'] ) ? absint( $_FILES['configuration_file']['size'] ) : '',
			);

			// 1. Basic error check
			if ( UPLOAD_ERR_OK !== $file['error'] ) {
				Utils::mo_sf_sync_show_error_message( 'Upload error. Please try again.' );
				return;
			}

			// 2. Extension check (.json only)
			$custom_mimes = array(
				'json' => 'application/json',
			);
			$filetype     = wp_check_filetype( $file['name'], $custom_mimes );
			if ( 'json' !== $filetype['ext'] ) {
				Utils::mo_sf_sync_show_error_message( 'Invalid file type. Only .json files are allowed.' );
				return;
			}

			// 3. MIME type check
			$finfo     = finfo_open( FILEINFO_MIME_TYPE );
			$mime_type = finfo_file( $finfo, $file['tmp_name'] );
			finfo_close( $finfo );
			if ( 'application/json' !== $mime_type ) {
				Utils::mo_sf_sync_show_error_message( 'Uploaded file must be a valid JSON file.' );
				return;
			}

			// Sanitize file path.
			$tmp_file = str_replace( '\\', '/', sanitize_text_field( $file['tmp_name'] ) );

			if ( $this->wp_filesystem && $this->wp_filesystem->exists( $tmp_file ) ) {
				$file_contents = $this->wp_filesystem->get_contents( $tmp_file );

				if ( false === $file_contents ) {
					Utils::mo_sf_sync_show_error_message( 'Failed to read uploaded configuration file.' );
					return;
				}

				$configuration_array = json_decode( $file_contents, true );

				if ( json_last_error() !== JSON_ERROR_NONE || ! is_array( $configuration_array ) ) {
					Utils::mo_sf_sync_show_error_message( 'Uploaded file contains invalid JSON.' );
					return;
				}

				$update_config = $this->mo_sf_sync_update_configuration_array( $configuration_array );

				if ( ! $update_config ) {
					Utils::mo_sf_sync_show_error_message( 'Import failed: The selected file is not a valid configuration export.' );
				} else {
					Utils::mo_sf_sync_show_success_message( 'Configuration import completed! Please Authorize again to connect to Salesforce.' );
				}
			} else {
				Utils::mo_sf_sync_show_error_message( 'Uploaded file not found or unreadable.' );
			}
		}
	}

	/**
	 * Function that provides the version information about the plugin.
	 *
	 * @return array
	 */
	public function mo_sf_sync_get_version_information() {
		$array_version                      = array();
		$array_version['Plugin_version']    = Plugin_Constants::VERSION;
		$array_version['PHP_version']       = phpversion();
		$array_version['Wordpress_version'] = get_bloginfo( 'version' );
		return $array_version;
	}

	/**
	 * Function to update the configuration array in the database.
	 *
	 * @param array $configuration_array The configuration array that includes the configuration of the plugin.
	 * @return bool
	 */
	public function mo_sf_sync_update_configuration_array( $configuration_array ) {

		if ( isset( $configuration_array['MAPPING_OBJECT'] ) ) {
			$mapping_import_res = $this->db->mo_sf_sync_insert_imported_mapping_data( $configuration_array['MAPPING_OBJECT'] );

			if ( $mapping_import_res ) {
				$this->user_journey_service->mo_sf_sync_journey_set_object_mapping_configured( true );
			} else {
				return false;
			}
		}

		if ( isset( $configuration_array['PROVISION_OBJECT'] ) ) {
			Utils::mo_sf_sync_save_settings( 'mo_sf_sync_provision', $configuration_array['PROVISION_OBJECT'] );
			$provision = Utils::mo_sf_sync_get_settings( Plugin_Constants::PROVISION_OBJECT );
			$enabled   = is_array( $provision ) && isset( $provision[ Plugin_Constants::AUTO_USER_UPDATE ] ) && 'on' === $provision[ Plugin_Constants::AUTO_USER_UPDATE ];
			$this->user_journey_service->mo_sf_sync_journey_set_realtime_wp_to_sf( $enabled );
		}

		if ( isset( $configuration_array['CONFIG_OBJECT'] ) ) {
			Utils::mo_sf_sync_save_settings( 'mo_sf_sync_config', $configuration_array['CONFIG_OBJECT'] );
		}

		return true;
	}
}
