<?php

if ( ! class_exists( 'FKCART_DB_Migrator' ) ) {
	#[AllowDynamicProperties]
	class FKCART_DB_Migrator extends WooFunnels_Background_Updater {
		public static $_instance = null;
		protected $prefix = 'bwf_fkcart_1';
		protected $action = 'migrator';

		public function __construct() {
			parent::__construct();
		}

		public static function get_instance() {
			if ( null === self::$_instance ) {
				self::$_instance = new self;
			}

			return self::$_instance;
		}


		public function maybe_re_dispatch_background_process() {
			if ( $this->is_queue_empty() ) {
				return;
			}
			if ( $this->is_process_running() ) {
				return;
			}
			$this->dispatch();
		}

		public function get_action() {
			return $this->action;
		}

		/**
		 * Kill process.
		 *
		 * Stop processing queue items, clear cronjob and delete all batches.
		 */
		public function kill_process() {
			$this->kill_process_safe();
		}

		public function get_last_offsets() {
			return array();
		}

		public function manage_last_offsets() {

		}

		protected function complete() {
			$migrate_total = get_option( '_bwf_fkcart_offset', 0 );
			$this->set_upgrade_state( 3 );
			WFFN_Core()->logger->log( 'FKcart migration process complete for total number of entry ' . $migrate_total, 'fkcart_migration', true );

			global $wpdb;
			$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}fk_cart_stats" );

			update_option( '_bwf_fkcart_offset', 0 );
		}

		public function get_upgrade_state() {

			/**
			 * 0: default state, nothing set
			 * 1: upgrade is available
			 * 2: upgrade is in process
			 * 3: upgrade is completed successfully
			 * 4: upgrade is unavailable
			 */
			return absint( get_option( '_fkcart_upgrade', '0' ) );
		}

		public function set_upgrade_state( $state ) {
			update_option( '_fkcart_upgrade', $state );
		}

		/**
		 * Prepare data for db migrate
		 * @return bool
		 */
		public function db_migrator() {
			global $wpdb;
			$per_page         = 1;
			$fkcart_threshold = absint( get_option( '_bwf_fkcart_threshold', 0 ) );

			/**
			 * If threshold is 0 then we will set it to total number of orders
			 * reaching inside this condition also means that this is the first time we are running this migration
			 */
			if ( 0 === $fkcart_threshold ) {

				$total_entry = $wpdb->get_var( "select count(ID) as total_entry from {$wpdb->prefix}fk_cart_stats WHERE status = 1 " );
				WFFN_Core()->logger->log( 'migration process total number of entry ' . $total_entry, 'fkcart_migration', true );

				if ( $total_entry === 0 ) {
					WFFN_Core()->logger->log( 'Fkcart no data found in cart state table', 'fkcart_migration', true );

					return false;
				}
				update_option( '_bwf_fkcart_threshold', absint( $total_entry ) );
				$fkcart_threshold = $total_entry;
			}

			/**
			 * Get the offset from where we need to start the process
			 */
			$offset = absint( get_option( '_bwf_fkcart_offset', 0 ) );

			if ( $offset > 0 && $fkcart_threshold > 0 && $offset >= $fkcart_threshold ) {
				/**
				 * Since we are inside here we must terminate the process as offset is equal to threshold
				 */
				WFFN_Core()->logger->log( 'Fkcart no entry found', 'fkcart_migration', true );

				return false;

			}

			/**
			 * Let's proceed with the process and find out next batch of entries
			 */
			WFFN_Core()->logger->log( 'Fkcart find entries from cart stats - offset: ' . $offset, 'fkcart_migration', true );
			$entries = $wpdb->get_results( $wpdb->prepare( "select * from {$wpdb->prefix}fk_cart_stats WHERE status = 1 limit %d,%d ", $offset, $per_page ), ARRAY_A );

			/**
			 * If we don't have any orders then we must terminate the process
			 */
			if ( empty( $entries ) ) {
				WFFN_Core()->logger->log( 'Fkcart no entry found for process', 'fkcart_migration', true );

				return false;
			}
			$insert_cart     = [];
			$update_cart     = [];
			$insert_products = [];

			foreach ( $entries as $item ) {
				if ( empty( $item['oid'] ) ) {
					continue;
				}
				$offset ++;
				update_option( '_bwf_fkcart_offset', $offset );

				$insert_products[] = [
					'oid'        => $item['oid'],
					'product_id' => $item['pid'],
					'price'      => $item['total'],
					'type'       => 1,
				];
				$product_id        = ( string ) $item['pid'];
				$upsells_viewed    = [ $product_id ];

				$cart_product = $wpdb->get_row( $wpdb->prepare( "select * from {$wpdb->prefix}fk_cart where oid=%d;", $item['oid'] ), ARRAY_A );

				if ( ! empty( $cart_product ) ) {
					$upsells_prev = json_decode( $cart_product['upsells_viewed'] );
					if ( is_array( $upsells_prev ) ) {
						foreach ( $upsells_prev as $upsell ) {
							$upsells_viewed[] = ( string ) $upsell;
						}
					}
					$cart_product['upsells_viewed'] = wp_json_encode( $upsells_viewed );
					$update_cart[ $item['oid'] ]    = $cart_product;

				} else if ( isset( $insert_cart[ $item['oid'] ] ) ) {
					$upsells_prev = json_decode( $insert_cart[ $item['oid'] ]['upsells_viewed'] );
					if ( is_array( $upsells_prev ) ) {
						foreach ( $upsells_prev as $upsell ) {
							$upsells_viewed[] = ( string ) $upsell;
						}
					}
					$insert_cart[ $item['oid'] ]['upsells_viewed'] = wp_json_encode( $upsells_viewed );
				} else {
					$insert_cart[ $item['oid'] ] = [
						'oid'            => $item['oid'],
						'addon_viewed'   => '',
						'upsells_viewed' => wp_json_encode( $upsells_viewed ),
						'discount'       => '',
						'free_shipping'  => 0,
						'date_created'   => $item['date_created'],
					];
				}
			}

			/***
			 * prepare process order array
			 */
			if ( ! empty( $insert_cart ) ) {
				$this->insert_data( $insert_cart, $wpdb->prefix . 'fk_cart' );
			}
			if ( ! empty( $insert_products ) ) {
				$this->insert_data( $insert_products, $wpdb->prefix . 'fk_cart_products' );
			}

			if ( ! empty( $update_cart ) ) {
				$this->update_data( $update_cart, $wpdb->prefix . 'fk_cart' );
			}

			return true;
		}

		/**
		 * Insert data in new tables
		 *
		 * @param $data
		 * @param $table_name
		 *
		 * @return void
		 */
		public function insert_data( $data, $table_name ) {
			/***
			 * prepare process order array
			 */
			if ( ! empty( $data ) ) {
				global $wpdb;
				$first_row     = reset( $data );
				$columns       = array_keys( $first_row );
				$placeholders  = array_fill( 0, count( $data ), '(' . rtrim( str_repeat( '%s, ', count( $columns ) ), ', ' ) . ')' );
				$query         = "INSERT INTO $table_name (" . implode( ', ', $columns ) . ") VALUES " . implode( ', ', $placeholders );
				$insert_values = [];
				foreach ( $data as $row ) {
					$insert_values = array_merge( $insert_values, array_values( $row ) );
				}
				$sql = $wpdb->prepare( $query, $insert_values );//phpcs:ignore
				$wpdb->query( $sql );//phpcs:ignore

				if ( ! empty( $wpdb->last_error ) ) {
					WFFN_Core()->logger->log( 'fkcart migration process insert data error ' . $wpdb->last_error . ' last query ' . $wpdb->last_query, 'fkcart_migration', true );
				}
			}
		}

		public function update_data( $data, $table_name ) {
			global $wpdb;
			if ( ! is_array( $data ) || empty( $data ) ) {
				return;
			}

			foreach ( $data as $item ) {
				$sql = '';
				unset( $item['id'] );

				$update_data  = $item;
				$oid_value    = $item['oid'];
				$placeholders = array();
				$update_query = "UPDATE $table_name SET ";
				foreach ( $update_data as $key => $value ) {
					$placeholders[] = "$key = %s";
				}
				$update_query       .= implode( ', ', $placeholders );
				$update_query       .= " WHERE oid = %d;";
				$update_data_values = array_merge( array_values( $update_data ), array( $oid_value ) );
				$sql                .= $wpdb->prepare( $update_query, $update_data_values ); //phpcs:ignore
				$wpdb->query( $sql );//phpcs:ignore
				if ( ! empty( $wpdb->last_error ) ) {
					WFFN_Core()->logger->log( 'fkcart migration process update data error ' . $wpdb->last_error . ' last query ' . $wpdb->last_query, 'fkcart_migration', true );
				}
			}

		}

	}

	if ( ! function_exists( 'FKCART_DB_Migrator' ) ) {
		function fkcart_db_migrator() {  //@codingStandardsIgnoreLine
			return FKCART_DB_Migrator::get_instance();
		}
	}

	fkcart_db_migrator();
}

if ( ! function_exists( 'fkcart_run_db_migrator' ) ) {
	function fkcart_run_db_migrator() {
		return fkcart_db_migrator()->db_migrator();
	}
}

