<?php
/**
 * Config Manager Service
 *
 * Handles configuration management for native integrations.
 *
 * @package SureForms
 * @since 1.13.0
 */

namespace SRFM_Pro\Inc\Pro\Native_Integrations\Services;

use SRFM\Inc\Helper;
use SRFM_Pro\Inc\Pro\Database\Tables\Integrations;
use SRFM_Pro\Inc\Pro\Native_Integrations\Utils\Integration_Utils;

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

/**
 * Config Manager Service class.
 *
 * @since 1.13.0
 */
class Config_Manager {
	/**
	 * Apply third-party integration filters to data
	 *
	 * @param array $data Base integration data.
	 * @return array Filtered integration data.
	 * @since 1.13.0
	 */
	public function apply_integration_filters( $data ) {
		// Ensure data is array with integrations key.
		if ( ! is_array( $data ) || ! isset( $data['integrations'] ) ) {
			$data = [ 'integrations' => [] ];
		}

		$additional_json_configs = apply_filters( 'srfm_pro_native_integrations_json_configs', [] );

		if ( ! empty( $additional_json_configs ) && is_array( $additional_json_configs ) ) {
			foreach ( $additional_json_configs as $json_config ) {
				if ( is_string( $json_config ) ) {
					$decoded_config = json_decode( $json_config, true );
					if ( is_array( $decoded_config ) && isset( $decoded_config['integrations'] ) ) {
						$data['integrations'] = array_merge( $data['integrations'], $decoded_config['integrations'] );
					}
				}
			}
		}

		return $data;
	}

	/**
	 * Handle integration configuration requests
	 *
	 * @param \WP_REST_Request $request The REST request.
	 * @return \WP_REST_Response
	 * @since 1.13.0
	 */
	public function handle_integration_config( $request ) {
		if ( 'GET' === $request->get_method() ) {
			return $this->get_integration_config( $request );
		}
			return $this->save_integration_config( $request );
	}

	/**
	 * Get all integrations
	 *
	 * @param \WP_REST_Request $request The REST request.
	 * @return \WP_REST_Response
	 * @since 1.13.0
	 */
	public function get_all_integrations( $request ) {
		$nonce = sanitize_text_field( Helper::get_string_value( $request->get_header( 'X-WP-Nonce' ) ) );

		if ( ! wp_verify_nonce( $nonce, 'wp_rest' ) ) {
			return new \WP_REST_Response(
				[
					'success' => false,
					'message' => __( 'Invalid security token. Please refresh the page and try again.', 'sureforms-pro' ),
				],
				403
			);
		}

		// Try to get from cache first.
		$cache_key              = 'srfm_pro_all_integrations';
		$formatted_integrations = wp_cache_get( $cache_key, 'sureforms_pro' );

		if ( false === $formatted_integrations ) {
			// Get all integrations from database.
			$integrations = Integrations::get_instance()->get_results( [] );

			$formatted_integrations = [];

			if ( is_array( $integrations ) && ! empty( $integrations ) ) {
				foreach ( $integrations as $integration ) {
					$formatted_integrations[] = [
						'type'       => $integration['type'] ?? '',
						'name'       => $integration['name'] ?? '',
						'status'     => $integration['status'] ?? '',
						'created_at' => $integration['created_at'] ?? '',
						'updated_at' => $integration['updated_at'] ?? '',
						'auth_type'  => $integration['data']['type'] ?? '',
					];
				}
			}

			// Add available WordPress plugin integrations.
			$wordpress_integrations = $this->get_wordpress_plugin_integrations();
			foreach ( $wordpress_integrations as $wp_integration ) {
				// Check if this integration exists in database.
				$existing = array_filter(
					$formatted_integrations,
					static function( $item ) use ( $wp_integration ) {
						return $item['type'] === $wp_integration['type'];
					}
				);

				// Only add if it's not configured yet.
				if ( empty( $existing ) ) {
					$formatted_integrations[] = [
						'type'       => $wp_integration['type'],
						'name'       => $wp_integration['name'],
						'status'     => 'disabled', // Will show as toggle in UI.
						'created_at' => '',
						'updated_at' => '',
						'auth_type'  => 'wordpress',
					];
				}
			}

			// Store the result in cache.
			wp_cache_set( $cache_key, $formatted_integrations, 'sureforms_pro', HOUR_IN_SECONDS );
		}

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

	/**
	 * Get integration JSON configuration
	 *
	 * @param \WP_REST_Request $request The REST request.
	 * @return \WP_REST_Response
	 * @since 1.13.0
	 */
	public function get_integration_json_config( $request ) {
		$integration_type = Helper::get_string_value( $request->get_param( 'type' ) );
		$display_name     = Helper::get_string_value( $request->get_header( 'Integration-Display-Name' ) );

		if ( empty( $integration_type ) ) {
			return new \WP_REST_Response(
				[
					'success' => false,
					'message' => __( 'Integration type is required.', 'sureforms-pro' ),
				],
				400
			);
		}

		try {
			// Handle 'all' case - return all integrations.
			if ( 'all' === $integration_type ) {
				// Get all integrations data using distributed loading.
				$data = $this->get_all_integrations_data();

				// Apply filter to include third-party integrations.
				$data = $this->apply_integration_filters( $data );

				return new \WP_REST_Response(
					[
						'success'      => true,
						'integrations' => $data['integrations'] ?? [],
					],
					200
				);
			}

			// Try direct filename lookup if display_name is provided.
			$integration_config = null;
			if ( ! empty( $display_name ) ) {
				$integration_config = $this->load_integration_config( $integration_type, $display_name );
			} else {
				$integration_config = $this->load_integration_config( $integration_type );
			}

			if ( ! $integration_config ) {
				return new \WP_REST_Response(
					[
						'success' => false,
						'message' => sprintf(
							/* translators: %s: Integration type */
							__( 'Integration configuration not found for: %s', 'sureforms-pro' ),
							$integration_type
						),
					],
					404
				);
			}

			// Extract actions from the found integration.
			$actions = [];
			if ( isset( $integration_config['actions'] ) && is_array( $integration_config['actions'] ) ) {
				foreach ( $integration_config['actions'] as $action ) {
					$actions[] = [
						'value'       => sanitize_key( str_replace( ' ', '_', strtolower( $action['name'] ?? '' ) ) ),
						'label'       => $action['name'] ?? '',
						'description' => $action['description'] ?? '',
					];
				}
			}

			return new \WP_REST_Response(
				[
					'success' => true,
					'config'  => $integration_config,
					'actions' => $actions,
				],
				200
			);

		} catch ( \Exception $e ) {
			return new \WP_REST_Response(
				[
					'success' => false,
					'message' => sprintf(
						/* translators: %s: Exception message */
						__( 'Failed to load configuration: %s', 'sureforms-pro' ),
						$e->getMessage()
					),
				],
				500
			);
		}
	}

	/**
	 * Load integration configuration from distributed JSON files
	 *
	 * @param string $integration_name Integration name.
	 * @param string $display_name     Optional display name for direct filename lookup.
	 * @return array|null Integration configuration or null if not found.
	 * @since 1.13.0
	 */
	public function load_integration_config( $integration_name, $display_name = '' ) {
		// Direct filename lookup using display_name.
		if ( ! empty( $display_name ) ) {
			$filename  = $this->normalize_integration_name( $display_name, true );
			$file_path = $this->get_integrations_directory() . $filename . '.json';

			$config = Integration_Utils::load_json_file( $file_path );
			if ( $config ) {
				return $config;
			}

			// Check if there's a folder-based config (config.json inside folder).
			$folder_path = $this->get_integrations_directory() . $filename . '/config.json';
			$config      = Integration_Utils::load_json_file( $folder_path );
			if ( $config ) {
				return $config;
			}
		}

		// Check third-party integrations with fallback.
		$all_data      = $this->get_all_integrations_data();
		$filtered_data = $this->apply_integration_filters( $all_data );

		if ( isset( $filtered_data['integrations'] ) && is_array( $filtered_data['integrations'] ) ) {
			foreach ( $filtered_data['integrations'] as $integration_config ) {
				$config_name     = $integration_config['integration']['name'] ?? '';
				$config_key      = $this->normalize_integration_name( $config_name );
				$integration_key = $this->normalize_integration_name( $integration_name );

				// Match by normalized name or original name.
				if ( $config_key === $integration_key ||
					strtolower( $config_name ) === strtolower( $integration_name ) ) {
					return $integration_config;
				}
			}
		}

		return null;
	}

	/**
	 * Find action configuration within integration config
	 *
	 * @param array  $integration_config Integration configuration.
	 * @param string $action_name Action name to find.
	 * @return array|null Action configuration or null if not found.
	 * @since 1.13.0
	 */
	public function find_action_config( $integration_config, $action_name ) {
		if ( isset( $integration_config['actions'] ) && is_array( $integration_config['actions'] ) ) {
			foreach ( $integration_config['actions'] as $action ) {
				$action_value = sanitize_key( str_replace( ' ', '_', strtolower( $action['name'] ?? '' ) ) );
				if ( $action_value === $action_name ) {
					return $action;
				}
			}
		}

		return null;
	}

	/**
	 * Get all integrations data from distributed files
	 *
	 * @since 1.13.0
	 * @return array All integrations data in standard format.
	 */
	public function get_all_integrations_data() {
		$integrations_dir = $this->get_integrations_directory();
		$integrations     = Integration_Utils::load_all_configs( $integrations_dir );

		return [ 'integrations' => $integrations ];
	}

	/**
	 * Get available WordPress plugin integrations
	 *
	 * @return array List of available WordPress plugin integrations.
	 * @since 1.13.0
	 */
	private function get_wordpress_plugin_integrations() {
		$integrations_dir = $this->get_integrations_directory();
		$configs          = Integration_Utils::load_all_configs( $integrations_dir, 'WordPress', true );

		$integrations = [];
		foreach ( $configs as $config ) {
			$integration_config = $config['integration'] ?? [];
			if ( ! is_array( $integration_config ) ) {
				continue;
			}

			$plugin_detection = $config['plugin_detection'] ?? [];
			$plugin_class     = $plugin_detection['class'] ?? '';
			$plugin_constant  = $plugin_detection['constant'] ?? '';

			// Extract directory name from config ID or use fallback.
			$directory = $config['id'] ?? 'unknown';

			$integrations[] = [
				'type'            => $config['id'] ?? $directory,
				'name'            => $integration_config['name'] ?? ucfirst( $directory ),
				'description'     => $integration_config['description'] ?? '',
				'icon'            => $integration_config['icon'] ?? '',
				'category'        => $integration_config['category'] ?? 'Other',
				'plugin_class'    => $plugin_class,
				'plugin_constant' => $plugin_constant,
				'website_url'     => $integration_config['website_url'] ?? '',
				'docs_url'        => $integration_config['docs_url'] ?? '',
			];
		}

		return $integrations;
	}

	/**
	 * Get integration configuration from request
	 *
	 * @param \WP_REST_Request $request The REST request.
	 * @return \WP_REST_Response
	 * @since 1.13.0
	 */
	private function get_integration_config( $request ) {
		// Verify nonce for security.
		$nonce = sanitize_text_field( Helper::get_string_value( $request->get_header( 'X-WP-Nonce' ) ) );
		if ( ! wp_verify_nonce( $nonce, 'wp_rest' ) ) {
			return new \WP_REST_Response(
				[
					'success' => false,
					'message' => __( 'Nonce verification failed.', 'sureforms-pro' ),
				],
				403
			);
		}

		// Get integration name from request.
		$integration_name = $request->get_param( 'integration' );

		if ( empty( $integration_name ) ) {
			return new \WP_REST_Response(
				[
					'success' => false,
					'message' => __( 'Integration name is required.', 'sureforms-pro' ),
				],
				400
			);
		}

		// Get integration from database.
		$integration = Integrations::get_by_type( sanitize_key( Helper::get_string_value( $integration_name ) ) );

		if ( $integration && ! empty( $integration['data'] ) ) {
			// Decrypt sensitive data before returning.
			$data = Integrations::decrypt_sensitive_data( Helper::get_array_value( $integration['data'] ) );

			// Extract type from root level.
			$auth_type = $data['type'] ?? '';

			// Extract credentials (everything except 'type').
			$credentials = [];
			foreach ( $data as $key => $value ) {
				if ( 'type' !== $key ) {
					$credentials[ $key ] = $value;
				}
			}

			return new \WP_REST_Response(
				[
					'success' => true,
					'data'    => [
						'credentials' => $credentials,
						'status'      => $integration['status'],
						'name'        => $integration['name'],
						'type'        => $auth_type,
					],
				],
				200
			);
		}

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

	/**
	 * Save integration configuration from request
	 *
	 * @param \WP_REST_Request $request The REST request.
	 * @return \WP_REST_Response
	 * @since 1.13.0
	 */
	private function save_integration_config( $request ) {
		// Verify nonce for security.
		$nonce = sanitize_text_field( Helper::get_string_value( $request->get_header( 'X-WP-Nonce' ) ) );
		if ( ! wp_verify_nonce( $nonce, 'wp_rest' ) ) {
			return new \WP_REST_Response(
				[
					'success' => false,
					'message' => __( 'Nonce verification failed.', 'sureforms-pro' ),
				],
				403
			);
		}

		// Check if this is a delete operation.
		$action = $request->get_param( 'action' );
		if ( 'delete' === $action ) {
			return $this->delete_integration_connection( $request );
		}

		$integration_name = $request->get_param( 'integration' );
		$config_data      = $request->get_param( 'config' );

		if ( empty( $integration_name ) || ! is_array( $config_data ) || empty( $config_data ) ) {
			return new \WP_REST_Response(
				[
					'success' => false,
					'message' => __( 'Integration name and configuration data are required.', 'sureforms-pro' ),
				],
				400
			);
		}
		// Extract credentials and status.
		$credentials  = $config_data['credentials'] ?? [];
		$status       = $config_data['status'] ?? 'disabled';
		$display_name = $config_data['name'] ?? $integration_name;
		$auth_type    = $config_data['type'] ?? '';

		// Prepare data array with type at root level and credentials at the same level.
		$data_to_save = [
			'type' => $auth_type,
		];

		// Add credentials to the same level.
		if ( ! empty( $credentials ) ) {
			$data_to_save = array_merge( $data_to_save, $credentials );
		}

		// Sanitize and encrypt the complete data structure.
		$sanitized_data = $this->sanitize_integration_config( $data_to_save );
		$encrypted_data = Integrations::encrypt_sensitive_data( $sanitized_data );

		// Save to database.
		$saved = Integrations::save_integration(
			sanitize_key( Helper::get_string_value( $integration_name ) ),
			sanitize_text_field( Helper::get_string_value( $display_name ) ),
			$encrypted_data,
			sanitize_key( Helper::get_string_value( $status ) )
		);

		if ( false !== $saved ) {
			// Clear cache when integration is modified.
			$this->clear_integrations_cache();

			return new \WP_REST_Response(
				[
					'success' => true,
					'message' => __( 'Integration configuration saved successfully.', 'sureforms-pro' ),
				],
				200
			);
		}
			return new \WP_REST_Response(
				[
					'success' => false,
					'message' => __( 'Failed to save integration configuration.', 'sureforms-pro' ),
				],
				500
			);
	}

	/**
	 * Delete integration connection.
	 *
	 * @param \WP_REST_Request $request The REST request.
	 * @return \WP_REST_Response
	 * @since 1.13.0
	 */
	private function delete_integration_connection( $request ) {
		$integration_id   = $request->get_param( 'integration_id' );
		$integration_type = $request->get_param( 'integration_type' );

		if ( empty( $integration_id ) && empty( $integration_type ) ) {
			return new \WP_REST_Response(
				[
					'success' => false,
					'message' => __( 'Integration ID or type is required for deletion.', 'sureforms-pro' ),
				],
				400
			);
		}

		// Delete by ID if provided, otherwise by type.
		if ( ! empty( $integration_id ) ) {
			$deleted = Integrations::delete( absint( $integration_id ) );
		} else {
			$deleted = Integrations::delete_by_type( sanitize_key( Helper::get_string_value( $integration_type ) ) );
		}

		if ( $deleted ) {
			// Clear cache when integration is deleted.
			$this->clear_integrations_cache();

			return new \WP_REST_Response(
				[
					'success' => true,
					'message' => __( 'Integration deleted successfully.', 'sureforms-pro' ),
				],
				200
			);
		}

		return new \WP_REST_Response(
			[
				'success' => false,
				'message' => __( 'Failed to delete integration.', 'sureforms-pro' ),
			],
			500
		);
	}

	/**
	 * Sanitize integration configuration data
	 *
	 * @param array $config Raw configuration data.
	 * @return array Sanitized configuration data.
	 * @since 1.13.0
	 */
	private function sanitize_integration_config( $config ) {
		$sanitized = [];

		// Sanitize each field appropriately.
		foreach ( $config as $key => $value ) {
			$sanitized_key = sanitize_key( $key );

			// Handle different field types.
			switch ( $sanitized_key ) {
				case 'type':
					// Auth type should be a valid key.
					$sanitized[ $sanitized_key ] = sanitize_key( Helper::get_string_value( $value ) );
					break;
				case 'api_key':
				case 'api_secret':
				case 'client_id':
				case 'client_secret':
				case 'access_token':
				case 'refresh_token':
				case 'token':
					// Sensitive fields - keep as-is but ensure they're strings.
					$sanitized[ $sanitized_key ] = Helper::get_string_value( $value );
					break;
				case 'username':
				case 'password':
					// Credentials - keep as-is but ensure they're strings.
					$sanitized[ $sanitized_key ] = Helper::get_string_value( $value );
					break;
				case 'expires_at':
				case 'expires_in':
					// Numeric fields.
					$sanitized[ $sanitized_key ] = Helper::get_integer_value( $value );
					break;
				case 'scope':
				case 'token_type':
				case 'display_name':
					// Text fields.
					$sanitized[ $sanitized_key ] = sanitize_text_field( Helper::get_string_value( $value ) );
					break;
				default:
					// Default sanitization for unknown fields.
					if ( is_string( $value ) ) {
						$sanitized[ $sanitized_key ] = sanitize_text_field( $value );
					} elseif ( is_array( $value ) ) {
						$sanitized[ $sanitized_key ] = $this->sanitize_integration_config( $value );
					} else {
						$sanitized[ $sanitized_key ] = $value;
					}
					break;
			}
		}

		return $sanitized;
	}

	/**
	 * Get integrations directory path
	 *
	 * @since 1.13.0
	 * @return string Path to integrations directory.
	 */
	private function get_integrations_directory() {
		return SRFM_PRO_DIR . 'inc/pro/native-integrations/integrations/';
	}

	/**
	 * Normalize integration name
	 *
	 * @param string $integration_name Integration name.
	 * @param bool   $for_filename Whether to format for filename (spaces to hyphens) or comparison key (remove spaces).
	 * @since 1.13.0
	 * @return string Normalized key or filename.
	 */
	private function normalize_integration_name( $integration_name, $for_filename = false ) {
		$clean_name = Helper::get_string_value( $integration_name );

		if ( $for_filename ) {
			// For filename: convert spaces to hyphens, lowercase, sanitize for file system.
			return sanitize_file_name( strtolower( str_replace( ' ', '-', trim( $clean_name ) ) ) );
		}

		// For comparison: remove spaces, lowercase.
		return strtolower( Helper::get_string_value( preg_replace( '/\s+/', '', trim( $clean_name ) ) ) );
	}

	/**
	 * Clear integrations cache
	 *
	 * @since 1.13.0
	 * @return void
	 */
	private function clear_integrations_cache() {
		wp_cache_delete( 'srfm_pro_all_integrations', 'sureforms_pro' );
	}

}
