<?php

class RPSync_WooCommerce {

	public function __construct() {
		add_action( 'rpsync_process_product_data', array( $this, 'process_product_data' ), 1 );
		add_filter( 'rpsync_process_wc_product', array( $this, 'process_wc_product' ), 10, 2 );
//		add_action( 'save_post_product', array( $this, 'save_product' ) );
	}

	/**
	 * Process extracted product_data for WooCommerce
	 *
	 * @param $data
	 *
	 * @return void
	 */
	public function process_product_data( $numref ) {
		// Load product data from RPSync database
		if ( empty( $product_data = RPSync::get_instance()->database->load_product_data( $numref ) ) ) {
			return;
		}

		// Process associated WooCommerce products
		foreach ( $product_data['skus'] as &$product ) {
			// Skip empty / invalid product_id
			if ( empty( $product['product_id'] ) || empty ( $wc_product = wc_get_product( $product['product_id'] ) ) ) {
				continue;
			}
			$wc_product = apply_filters( 'rpsync_process_wc_product', $wc_product, $product, $product_data );
			$wc_product->save();
		}
	}

	/**
	 * Process WooCommerce product from extracted Retailpoint data
	 *
	 * @param WC_Product $wc_product
	 * @param $product
	 *
	 * @return WC_Product
	 * @throws WC_Data_Exception
	 */
	public function process_wc_product( WC_Product $wc_product, $product ) {
		$changes = array();
		if ( empty( $wc_product->get_name() ) ) {
			$wc_product->set_name( $product['title'] );
			$changes['Titre'] = "'' => '${product['title']}'";
		}
		if ( empty( $wc_product->get_sku() ) ) {
			$wc_product->set_sku( $product['sku'] );
			$changes['SKU'] = "'' => '${product['sku']}'";
		}
		// Prices
		if ( $product['regular_price'] !== ( $regular_price = $wc_product->get_regular_price() ) ) {
			$wc_product->set_regular_price( $product['regular_price'] );
			$changes['Prix régulier'] = "'$regular_price' => '${product['regular_price']}'";
		}
		if ( $product['sale_price'] !== ( $sale_price = $wc_product->get_sale_price() ) ) {
			$wc_product->set_sale_price( $product['sale_price'] );
			$changes['Prix spécial'] = "'$sale_price' => '${product['sale_price']}'";
		}
		// Stock
		$wc_product->set_manage_stock( true );
		if ( $product['stock'] !== ( $stock_quantity = $wc_product->get_stock_quantity() ) ) {
			$wc_product->set_stock_quantity( $product['stock'] );
			$changes['Inventaire'] = "'$stock_quantity' => '${product['stock']}'";
		}

		// Log changes
		if ( ! empty( $changes ) ) {
			$changes = implode( "\n", array_map( function ( $label, $change ) {
				return "  $label: $change";
			}, array_keys( $changes ), $changes ) );
			RPSync::get_instance()->info( sprintf( "SKU %s => %s (ID: %d)\n", $product['sku'], $wc_product->get_name(), $wc_product->get_id() ) . $changes );
		}

		return $wc_product;
	}

	/**
	 * Find product ID from SKU
	 *
	 * @param $sku string The SKU to find
	 *
	 * @return false|int The product ID if found, false otherwise
	 */
	public static function find_product_by_sku( string $sku ) {
		global $wpdb;
		$query = "SELECT post_id FROM $wpdb->postmeta WHERE meta_key='_sku' AND meta_value='$sku' ORDER BY post_ID DESC LIMIT 1;";
		if ( empty( $results = $wpdb->get_results( $query, ARRAY_A ) ) ) {
			return false;
		}

		return (int) $results[0]['post_id'];
	}

	/**
	 * Create WooCommerce product by numref
	 *
	 * @param string $numref
	 *
	 * @return bool|void
	 * @throws WC_Data_Exception
	 */
	public function create_product( string $numref ) {
		// Load Retailpoint product data
		if ( empty( $product_data = RPSync::get_instance()->database->load_product_data( $numref ) ) ) {
			return false;
		}

		// Check if WC product already exists
		if ( ! empty( $product_data['product_id'] ) ) {
			return false;
		}

		// Create simple / variable product
		if ( sizeof( $product_data['skus'] ) === 1 ) {
			// Create simple product with 'draft' status
			$product    = &$product_data['skus'][ array_key_first( $product_data['skus'] ) ];
			$wc_product = new WC_Product_Simple();
			$wc_product->set_status( 'draft' );
			$wc_product->set_name( $product['title'] );
			$wc_product->set_sku( $product['sku'] );
			if ( ! $wc_product->save() ) {
				return false;
			}
			// Update product_id in Retailpoint tables
			$product_data['product_id'] = $product['product_id'] = $wc_product->get_id();
			if ( ! RPSync::get_instance()->database->save_product_data( $product_data ) ) {
				return false;
			}
		} else {
			// Create variable product with 'draft' status
			$wc_product = new WC_Product_Variable();
			$wc_product->set_status( 'draft' );
			$wc_product->set_name( reset( $product_data['skus'] )['title'] );
			$wc_product->set_attributes( $this->create_variable_attributes( $product_data ) );
			if ( ! $wc_product->save() ) {
				return false;
			}
			$product_data['product_id'] = $wc_product->get_id();
			foreach ( $product_data['skus'] as &$product ) {
				// Create product variation
				$wc_variation = new WC_Product_Variation();
				$wc_variation->set_parent_id( $wc_product->get_id() );
				$wc_variation->set_status( 'publish' );
				$wc_variation->set_sku( $product['sku'] );
				$wc_variation->set_attributes( $product['attributes'] );
				if ( ! $wc_variation->save() ) {
					return false;
				}
				$product['product_id'] = $wc_variation->get_id();
			}
			if ( ! RPSync::get_instance()->database->save_product_data( $product_data ) ) {
				return false;
			}
		}

		// Process newly created product synchronously
		do_action( 'rpsync_process_product_data', $numref, 'rpsync' );
		return true;
	}

	/**
	 * Create variable product attributes
	 *
	 * @param array $product_data
	 *
	 * @return array
	 */
	public function create_variable_attributes( array $product_data ) {
		$attributes = array();
		foreach ( $product_data['skus'] as $product ) {
			foreach ( $product['attributes'] as $name => $value ) {
				$attributes[ $name ][] = $value;
			}
		}

		return array_map( function ( $name, array $options ) {
			$wc_attribute = new WC_Product_Attribute();
			$wc_attribute->set_name( $name );
			$wc_attribute->set_options( $options );
			$wc_attribute->set_visible( true );
			if ( sizeof( $options ) > 1 ) {
				$wc_attribute->set_variation( true );
			}
			return $wc_attribute;
		}, array_keys( $attributes ), array_map( 'array_unique', $attributes ) );
	}

	/**
	 * Update WooCommerce product by numref
	 *
	 * @param string $numref
	 *
	 * @return bool
	 */
	public function update_product( string $numref ) {
		if ( RPSync::get_instance()->database->get_md5( $numref ) === false ) {
			return false;
		}
		do_action( 'rpsync_process_product_data', $numref, 'rpsync' );
		return true;
	}

	/**
	 * Destroy WooCommerce product by numref
	 *
	 * @param string $numref
	 *
	 * @return bool
	 */
	public function destroy_product( string $numref ) {
		if ( empty( $product_data = RPSync::get_instance()->database->load_product_data( $numref ) ) ) {
			return false;
		}
		if ( empty( $product_data['product_id'] ) || ! wp_delete_post( $product_data['product_id'] ) ) {
			return false;
		}
		$product_data['product_id'] = null;
		foreach ( $product_data['skus'] as &$product ) {
			$product['product_id'] = null;
		}

		return RPSync::get_instance()->database->save_product_data( $product_data );
	}

	/**
	 * Invalidate and dispatch numref when saving product
	 *
	 * @param $post_id
	 *
	 * @return void
	 */
	public function save_product( $post_id ) {
		if ( ! empty( $numrefs = explode( ' / ', $_POST["acf"]["field_61d88632b62cd"] ?: '' ) ) ) {
			array_walk( $numrefs, function ( $numref ) {
				RPSync::get_instance()->database->reset_md5( $numref );
				RPSync::get_instance()->dispatch_process_numref( $numref );
			} );
		}
	}
}
