<?php

namespace fluXtore\Core\Admin\Ajax;

// Exit if accessed directly.
use fluXtore\Core\Models\fluXtore_Flow;
use fluXtore\Core\Models\fluXtore_Step;
use Exception;

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

// Avoid defining the class twice.
if ( ! class_exists( 'fluXtore_AjaxFlows' ) ) {
	class fluXtore_AjaxFlows extends fluXtore_AjaxBase {
		/**
		 * @var fluXtore_AjaxFlows $instance
		 */
		private static $instance;

		public static function init() {
			if ( !is_null( self::$instance ) ) {
				return;
			}

			self::$instance = new fluXtore_AjaxFlows();
			self::$instance->register_ajax_events();
		}

		function register_ajax_events() {
			$this->init_ajax_events([
				'create_flow',
				'get_flow',
				'get_all_flows',
				'save_flow_props',
				'delete_flow',
                'clone_flow'
			]);
		}

		function create_flow() {
			$flow = new fluXtore_Flow();

			try {
				$flow_id = $flow->create( [
					'title' => sanitize_text_field( $_GET[ 'name' ] ),
					'template' => sanitize_text_field( $_GET[ 'template' ] )
				] );

				// Save the editor type as flow meta for later identification
				if ( isset( $_GET['editor'] ) && ! empty( $_GET['editor'] ) ) {
					$editor = sanitize_text_field( $_GET['editor'] );
					update_post_meta( $flow_id, FLUXTORE_PREFIX . 'editor', $editor );
				}
			} catch (Exception $ex) {
				wp_send_json_error( [ 'error' => $ex->getMessage(), 401 ] );
				exit;
			}

			wp_send_json_success( [ 'id' => $flow_id ] );
		}

		private function sanitize_flow_fields( $flow ) {
			foreach ( $flow as $key => $value ) {
				if ( is_string( $value ) ) {
					$value = maybe_unserialize( $value );
				} else if ( is_array( $value ) ) {
					foreach ( $value as $i => $v ) {
						if ( is_string( $v ) ) {
							$value[ $i ] = maybe_unserialize( $v );
						}
					}
				}

				if ( string_starts_with( $key, 'post_' ) ) {
					$k = explode( 'post_', $key )[ 1 ];
					$flow->$k = $value;
					unset( $flow->$key );
				} elseif ( string_starts_with( $key, FLUXTORE_PREFIX ) ) {
					$k = explode( FLUXTORE_PREFIX, $key )[ 1 ];
					$flow->$k = $value;
					unset( $flow->$key );
				}
			}

				$first_step_preview_link = null;

				foreach ( $flow->steps as $step_index => $step ) {
					foreach ( $step as $id_index => $step_id ) {
						$flow->steps[ 0 ][ $id_index ] = ( new fluXtore_Step() )->get( $step_id );
						$preview_link = get_preview_post_link( $step_id );
						$flow->steps[ 0 ][ $id_index ]->preview_link = $preview_link;

						if ( is_null( $first_step_preview_link ) ) {
							$first_step_preview_link = $preview_link;
						}

						if (
							isset( $flow->steps[ 0 ][ $id_index ]->{FLUXTORE_PREFIX . 'order'}[ 0 ] ) &&
							"" . $flow->steps[ 0 ][ $id_index ]->{FLUXTORE_PREFIX . 'order'}[ 0 ] === '0'
						) {
							$flow->preview_link = $preview_link;
						}
					}
				}

                                if ( empty( $flow->preview_link ) && ! empty( $first_step_preview_link ) ) {
                                        $flow->preview_link = $first_step_preview_link;
                                }

                        $flow->edit_link = '/' . $flow->ID . '/steps';
                        $flow = $this->append_flow_editor_details( $flow );

                        $schedule = fluXtore_Flow::get_schedule_status( $flow->ID );
                        $flow->schedule = $schedule['label'];
                        $flow->schedule_status = $schedule['slug'];

                        if ( ! empty( $schedule['details'] ) ) {
                                $flow->schedule_details = $schedule['details'];
                        }

                        return $flow;
                }

                private function append_flow_editor_details( $flow ) {
                        $editors = [];

                        // First check if the flow has an editor meta saved
                        error_log('Flow ID: ' . print_r($flow->ID, true));
                        error_log('Flow post_id: ' . print_r($flow->post_id ?? 'not set', true));
                        $flow_id = $flow->ID ?? $flow->post_id ?? null;
                        error_log('Using flow_id: ' . $flow_id);

                        if ( $flow_id ) {
                                $flow_editor_meta = get_post_meta( $flow_id, FLUXTORE_PREFIX . 'editor', true );
                                error_log('Flow editor meta: ' . $flow_editor_meta);

                                if ( ! empty( $flow_editor_meta ) ) {
                                        $formatted = $this->format_editor_label( $flow_editor_meta );
                                        $editors[ $formatted ] = $formatted;
                                }
                        }

                        if ( empty( $editors ) ) {
                                // Fall back to detecting from steps
                                if ( isset( $flow->steps ) ) {
                                        foreach ( (array) $flow->steps as $step_group ) {
                                                if ( is_array( $step_group ) || $step_group instanceof \Traversable ) {
                                                        foreach ( $step_group as $step ) {
                                                                $editor = $this->detect_step_editor( $step );

                                                                if ( ! empty( $editor ) ) {
                                                                        $editors[ $editor ] = $editor;
                                                                }
                                                        }
                                                } elseif ( is_object( $step_group ) ) {
                                                        $editor = $this->detect_step_editor( $step_group );

                                                        if ( ! empty( $editor ) ) {
                                                                $editors[ $editor ] = $editor;
                                                        }
                                                }
                                        }
                                }

                                // If still no editors detected, use default
                                if ( empty( $editors ) ) {
                                        $default = get_option( '__fluxtore_default_editior', '' );

                                        if ( ! empty( $default ) ) {
                                                $formatted = $this->format_editor_label( $default );
                                                $editors[ $formatted ] = $formatted;
                                        } else {
                                                $editors['Gutenberg'] = 'Gutenberg';
                                        }
                                }
                        }

                        $labels = array_values( $editors );
                        $flow->editor = reset( $labels );
                        $flow->editor_chips = $labels;

                        return $flow;
                }

                private function detect_step_editor( $step ) {
                        $elementor_keys = [ '_elementor_edit_mode', '_elementor_data' ];

                        foreach ( $elementor_keys as $key ) {
                                $value = $this->extract_step_meta_value( $step, $key );

                                if ( ! empty( $value ) ) {
                                        return 'Elementor';
                                }
                        }

                        $bricks_keys = [ '_bricks_page_builder_activated', '_bricks_data', '_bricks_page_content' ];

                        foreach ( $bricks_keys as $key ) {
                                $value = $this->extract_step_meta_value( $step, $key );

                                if ( ! empty( $value ) ) {
                                        return 'Bricks';
                                }
                        }

                        $divi_keys = [ '_et_pb_use_builder', '_et_pb_version' ];

                        foreach ( $divi_keys as $key ) {
                                $value = $this->extract_step_meta_value( $step, $key );

                                if ( ! empty( $value ) ) {
                                        return 'Divi';
                                }
                        }

                        // Check for Gutenberg blocks
                        $post_id = null;
                        if ( is_object( $step ) && isset( $step->ID ) ) {
                                $post_id = $step->ID;
                        } elseif ( is_array( $step ) && isset( $step['ID'] ) ) {
                                $post_id = $step['ID'];
                        }

                        if ( $post_id ) {
                                // Check using has_blocks function
                                if ( function_exists( 'has_blocks' ) && has_blocks( $post_id ) ) {
                                        return 'Gutenberg';
                                }

                                // Get fresh post data to check content
                                $post = get_post( $post_id );
                                if ( $post && ! empty( $post->post_content ) ) {
                                        // Check for block markers
                                        if ( strpos( $post->post_content, '<!-- wp:' ) !== false ) {
                                                return 'Gutenberg';
                                        }
                                }
                        }

                        // If no other editor detected, return null (will use default editor fallback)
                        return null;
                }

                private function extract_step_meta_value( $step, $key ) {
                        if ( is_object( $step ) && isset( $step->$key ) ) {
                                $value = $step->$key;
                        } elseif ( is_array( $step ) && array_key_exists( $key, $step ) ) {
                                $value = $step[ $key ];
                        } else {
                                return null;
                        }

                        if ( is_array( $value ) ) {
                                $value = reset( $value );
                        }

                        if ( is_string( $value ) ) {
                                $maybe_unserialized = maybe_unserialize( $value );

                                if ( false !== $maybe_unserialized || 'b:0;' === $value ) {
                                        $value = $maybe_unserialized;
                                }
                        }

                        return $value;
                }

                private function format_editor_label( $editor ) {
                        $map = [
                                'elementor' => 'Elementor',
                                'bricks'    => 'Bricks',
                                'divi'      => 'Divi',
                                'gutenberg' => 'Gutenberg',
                        ];

                        $normalized = strtolower( (string) $editor );

                        if ( isset( $map[ $normalized ] ) ) {
                                return $map[ $normalized ];
                        }

                        return ucfirst( $normalized );
                }

		function get_flow() {
			$id = intval( $_GET[ 'id' ] );

			$flow = new fluXtore_Flow();
			$result = $flow->get( $id );

			wp_send_json_success( $this->sanitize_flow_fields( $result ) );
		}

		function get_all_flows() {
			$flow = new fluXtore_Flow();
			$result = [];

			foreach ( $flow->get_all() as $f ) {
				$result[] = $this->sanitize_flow_fields( $f );
			}

			wp_send_json_success( $result );
		}

		function save_flow_props() {
			try {
				$id = intval( $_GET[ 'id' ] );

				$flow = new fluXtore_Flow();
				$params = [];
                $metas = [];

                                foreach ( $_GET as $key => $value ) {
                                        $raw_value = isset( $_GET[ $key ] ) ? wp_unslash( $_GET[ $key ] ) : $value;
                                        $value     = sanitize_text_field( $raw_value );

                    if ( string_starts_with( $key, 'meta_' ) ) {
                        $meta_key = str_replace( 'meta_', '', $key );

                        $should_update = apply_filters(
                            'fluxtore_flow_should_update_meta',
                            ! in_array( $meta_key, [ 'schedule_start', 'schedule_end' ], true ),
                            [
                                'meta_key'  => $meta_key,
                                'flow_id'   => $id,
                                'value'     => $value,
                                'raw_value' => $raw_value,
                                'params'    => $_GET,
                            ]
                        );

                        if ( ! $should_update ) {
                            continue;
                        }

                        $filtered_value = apply_filters(
                            'fluxtore_flow_sanitize_meta_value',
                            $value,
                            [
                                'meta_key'  => $meta_key,
                                'flow_id'   => $id,
                                'value'     => $value,
                                'raw_value' => $raw_value,
                                'params'    => $_GET,
                            ]
                        );

                        $metas[ $meta_key ] = $filtered_value;
                        continue;
                    }

					if ( string_starts_with( $key, 'flow_' ) ) {
						$params[ str_replace( 'flow_', '', $key ) ] = $value;
					}

					if ( string_starts_with( $key, 'post_' ) ) {
						$params[ $key ] = $value;
					}
				}

                $flow->update_meta( $id, $metas );
				$result = $flow->update( $id, $params );
				wp_send_json_success( $result );
			} catch (\Exception $ex) {
				wp_send_json_error([ "message" => $ex->errorMessage() ]);
			}
		}

		function delete_flow() {
			$id = intval( $_GET[ 'id' ] );

			$flow = new fluXtore_Flow();
			$result = $flow->delete( $id );

			wp_send_json_success( $result );
		}

        function clone_flow() {
            $flow_id = intval($_GET['id']);

            $original_flow = new fluXtore_Flow();
            $original_flow_data = $original_flow->get($flow_id);

            // Create a new flow with the same title (appending "- Copy")
            $new_flow = new fluXtore_Flow();
            try {
                $new_flow_id = $new_flow->create([
                    'title' => $original_flow_data->post_title . ' - Copy',
                    'template' => '_blank' // We'll manually copy steps instead of using template
                ]);
            } catch (Exception $ex) {
                wp_send_json_error(['error' => $ex->getMessage(), 401]);
                exit;
            }

            // Copy flow meta data
            $meta_keys = [
                FLUXTORE_PREFIX . 'show_header',
                FLUXTORE_PREFIX . 'show_footer'
            ];

            foreach ($meta_keys as $meta_key) {
                if (isset($original_flow_data->$meta_key)) {
                    update_post_meta($new_flow_id, $meta_key, $original_flow_data->$meta_key[0]);
                }
            }

            // Get all steps from the original flow
            $original_steps = get_post_meta($flow_id, FLUXTORE_PREFIX . 'steps', true);
            $new_steps = [];
            $step_model = new fluXtore_Step();

            // Clone each step
            foreach ($original_steps as $original_step_id) {
                $original_step = $step_model->get($original_step_id);

                // Create new step
                $new_step_id = $step_model->create([
                    'title' => $original_step->post_title,
                    'flow_id' => $new_flow_id,
                    'tag' => $original_step->{FLUXTORE_PREFIX . 'tag'}[0]
                ]);

                // Clone step content and meta data
                $post_content = get_post_field('post_content', $original_step_id);
                wp_update_post([
                    'ID' => $new_step_id,
                    'post_content' => $post_content
                ]);

                // Copy Elementor data if exists
                $elementor_data = get_post_meta($original_step_id, '_elementor_data', true);
                if ($elementor_data) {
                    update_post_meta($new_step_id, '_elementor_data', $elementor_data);
                    update_post_meta($new_step_id, '_elementor_edit_mode', get_post_meta($original_step_id, '_elementor_edit_mode', true));
                    update_post_meta($new_step_id, '_elementor_version', get_post_meta($original_step_id, '_elementor_version', true));
                }

                // Copy step meta data
                $step_meta_keys = [
                    FLUXTORE_PREFIX . 'product',
                    FLUXTORE_PREFIX . 'price_type',
                    FLUXTORE_PREFIX . 'price',
                    FLUXTORE_PREFIX . 'order_bump_enabled',
                    FLUXTORE_PREFIX . 'order_bump_default_checked',
                    FLUXTORE_PREFIX . 'order_bump_product',
                    FLUXTORE_PREFIX . 'order_bump_price',
                    FLUXTORE_PREFIX . 'order_bump_discount',
                    FLUXTORE_PREFIX . 'order_bump_text',
                    FLUXTORE_PREFIX . 'order_bump_toggle',
                    FLUXTORE_PREFIX . 'order_bump_frame',
                    FLUXTORE_PREFIX . 'order_bump_primary_color',
                    FLUXTORE_PREFIX . 'order_bump_secondary_color',
                    FLUXTORE_PREFIX . 'billing_fields',
                    FLUXTORE_PREFIX . 'shipping_fields',
                    FLUXTORE_PREFIX . 'hide_additional_notes'
                ];

                foreach ($step_meta_keys as $meta_key) {
                    $meta_value = get_post_meta($original_step_id, $meta_key, true);
                    if ($meta_value) {
                        update_post_meta($new_step_id, $meta_key, $meta_value);
                    }
                }

                // Add new step to the steps array
                $new_steps[] = $new_step_id;
            }

            // Update the flow's steps meta
            update_post_meta($new_flow_id, FLUXTORE_PREFIX . 'steps', $new_steps);

            // Second pass to handle step relationships (yes/no steps)
            foreach ($original_steps as $i => $original_step_id) {
                $yes_step = get_post_meta($original_step_id, FLUXTORE_PREFIX . 'yes_step', true);
                $no_step = get_post_meta($original_step_id, FLUXTORE_PREFIX . 'no_step', true);

                if ($yes_step) {
                    $yes_index = array_search($yes_step, $original_steps);
                    if ($yes_index !== false) {
                        update_post_meta($new_steps[$i], FLUXTORE_PREFIX . 'yes_step', $new_steps[$yes_index]);
                    }
                }

                if ($no_step) {
                    $no_index = array_search($no_step, $original_steps);
                    if ($no_index !== false) {
                        update_post_meta($new_steps[$i], FLUXTORE_PREFIX . 'no_step', $new_steps[$no_index]);
                    }
                }
            }

            wp_send_json_success(['id' => $new_flow_id]);
        }
	}
}

fluXtore_AjaxFlows::init();