<?php

namespace SheetWise\ActionScheduler;

use SheetWise\Admin\GoogleSheet;
use SheetWise\Sync\RetryHandler;
use SheetWise\Vendor\Google\Service\Sheets\AppendValuesResponse;
use SheetWise\Vendor\Google\Service\Sheets\ValueRange;
use SheetWise\Conditions\RuleEvaluator;

class Hooks {

	/**
	 * Initialize the scheduled action hooks
	 */
	public function __construct() {
		add_action( 'init', [ $this, 'register_scheduled_hooks' ] );
	}

	/**
	 * Register the scheduled action hooks for all data sources
	 *
	 * @since 2.0.0
	 *
	 * @return void
	 */
	public function register_scheduled_hooks() {
		$actions = array_keys( swise_get_data_sources() );
		foreach ( $actions as $action ) {
			add_action( 'sheetwise_scheduled_' . $action, [ $this, 'process_data' ] );
		}
	}

	/**
	 * Process the data
	 *
	 * @since 1.0.0
	 *
	 * @param array $args
	 *
	 * @return bool|AppendValuesResponse
	 */
	public function process_data( $args ) {
		if ( empty( $args['hook'] ) || empty( $args['values'] ) || empty( $args['type'] ) || empty( $args['id'] ) ) {
			return false;
		}

		$hook    = $args['hook'];
		$results = $this->get_results( $hook );
		$values  = is_array( $args['values'] ) ? $args['values'] : [];

		if ( empty( $results ) ) {
			return false;
		}

		foreach ( $results as $result ) {
			$data = $this->get_common_data( $result );

			if ( ! $data ) {
				continue;
			}

			$all_event_codes = swise_get_data_source_events();

			if ( ! array_key_exists( $hook, $all_event_codes ) ) {
				continue;
			}

			$all_event_codes = swise_get_data_source_events();

			if ( ! array_key_exists( $hook, $all_event_codes ) ) {
				continue;
			}

			$submitted_values = [];
			$default_events = array_keys( $all_event_codes[ $hook ] );

			foreach ( $default_events as $event ) {
				$submitted_values[] = isset( $values[ $event ] ) ? $values[ $event ] : '';
			}

			// add `[[` and `]]` to the $default_events array
			$default_events = array_map(
				function ( $event ) {
					return "[[$event]]";
				}, $default_events
			);

			$values = [];

			foreach ( $data['event_codes'] as $event_code ) {
				$values[] = str_replace( $default_events, $submitted_values, $event_code );
			}

			$values = apply_filters( 'swise_values_to_insert_' . $hook, $values, $hook, $result );

			if ( empty( $values ) ) {
				continue;
			}

			// Evaluate conditional logic rules
			if ( ! empty( $data['conditions']['rules'] ) ) {
				// Build field_key => resolved_value map for rule evaluation
				$all_event_keys = array_keys( swise_get_data_source_events()[ $hook ] );
				$field_values   = [];

				foreach ( $all_event_keys as $i => $key ) {
					$field_values[ $key ] = isset( $submitted_values[ $i ] ) ? $submitted_values[ $i ] : '';
				}

				$evaluator   = new RuleEvaluator();
				$should_sync = $evaluator->evaluate( $data['conditions'], $field_values );

				/**
				 * Filter whether an event should be synced after condition evaluation
				 *
				 * @since SWISE_SINCE
				 *
				 * @param bool  $should_sync    Whether the event passed condition evaluation
				 * @param array $conditions     The conditions config from integration JSON
				 * @param array $field_values   Associative array: field_key => resolved_value
				 * @param int   $integration_id The integration post ID
				 */
				$should_sync = apply_filters(
					'swise_condition_evaluated',
					$should_sync,
					$data['conditions'],
					$field_values,
					$result->post_id
				);

				if ( ! $should_sync ) {
					$logger = new \SheetWise\Sync\SyncLogger();
					$logger->log( [
						'integration_id' => $result->post_id,
						'hook'           => $hook,
						'status'         => 'skipped',
						'attempts'       => 1,
						'error_message'  => __( 'Conditions not met', 'sheet-wise' ),
						'data_payload'   => $field_values,
						'row_count'      => 0,
					] );

					continue;
				}
			}

			$spreadsheet_id = ! empty( $data['sheet_id'] ) ? $data['sheet_id'] : '';

			if ( empty( $spreadsheet_id ) ) {
				continue;
			}

			$value_range = new ValueRange();
			$value_range->setValues( [ $values ] );
			$sheet       = new GoogleSheet( $spreadsheet_id );
			$service     = $sheet->get_service();
			$sheet_title = apply_filters( 'swise_sheet_title_' . $hook, 'Sheet1', $spreadsheet_id );

			$retry_handler = new RetryHandler();
			$context       = [
				'integration_id' => $result->post_id,
				'hook'           => $hook,
				'data_payload'   => $values,
				'spreadsheet_id' => $spreadsheet_id,
				'sheet_title'    => $sheet_title,
			];

			$sync_result = $retry_handler->execute(
				function () use ( $service, $spreadsheet_id, $sheet_title, $value_range ) {
					return $service->spreadsheets_values->append(
						$spreadsheet_id, $sheet_title, $value_range, [ 'valueInputOption' => 'USER_ENTERED' ]
					);
				},
				$context
			);

			/**
			 * Fires after a sync attempt completes (success or failure)
			 *
			 * @since 2.0.0
			 *
			 * @param array $sync_result Result with status, response, error, attempts
			 * @param array $context     Sync context with integration_id, hook, data_payload
			 */
			do_action( 'swise_sync_completed', $sync_result, $context );

			if ( $sync_result['status'] === 'success' ) {
				return $sync_result['response'];
			}

			return false;
		}

		return true;
	}

	/**
	 * Get the results
	 *
	 * @since 1.0.0
	 *
	 * @return array|object|null Database query results.
	 */
	private function get_results( $meta_value ) {
		global $wpdb;

		return $wpdb->get_results(
			$wpdb->prepare(
				"SELECT * FROM $wpdb->postmeta pm
				INNER JOIN $wpdb->posts p ON pm.post_id = p.ID
				WHERE pm.meta_key = %s AND pm.meta_value = %s AND p.post_status != %s", swise_get_hook_meta_key(),
				$meta_value, 'draft'
			)
		);
	}

	/**
	 * Get the common data
	 *
	 * @since 1.0.0
	 *
	 * @param object $result
	 *
	 * @return null|array
	 */
	private function get_common_data( $result ) {
		$integration = get_post( $result->post_id );
		if ( ! $integration ) {
			return null;
		}
		$integration = json_decode( $integration->post_content );
		if ( ! $integration ) {
			return null;
		}
		$sheet_id = $integration->sheet;
		if ( ! $sheet_id ) {
			return null;
		}
		$event_codes = $integration->event_codes;
		if ( ! $event_codes ) {
			return null;
		}
		$source = $integration->source;
		if ( ! $source ) {
			return null;
		}
		$sheet = new GoogleSheet( $sheet_id );

		$conditions = isset( $integration->conditions ) ? (array) $integration->conditions : [];

		// Convert rules from stdClass to arrays if needed (JSON decode gives objects)
		if ( ! empty( $conditions['rules'] ) ) {
			$conditions['rules'] = array_map( function ( $rule ) {
				return (array) $rule;
			}, $conditions['rules'] );
		}

		return [
			'event_codes' => $integration->event_codes,
			'sheet'       => $sheet,
			'sheet_id'    => $sheet_id,
			'source'      => $source,
			'conditions'  => $conditions,
		];
	}
}
