<?php

declare(strict_types=1);

namespace FormConnector\API\Endpoints;

use FormConnector\Integration\Forms\FormIntegrationManager;
use FormConnector\Integration\Forms\Mappings;
use FormConnector\Integration\Forms\SubmissionHandler;
use FormConnector\Features\License\License;
use FormConnector\Core\Validation\PhoneValidator;

/**
 * Forms and Mappings REST API endpoints.
 */
class FormsEndpoints {

	private const NAMESPACE = 'fc/v1';

	/**
	 * Register forms and mappings routes.
	 */
	public static function register(): void {
		// Forms discovery
		register_rest_route(self::NAMESPACE, '/forms', [
			'methods' => \WP_REST_Server::READABLE,
			'callback' => [self::class, 'get_forms'],
			'permission_callback' => [self::class, 'permission_check'],
		]);

		register_rest_route(self::NAMESPACE, '/forms/(?P<plugin>[a-z0-9]+)/(?P<form_id>[a-z0-9_-]+)/fields', [
			'methods' => \WP_REST_Server::READABLE,
			'callback' => [self::class, 'get_form_fields'],
			'permission_callback' => [self::class, 'permission_check'],
		]);

		// Mappings CRUD
		register_rest_route(self::NAMESPACE, '/mappings', [
			'methods' => \WP_REST_Server::READABLE,
			'callback' => [self::class, 'get_all_mappings'],
			'permission_callback' => [self::class, 'permission_check'],
		]);

		register_rest_route(self::NAMESPACE, '/mappings/(?P<plugin>[a-z0-9]+)/(?P<form_id>[a-z0-9_-]+)', [
			'methods' => \WP_REST_Server::READABLE,
			'callback' => [self::class, 'get_mapping'],
			'permission_callback' => [self::class, 'permission_check'],
		]);

		register_rest_route(self::NAMESPACE, '/mappings/save', [
			'methods' => \WP_REST_Server::CREATABLE,
			'callback' => [self::class, 'save_mapping'],
			'permission_callback' => [self::class, 'permission_check'],
		]);

		register_rest_route(self::NAMESPACE, '/mappings/delete', [
			'methods' => \WP_REST_Server::CREATABLE,
			'callback' => [self::class, 'delete_mapping'],
			'permission_callback' => [self::class, 'permission_check'],
		]);

		register_rest_route(self::NAMESPACE, '/mappings/test', [
			'methods' => \WP_REST_Server::CREATABLE,
			'callback' => [self::class, 'test_mapping'],
			'permission_callback' => [self::class, 'permission_check'],
		]);
	}

	/**
	 * Permission check for admin-only endpoints.
	 */
	public static function permission_check(): bool {
		return current_user_can('manage_options');
	}

	/**
	 * Get all forms from active plugins.
	 */
	public static function get_forms(\WP_REST_Request $request): \WP_REST_Response {
		$manager = FormIntegrationManager::get_instance();
		
		return new \WP_REST_Response([
			'success' => true,
			'data' => [
				'plugins' => $manager->get_plugins(),
				'forms' => $manager->get_all_forms(),
			],
		], 200);
	}

	/**
	 * Get fields for a specific form.
	 */
	public static function get_form_fields(\WP_REST_Request $request): \WP_REST_Response {
		$plugin = $request->get_param('plugin');
		$form_id = $request->get_param('form_id');

		$manager = FormIntegrationManager::get_instance();
		$fields = $manager->get_form_fields($plugin, $form_id);

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

	/**
	 * Get all mappings.
	 */
	public static function get_all_mappings(\WP_REST_Request $request): \WP_REST_Response {
		$mappings = new Mappings();

		return new \WP_REST_Response([
			'success' => true,
			'data' => [
				'mappings' => $mappings->get_all_mappings(),
				'conditional' => $mappings->get_all_conditional(),
			],
		], 200);
	}

	/**
	 * Get mapping for a specific form.
	 */
	public static function get_mapping(\WP_REST_Request $request): \WP_REST_Response {
		$plugin = $request->get_param('plugin');
		$form_id = $request->get_param('form_id');

		$mappings = new Mappings();

		return new \WP_REST_Response([
			'success' => true,
			'data' => [
				'mapping' => $mappings->get_mapping($plugin, $form_id),
				'conditional' => $mappings->get_conditional($plugin, $form_id),
			],
		], 200);
	}

	/**
	 * Save mapping for a form.
	 */
	public static function save_mapping(\WP_REST_Request $request): \WP_REST_Response {
		// Require valid license for this operation
		$license = new License();
		$license_error = $license->require_license();
		if ($license_error !== null) {
			return $license_error;
		}

		$plugin = sanitize_text_field($request->get_param('plugin') ?? '');
		$form_id = sanitize_text_field($request->get_param('form_id') ?? '');
		$mapping = $request->get_param('mapping') ?? [];
		$conditional = $request->get_param('conditional') ?? [];

		// Validate required parameters
		if (empty($plugin)) {
			return new \WP_REST_Response([
				'success' => false,
				'error' => 'missing_plugin',
				'message' => __('Plugin type is required.', 'form-connector'),
			], 400);
		}
		
		if (empty($form_id)) {
			return new \WP_REST_Response([
				'success' => false,
				'error' => 'missing_form_id',
				'message' => __('Form ID is required.', 'form-connector'),
			], 400);
		}
		
		// Validate supported plugins
		$supported_plugins = ['gravityforms', 'cf7', 'wpforms', 'forminator', 'fluentforms'];
		if (!in_array($plugin, $supported_plugins)) {
			return new \WP_REST_Response([
				'success' => false,
				'error' => 'invalid_plugin',
				'message' => sprintf(__('Unsupported plugin: %s', 'form-connector'), $plugin),
			], 400);
		}
		
		// Validate mapping structure
		if (!is_array($mapping)) {
			return new \WP_REST_Response([
				'success' => false,
				'error' => 'invalid_mapping',
				'message' => __('Mapping data must be an array.', 'form-connector'),
			], 400);
		}
		
		// Ensure location_id is set if enabled
		if (!empty($mapping['enabled']) && empty($mapping['location_id'])) {
			// Check if conditional routing is enabled with valid rules
			$has_conditional_routing = !empty($conditional['enabled']) 
				&& !empty($conditional['field']) 
				&& !empty($conditional['rules']);
				
			if (!$has_conditional_routing) {
				return new \WP_REST_Response([
					'success' => false,
					'error' => 'missing_location',
					'message' => __('Please select a default location or enable conditional routing.', 'form-connector'),
				], 400);
			}
		}

		$mappings_manager = new Mappings();

		try {
			// Save field mapping
			$mapping_saved = $mappings_manager->save_mapping($plugin, $form_id, $mapping);

			// Save conditional mapping if provided
			$conditional_saved = true;
			if (!empty($conditional)) {
				$conditional_saved = $mappings_manager->save_conditional($plugin, $form_id, $conditional);
			}

			if ($mapping_saved && $conditional_saved) {
				return new \WP_REST_Response([
					'success' => true,
					'message' => __('Mapping saved successfully.', 'form-connector'),
					'data' => [
						'mapping' => $mappings_manager->get_mapping($plugin, $form_id),
						'conditional' => $mappings_manager->get_conditional($plugin, $form_id),
					],
				], 200);
			}

			return new \WP_REST_Response([
				'success' => false,
				'error' => 'save_failed',
				'message' => __('Failed to save mapping. Please try again.', 'form-connector'),
			], 500);
			
		} catch (\Exception $e) {
			return new \WP_REST_Response([
				'success' => false,
				'error' => 'exception',
				'message' => __('An error occurred while saving: ', 'form-connector') . $e->getMessage(),
			], 500);
		}
	}

	// -------------------------------------------------------------------------
	// Test mapping
	// -------------------------------------------------------------------------

	/**
	 * Perform a synthetic test against the current mapping configuration.
	 *
	 * Generates fake field values for each mapped CareHQ field and runs them
	 * through the normal map_fields() pipeline to show exactly what payload
	 * would be sent to CareHQ.
	 *
	 * dry_run=true  → returns the payload without calling CareHQ.
	 * dry_run=false → sends the payload to CareHQ (requires valid license).
	 */
	public static function test_mapping(\WP_REST_Request $request): \WP_REST_Response {
		$plugin  = sanitize_text_field($request->get_param('plugin') ?? '');
		$form_id = sanitize_text_field($request->get_param('form_id') ?? '');
		$dry_run = filter_var($request->get_param('dry_run') ?? true, FILTER_VALIDATE_BOOLEAN);

		if (empty($plugin) || empty($form_id)) {
			return new \WP_REST_Response([
				'success' => false,
				'message' => __('Plugin and form ID are required.', 'form-connector'),
			], 400);
		}

		// Load the mapping for this form.
		$mappings     = new Mappings();
		$mapping_data = $mappings->get_mapping($plugin, $form_id);

		if (empty($mapping_data['enabled'])) {
			return new \WP_REST_Response([
				'success' => false,
				'message' => __('This form mapping is not enabled. Enable the integration first.', 'form-connector'),
			], 400);
		}

		$field_mapping = is_array($mapping_data['fields'] ?? null)
			? $mapping_data['fields']
			: (array) ($mapping_data['fields'] ?? []);

		$location_id = is_string($mapping_data['location_id'] ?? null)
			? $mapping_data['location_id']
			: '';

		// Build synthetic original_fields: {form_field_id => test_value} keyed by
		// the carehq field name so we pick sensible placeholder values.
		$test_original = [];
		foreach ($field_mapping as $carehq_field => $form_field_id) {
			if (!empty($form_field_id)) {
				$test_original[$form_field_id] = self::get_test_value($carehq_field);
			}
		}

		// Map synthetic fields through the same pipeline as real submissions.
		$handler = SubmissionHandler::get_instance();
		$payload = $handler->map_fields($test_original, $field_mapping);
		$payload['location'] = $location_id;

		// Run phone through the same validation as the real submission flow so
		// the test payload accurately mirrors what CareHQ would actually receive.
		$warnings = [];
		if (!empty($payload['phone'])) {
			$phone_validator = new PhoneValidator();
			$phone_result    = $phone_validator->validate_and_format((string) $payload['phone']);
			if ($phone_result['valid']) {
				$payload['phone'] = $phone_result['formatted'];
			} else {
				unset($payload['phone']);
			}
		}

		// Add sales channel from CareHQ settings.
		$sales_channel = (string) get_option('fc_carehq_sales_channel_id', '');
		if (!empty($sales_channel)) {
			$payload['sales_channel'] = sanitize_text_field($sales_channel);
		}

		// Warn about missing important fields.
		if (empty($payload['email']) && empty($payload['phone'])) {
			$warnings[] = __('Neither email nor phone is mapped. CareHQ will likely reject this enquiry.', 'form-connector');
		}
		if (empty($payload['first_name']) && empty($payload['last_name'])) {
			$warnings[] = __('No name fields are mapped. The enquiry will be created without a contact name.', 'form-connector');
		}

		if ($dry_run) {
			return new \WP_REST_Response([
				'success' => true,
				'data'    => [
					'dry_run'  => true,
					'payload'  => $payload,
					'warnings' => $warnings,
				],
			], 200);
		}

		// Live send – require a valid license first.
		$license       = new License();
		$license_error = $license->require_license();
		if ($license_error !== null) {
			return $license_error;
		}

		$api    = \FormConnector\Integration\CareHQ\APIClient::get_instance();
		$result = $api->send_care_enquiry($payload);

		if (is_wp_error($result)) {
			return new \WP_REST_Response([
				'success' => false,
				'data'    => [
					'dry_run'  => false,
					'payload'  => $payload,
					'warnings' => $warnings,
					'error'    => $result->get_error_message(),
				],
			], 200);
		}

		return new \WP_REST_Response([
			'success' => true,
			'data'    => [
				'dry_run'  => false,
				'payload'  => $payload,
				'warnings' => $warnings,
				'result'   => $result,
			],
		], 200);
	}

	/**
	 * Return a sensible test value for a given CareHQ field name.
	 */
	private static function get_test_value(string $carehq_field): string {
		return match ($carehq_field) {
			'first_name'        => 'Test',
			'last_name'         => 'Submission',
			'email'             => 'test+fc@example.com',
			'phone'             => '+447800900000',
			'care_requirements' => 'This is a test submission generated by FormConnector.',
			default             => 'Test value',
		};
	}

	/**
	 * Delete mapping for a form.
	 */
	public static function delete_mapping(\WP_REST_Request $request): \WP_REST_Response {
		$plugin = sanitize_text_field($request->get_param('plugin') ?? '');
		$form_id = sanitize_text_field($request->get_param('form_id') ?? '');

		if (empty($plugin) || empty($form_id)) {
			return new \WP_REST_Response([
				'success' => false,
				'message' => __('Plugin and form ID are required.', 'form-connector'),
			], 400);
		}

		$mappings = new Mappings();
		$mappings->delete_mapping($plugin, $form_id);

		return new \WP_REST_Response([
			'success' => true,
			'message' => __('Mapping deleted.', 'form-connector'),
		], 200);
	}
}
