<?php
/**
 * FoodOrd Demo Importer.
 *
 * @package FoodOrd
 */

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

/**
 * Class Foodord_Demo_Importer
 */
class Foodord_Demo_Importer {
	/**
	 * Embedded demo directory.
	 *
	 * @var string
	 */
	private $demo_dir;

	/**
	 * Import summary counters.
	 *
	 * @var array<string, int>
	 */
	private $counts = array(
		'images'     => 0,
		'categories' => 0,
		'products'   => 0,
		'variations' => 0,
	);

	/**
	 * Imported Order Page ID.
	 *
	 * @var int
	 */
	private $order_page_id = 0;

	/**
	 * Constructor.
	 *
	 * @param string $demo_dir Demo directory.
	 */
	public function __construct( string $demo_dir ) {
		$this->demo_dir = untrailingslashit( $demo_dir );
	}

	/**
	 * Run the demo import.
	 *
	 * @return array{success: bool, message: string, counts: array<string,int>, order_page_id: int}
	 */
	public function import(): array {
		$check = $this->check_prerequisites();
		if ( is_wp_error( $check ) ) {
			return array(
				'success'       => false,
				'message'       => $check->get_error_message(),
				'counts'        => $this->counts,
				'order_page_id' => 0,
			);
		}

		try {
			$data = $this->read_demo_json();
			if ( is_wp_error( $data ) ) {
				return array(
					'success'       => false,
					'message'       => $data->get_error_message(),
					'counts'        => $this->counts,
					'order_page_id' => 0,
				);
			}

		$settings = isset( $data['settings'] ) && is_array( $data['settings'] ) ? $data['settings'] : array();
		$topping_sets = isset( $data['topping_sets'] ) && is_array( $data['topping_sets'] ) ? $data['topping_sets'] : array();
		$this->import_settings( $settings, $topping_sets );

		$categories = isset( $data['categories'] ) && is_array( $data['categories'] ) ? $data['categories'] : array();
		$category_map = $this->import_categories( $categories );

		$image_map = isset( $data['image_map'] ) && is_array( $data['image_map'] ) ? $data['image_map'] : array();
		$image_source = isset( $data['images'] ) && is_array( $data['images'] ) ? $data['images'] : array();
			$image_id_map = $this->import_images( $image_map, $image_source );
			if ( is_wp_error( $image_id_map ) ) {
				return array(
					'success'       => false,
					'message'       => $image_id_map->get_error_message(),
					'counts'        => $this->counts,
					'order_page_id' => 0,
				);
			}

		$products = isset( $data['products'] ) && is_array( $data['products'] ) ? $data['products'] : array();
			$product_result = $this->import_products( $products, $category_map, $image_id_map );
			if ( is_wp_error( $product_result ) ) {
				return array(
					'success'       => false,
					'message'       => $product_result->get_error_message(),
					'counts'        => $this->counts,
					'order_page_id' => 0,
				);
			}

			$this->order_page_id = $this->create_or_update_order_page();
			if ( $this->order_page_id > 0 ) {
				$this->set_static_front_page( $this->order_page_id );
			}

			return array(
				'success'       => true,
				'message'       => __( 'Demo content imported successfully.', 'foodord' ),
				'counts'        => $this->counts,
				'order_page_id' => $this->order_page_id,
			);
		} catch ( Throwable $e ) {
			return array(
				'success'       => false,
				/* translators: %s: Error message. */
				'message'       => sprintf( __( 'Demo import failed: %s', 'foodord' ), $e->getMessage() ),
				'counts'        => $this->counts,
				'order_page_id' => 0,
			);
		}
	}

	/**
	 * Check import prerequisites.
	 */
	private function check_prerequisites() {
		if ( ! ( class_exists( 'WooCommerce' ) || function_exists( 'wc' ) ) ) {
			return new WP_Error( 'foodord_demo_import_wc_missing', __( 'WooCommerce must be installed and active to import the demo.', 'foodord' ) );
		}

		$demo_dir = $this->demo_dir;
		if ( '' === $demo_dir || ! is_dir( $demo_dir ) ) {
			return new WP_Error( 'foodord_demo_import_missing', __( 'Demo content is missing from the plugin.', 'foodord' ) );
		}

		$json_path = trailingslashit( $demo_dir ) . 'demo-data.json';
		if ( ! file_exists( $json_path ) ) {
			return new WP_Error( 'foodord_demo_import_json_missing', __( 'Demo data file (demo-data.json) is missing.', 'foodord' ) );
		}

		$images_dir = trailingslashit( $demo_dir ) . 'images';
		if ( ! is_dir( $images_dir ) ) {
			return new WP_Error( 'foodord_demo_import_images_missing', __( 'Demo images directory is missing.', 'foodord' ) );
		}

		return true;
	}

	/**
	 * Read demo-data.json from embedded demo directory.
	 * @return array|WP_Error
	 */
	private function read_demo_json() {
		$json_path = trailingslashit( $this->demo_dir ) . 'demo-data.json';
		if ( ! file_exists( $json_path ) ) {
			return new WP_Error( 'foodord_demo_import_json_missing', __( 'Demo data file (demo-data.json) is missing.', 'foodord' ) );
		}

		$raw = file_get_contents( $json_path );
		if ( false === $raw || '' === trim( $raw ) ) {
			return new WP_Error( 'foodord_demo_import_json_empty', __( 'Demo data file is empty.', 'foodord' ) );
		}

		$data = json_decode( $raw, true );
		if ( ! is_array( $data ) ) {
			return new WP_Error( 'foodord_demo_import_json_invalid', __( 'Demo data file is invalid JSON.', 'foodord' ) );
		}

		return $data;
	}

	/**
	 * Import FoodOrd settings.
	 *
	 * @param array $settings Settings map.
	 * @param array $topping_sets Topping sets payload.
	 */
	private function import_settings( array $settings, array $topping_sets ): void {
		$exclude_keys = array(
			'foodord_license_key',
			'foodord_license_status',
			'foodord_license_email',
			'foodord_onboarding_complete',
			'foodord_onboarding_redirect',
		);

		foreach ( $settings as $key => $value ) {
			$key = is_string( $key ) ? $key : '';
			if ( '' === $key || 0 !== strpos( $key, 'foodord_' ) ) {
				continue;
			}
			if ( in_array( $key, $exclude_keys, true ) ) {
				continue;
			}
			update_option( $key, $value );
		}

		if ( ! isset( $settings['foodord_topping_sets'] ) && ! empty( $topping_sets ) ) {
			update_option( 'foodord_topping_sets', $topping_sets );
		}
	}

	/**
	 * Import product categories.
	 *
	 * @param array $categories Categories payload.
	 * @return array<string,int> Category slug => term ID.
	 */
	private function import_categories( array $categories ): array {
		$slug_to_id = array();

		foreach ( $categories as $category ) {
			if ( ! is_array( $category ) ) {
				continue;
			}

			$slug = isset( $category['slug'] ) ? sanitize_title( (string) $category['slug'] ) : '';
			if ( '' === $slug ) {
				continue;
			}

			$name = isset( $category['name'] ) ? (string) $category['name'] : $slug;
			$desc = isset( $category['description'] ) ? (string) $category['description'] : '';

			$existing = get_term_by( 'slug', $slug, 'product_cat' );
			if ( $existing && isset( $existing->term_id ) ) {
				$result = wp_update_term(
					(int) $existing->term_id,
					'product_cat',
					array(
						'name'        => $name,
						'description' => $desc,
					)
				);
				$term_id = is_wp_error( $result ) ? (int) $existing->term_id : (int) $result['term_id'];
			} else {
				$result = wp_insert_term(
					$name,
					'product_cat',
					array(
						'slug'        => $slug,
						'description' => $desc,
					)
				);
				if ( is_wp_error( $result ) ) {
					continue;
				}
				$term_id = (int) $result['term_id'];
			}

			$slug_to_id[ $slug ] = $term_id;
			$this->counts['categories']++;

			$order = isset( $category['menu_order'] ) ? (int) $category['menu_order'] : 0;
			update_term_meta( $term_id, 'order', $order );
			update_term_meta( $term_id, '_foodord_demo_imported', '1' );
		}

		foreach ( $categories as $category ) {
			if ( ! is_array( $category ) ) {
				continue;
			}

			$slug = isset( $category['slug'] ) ? sanitize_title( (string) $category['slug'] ) : '';
			if ( '' === $slug || ! isset( $slug_to_id[ $slug ] ) ) {
				continue;
			}

			$parent_slug = isset( $category['parent_slug'] ) ? sanitize_title( (string) $category['parent_slug'] ) : '';
			$parent_id   = ( '' !== $parent_slug && isset( $slug_to_id[ $parent_slug ] ) ) ? (int) $slug_to_id[ $parent_slug ] : 0;

			wp_update_term(
				(int) $slug_to_id[ $slug ],
				'product_cat',
				array(
					'parent' => $parent_id,
				)
			);
		}

		return $slug_to_id;
	}

	/**
	 * Import images from embedded demo directory.
	 *
	 * @param array $image_map Demo image map (old_id => relative path).
	 * @param array $image_source Image info payload.
	 * @return array<string,int>|WP_Error
	 */
	private function import_images( array $image_map, array $image_source ) {
		require_once ABSPATH . 'wp-admin/includes/file.php';
		require_once ABSPATH . 'wp-admin/includes/image.php';
		require_once ABSPATH . 'wp-admin/includes/media.php';

		$old_to_new = array();
		$demo_dir   = trailingslashit( $this->demo_dir );

		foreach ( $image_map as $old_id => $relative_path ) {
			$old_id        = is_string( $old_id ) ? $old_id : (string) $old_id;
			$relative_path = is_string( $relative_path ) ? $relative_path : '';
			if ( '' === $old_id || '' === $relative_path ) {
				continue;
			}

			$attachment_slug = sanitize_title( 'foodord-demo-attachment-' . $old_id );
			$existing_post   = get_page_by_path( $attachment_slug, OBJECT, 'attachment' );
			if ( $existing_post && isset( $existing_post->ID ) ) {
				$old_to_new[ $old_id ] = (int) $existing_post->ID;
				continue;
			}

			$relative_path = ltrim( $relative_path, '/' );
			if ( false !== strpos( $relative_path, '..' ) ) {
				return new WP_Error( 'foodord_demo_import_image_path_invalid', __( 'Invalid demo image path detected.', 'foodord' ) );
			}

			$source_path = $demo_dir . $relative_path;
			if ( ! file_exists( $source_path ) ) {
				/* translators: %s: Missing file path. */
				return new WP_Error( 'foodord_demo_import_image_missing', sprintf( __( 'Missing image file: %s', 'foodord' ), $relative_path ) );
			}

			$filename = isset( $image_source[ $old_id ]['filename'] ) ? (string) $image_source[ $old_id ]['filename'] : basename( $source_path );
			$filename = sanitize_file_name( $filename );

			$tmp_name = wp_tempnam( basename( $source_path ) );
			if ( ! $tmp_name ) {
				return new WP_Error( 'foodord_demo_import_tmp_file_failed', __( 'Could not create a temporary file for demo images.', 'foodord' ) );
			}

			if ( ! copy( $source_path, $tmp_name ) ) {
				wp_delete_file( $tmp_name );
				return new WP_Error( 'foodord_demo_import_tmp_copy_failed', __( 'Could not prepare demo images for import.', 'foodord' ) );
			}

			$file = array(
				'name'     => $filename,
				'tmp_name' => $tmp_name,
				'error'    => 0,
				'size'     => filesize( $tmp_name ),
			);

			$upload = wp_handle_sideload(
				$file,
				array(
					'test_form' => false,
				)
			);

			if ( ! is_array( $upload ) || isset( $upload['error'] ) ) {
				if ( file_exists( $tmp_name ) ) {
					wp_delete_file( $tmp_name );
				}
				return new WP_Error( 'foodord_demo_import_image_upload_failed', __( 'Could not import demo images.', 'foodord' ) );
			}

			$attachment_id = wp_insert_attachment(
				array(
					'post_mime_type' => isset( $upload['type'] ) ? (string) $upload['type'] : '',
					'post_title'     => sanitize_text_field( pathinfo( $filename, PATHINFO_FILENAME ) ),
					'post_name'      => $attachment_slug,
					'post_status'    => 'inherit',
				),
				$upload['file']
			);

			if ( is_wp_error( $attachment_id ) ) {
				return $attachment_id;
			}

			$metadata = wp_generate_attachment_metadata( (int) $attachment_id, $upload['file'] );
			if ( is_array( $metadata ) ) {
				wp_update_attachment_metadata( (int) $attachment_id, $metadata );
			}

			update_post_meta( (int) $attachment_id, '_foodord_demo_attachment_id', $old_id );
			$old_to_new[ $old_id ] = (int) $attachment_id;
			$this->counts['images']++;
		}

		return $old_to_new;
	}

	/**
	 * Set SKU safely without aborting demo import.
	 *
	 * @param WC_Product $product Product instance.
	 * @param string     $sku SKU string.
	 */
	private function set_sku_safe( WC_Product $product, string $sku ): void {
		$sku = trim( sanitize_text_field( $sku ) );
		if ( '' === $sku ) {
			return;
		}

		$product_id = (int) $product->get_id();
		if ( function_exists( 'wc_product_has_unique_sku' ) && function_exists( 'wc_product_generate_unique_sku' ) ) {
			if ( ! wc_product_has_unique_sku( $product_id, $sku ) ) {
				$sku = wc_product_generate_unique_sku( $product_id, $sku );
			}
		}

		try {
			$product->set_sku( $sku );
		} catch ( Exception $e ) {
			$product->set_sku( '' );
		}
	}

	/**
	 * Import products.
	 *
	 * @param array $products Products payload.
	 * @param array<string,int> $category_map Category slug => term ID.
	 * @param array<string,int> $image_id_map Demo image ID => attachment ID.
	 * @return true|WP_Error
	 */
	private function import_products( array $products, array $category_map, array $image_id_map ) {
		foreach ( $products as $product_data ) {
			if ( ! is_array( $product_data ) ) {
				continue;
			}

			$slug = isset( $product_data['slug'] ) ? sanitize_title( (string) $product_data['slug'] ) : '';
			if ( '' === $slug ) {
				continue;
			}

			$type = isset( $product_data['type'] ) ? (string) $product_data['type'] : 'simple';
			$type = in_array( $type, array( 'simple', 'variable' ), true ) ? $type : 'simple';

			$existing_post = get_page_by_path( $slug, OBJECT, 'product' );
			$existing_id   = $existing_post && isset( $existing_post->ID ) ? (int) $existing_post->ID : 0;
			$existing      = $existing_id > 0 ? wc_get_product( $existing_id ) : false;

			if ( $existing_id > 0 && $existing && method_exists( $existing, 'get_type' ) && $existing->get_type() !== $type ) {
				wp_delete_post( $existing_id, true );
				$existing_id = 0;
				$existing    = false;
			}

			if ( $existing_id > 0 && $existing ) {
				$product = $existing;
			} else {
				$product = ( 'variable' === $type ) ? new WC_Product_Variable() : new WC_Product_Simple();
			}

			$name = isset( $product_data['name'] ) ? (string) $product_data['name'] : $slug;
			$product->set_name( $name );
			$product->set_slug( $slug );
			$product->set_status( isset( $product_data['status'] ) ? (string) $product_data['status'] : 'publish' );
			$product->set_description( isset( $product_data['description'] ) ? (string) $product_data['description'] : '' );
			$product->set_short_description( isset( $product_data['short_description'] ) ? (string) $product_data['short_description'] : '' );
			$product->set_menu_order( isset( $product_data['menu_order'] ) ? (int) $product_data['menu_order'] : 0 );
			$this->set_sku_safe( $product, isset( $product_data['sku'] ) ? (string) $product_data['sku'] : '' );

			$category_ids = array();
			if ( isset( $product_data['categories'] ) && is_array( $product_data['categories'] ) ) {
				foreach ( $product_data['categories'] as $cat_slug ) {
					$cat_slug = sanitize_title( (string) $cat_slug );
					if ( '' === $cat_slug ) {
						continue;
					}
					if ( isset( $category_map[ $cat_slug ] ) ) {
						$category_ids[] = (int) $category_map[ $cat_slug ];
					}
				}
			}
			if ( ! empty( $category_ids ) ) {
				$product->set_category_ids( array_values( array_unique( $category_ids ) ) );
			}

			if ( 'simple' === $type ) {
				$product->set_regular_price( isset( $product_data['regular_price'] ) ? (string) $product_data['regular_price'] : '' );
				$product->set_sale_price( isset( $product_data['sale_price'] ) ? (string) $product_data['sale_price'] : '' );
				$product->set_price( isset( $product_data['price'] ) ? (string) $product_data['price'] : '' );
			}

			if ( 'variable' === $type ) {
				$attributes = $this->build_variable_attributes( isset( $product_data['attributes'] ) && is_array( $product_data['attributes'] ) ? $product_data['attributes'] : array() );
				if ( ! is_wp_error( $attributes ) ) {
					$product->set_attributes( $attributes );
				}
			}

			$featured_id = 0;
			if ( isset( $product_data['image']['id'] ) ) {
				$old_image_id = (string) $product_data['image']['id'];
				$featured_id  = isset( $image_id_map[ $old_image_id ] ) ? (int) $image_id_map[ $old_image_id ] : 0;
			}
			if ( $featured_id > 0 ) {
				$product->set_image_id( $featured_id );
			}

			$gallery_ids = array();
			if ( isset( $product_data['gallery'] ) && is_array( $product_data['gallery'] ) ) {
				foreach ( $product_data['gallery'] as $gallery ) {
					if ( ! is_array( $gallery ) || ! isset( $gallery['id'] ) ) {
						continue;
					}
					$old_gallery_id = (string) $gallery['id'];
					if ( isset( $image_id_map[ $old_gallery_id ] ) ) {
						$gallery_ids[] = (int) $image_id_map[ $old_gallery_id ];
					}
				}
			}
			if ( ! empty( $gallery_ids ) ) {
				$product->set_gallery_image_ids( array_values( array_unique( $gallery_ids ) ) );
			}

			$product_id = (int) $product->save();
			if ( $product_id <= 0 ) {
				/* translators: %s: Product name. */
				return new WP_Error( 'foodord_demo_import_product_failed', sprintf( __( 'Could not save product: %s', 'foodord' ), $name ) );
			}

			update_post_meta( $product_id, '_foodord_demo_imported', '1' );
			if ( isset( $product_data['id'] ) ) {
				update_post_meta( $product_id, '_foodord_demo_original_product_id', (string) $product_data['id'] );
			}

			if ( isset( $product_data['topping_sets'] ) && is_array( $product_data['topping_sets'] ) ) {
				update_post_meta( $product_id, '_foodord_topping_sets', $product_data['topping_sets'] );
			}

			if ( isset( $product_data['meta'] ) && is_array( $product_data['meta'] ) ) {
				foreach ( $product_data['meta'] as $meta_key => $meta_value ) {
					$meta_key = is_string( $meta_key ) ? $meta_key : '';
					if ( '' === $meta_key ) {
						continue;
					}
					update_post_meta( $product_id, $meta_key, $meta_value );
				}
			}

			$this->counts['products']++;

			if ( 'variable' === $type && $product instanceof WC_Product_Variable ) {
				$variations = isset( $product_data['variations'] ) && is_array( $product_data['variations'] ) ? $product_data['variations'] : array();
				$variation_result = $this->import_variations( $product, $variations );
				if ( is_wp_error( $variation_result ) ) {
					return $variation_result;
				}
			}
		}

		return true;
	}

	/**
	 * Build variable product attributes.
	 *
	 * @param array $attributes Attributes payload.
	 * @return array<int, WC_Product_Attribute>|WP_Error
	 */
	private function build_variable_attributes( array $attributes ) {
		if ( ! class_exists( 'WC_Product_Attribute' ) ) {
			return new WP_Error( 'foodord_demo_import_attributes_missing', __( 'WooCommerce product attributes are not available.', 'foodord' ) );
		}

		$result = array();
		foreach ( $attributes as $attribute_data ) {
			if ( ! is_array( $attribute_data ) ) {
				continue;
			}
			$name = isset( $attribute_data['name'] ) ? (string) $attribute_data['name'] : '';
			if ( '' === trim( $name ) ) {
				continue;
			}

			$options = array();
			if ( isset( $attribute_data['options'] ) && is_array( $attribute_data['options'] ) ) {
				foreach ( $attribute_data['options'] as $option ) {
					$option = (string) $option;
					if ( '' !== trim( $option ) ) {
						$options[] = $option;
					}
				}
			}

			$attribute = new WC_Product_Attribute();
			$attribute->set_id( 0 );
			$attribute->set_name( $name );
			$attribute->set_options( $options );
			$attribute->set_visible( isset( $attribute_data['visible'] ) ? (bool) $attribute_data['visible'] : true );
			$attribute->set_variation( isset( $attribute_data['variation'] ) ? (bool) $attribute_data['variation'] : true );

			$result[] = $attribute;
		}

		return $result;
	}

	/**
	 * Import variations for variable product.
	 *
	 * @param WC_Product_Variable $product Variable product.
	 * @param array $variations Variations payload.
	 * @return true|WP_Error
	 */
	private function import_variations( WC_Product_Variable $product, array $variations ) {
		$existing_children = $product->get_children();
		if ( is_array( $existing_children ) ) {
			foreach ( $existing_children as $child_id ) {
				wp_delete_post( (int) $child_id, true );
			}
		}

		foreach ( $variations as $variation_data ) {
			if ( ! is_array( $variation_data ) ) {
				continue;
			}

			$variation = new WC_Product_Variation();
			$variation->set_parent_id( (int) $product->get_id() );
			$variation->set_status( 'publish' );
			$this->set_sku_safe( $variation, isset( $variation_data['sku'] ) ? (string) $variation_data['sku'] : '' );
			$variation->set_regular_price( isset( $variation_data['regular_price'] ) ? (string) $variation_data['regular_price'] : '' );
			$variation->set_sale_price( isset( $variation_data['sale_price'] ) ? (string) $variation_data['sale_price'] : '' );
			$variation->set_price( isset( $variation_data['price'] ) ? (string) $variation_data['price'] : '' );
			$variation->set_stock_status( isset( $variation_data['stock_status'] ) ? (string) $variation_data['stock_status'] : 'instock' );
			$variation->set_description( isset( $variation_data['description'] ) ? (string) $variation_data['description'] : '' );

			$attrs = isset( $variation_data['attributes'] ) && is_array( $variation_data['attributes'] ) ? $variation_data['attributes'] : array();
			$variation->set_attributes( $attrs );

			$variation_id = (int) $variation->save();
			if ( $variation_id <= 0 ) {
				return new WP_Error( 'foodord_demo_import_variation_failed', __( 'Could not create product variations.', 'foodord' ) );
			}

			$this->counts['variations']++;
		}

		if ( class_exists( 'WC_Product_Variable' ) && method_exists( 'WC_Product_Variable', 'sync' ) ) {
			WC_Product_Variable::sync( (int) $product->get_id() );
		}

		return true;
	}

	/**
	 * Create or update the Order Page.
	 */
	private function create_or_update_order_page(): int {
		$page_slug = 'order-page';
		$content   = "[foodord_products]\n[foodord_card]\n";

		$existing = get_page_by_path( $page_slug, OBJECT, 'page' );
		$postarr  = array(
			'post_title'     => 'Order Page',
			'post_name'      => $page_slug,
			'post_type'      => 'page',
			'post_status'    => 'publish',
			'post_content'   => $content,
			'comment_status' => 'closed',
		);

		if ( $existing && isset( $existing->ID ) ) {
			$postarr['ID'] = (int) $existing->ID;
			$result        = wp_update_post( $postarr, true );
			return is_wp_error( $result ) ? (int) $existing->ID : (int) $result;
		}

		$result = wp_insert_post( $postarr, true );
		if ( is_wp_error( $result ) ) {
			return 0;
		}

		return (int) $result;
	}

	/**
	 * Set static front page.
	 *
	 * @param int $page_id Front page ID.
	 */
	private function set_static_front_page( int $page_id ): void {
		if ( $page_id <= 0 ) {
			return;
		}
		update_option( 'show_on_front', 'page' );
		update_option( 'page_on_front', $page_id );
		update_option( 'page_for_posts', 0 );
	}

}
