<?php
/** API Site Options Controller
 *
 * @package BwWinnersGlobalSite
 * @subpackage API
 */

namespace BwWinnersGlobalSite\API;

if ( ! class_exists( __NAMESPACE__ . '\Migrate_Post_Controller' ) ) {
	/**
	 * Controller for BwWinnersGlobalSite Migration routes and endpoints
	 */
	class Migrate_Post_Controller {

		/**
		 * REST API namespace
		 *
		 * @var string
		 */
		public $namespace;

		/**
		 * Controller's resource name
		 *
		 * @var string
		 */
		public $resource_name;

		/**
		 * Controller's resource route
		 *
		 * @var string
		 */
		public $resource_route;

		/**
		 * Initializes properties and adds hooks.
		 */
		public function __construct() {
			$this->namespace = \BwWinnersGlobalSite\API_NAMESPACE;

			$this->resource_name = 'migrate-post';

			$this->resource_route = '/' . $this->resource_name;

			add_action( 'rest_api_init', array( $this, 'register_routes' ) );
		}


		/**
		 * Registers routes for the BwWinnersGlobalSite Migration
		 */
		public function register_routes() {

			register_rest_route(
				$this->namespace,
				$this->resource_route . '/settings',
				array(
					'methods'             => array( 'GET' ),
					'callback'            => array( $this, 'settings' ),
					'permission_callback' => array( $this, 'permissions_check' ),
				)
			);

			register_rest_route(
				$this->namespace,
				$this->resource_route . '/migrate',
				array(
					'methods'             => array( 'POST' ),
					'callback'            => array( $this, 'migrate' ),
					'permission_callback' => array( $this, 'permissions_check' ),
				)
			);
		}

		/**
		 * Returns true if user can use the BwWinnersGlobalSite Options Page features
		 *
		 * @return boolean
		 */
		public function permissions_check() {
			return current_user_can( 'manage_options' );
		}

		/**
		 * Updates the BwWinnersGlobalSite plugin get settings info
		 *
		 * @param WP_REST_Request $request        API request.
		 *
		 * @return WP_REST_Response|WP_Error|WP_HTTP_Response|mixed
		 */
		public function settings ( $request ) {

			$settings = [
				'blog_ids' => []
			];

			$sites = get_sites();

			foreach ( $sites as $site ) {
				$settings['blog_ids'][] = $site->blog_id;
			}

			return rest_ensure_response( $settings );
		}

		/**
		 * Runs a manual sync cleanup step
		 *
		 * @param WP_REST_Request $request        API request.
		 *
		 * @return WP_REST_Response|WP_Error|WP_HTTP_Response|mixed
		 */
		public function migrate ( $request ) {

			$data = $request->get_json_params();

			$source_blog_id = $data['blog_id'];
			$page = $data['page'] ?  $data['page'] : 1;
			$per_page = isset( $data['per_page'] ) ?  $data['per_page'] : 50;

			$response = [
				'source_blog_id' => $source_blog_id,
				'page' => $page,
				'per_page' => $per_page
			];


			try {
				$results = $this->migrate_page( $source_blog_id, $page, $per_page );
				$response['total_pages'] = $results['total_pages'];
				$response['messages'] = $results['messages'];
			} catch ( \Throwable $e ) {
				$response['status'] = 500;
				$response['error'] = $e->getMessage();

				return wp_send_json_error( new \WP_Error(
					'internal_server_error',
					$e->getMessage(),
					$response
				) );
			}

			return rest_ensure_response( $response );			
		}

		public function migrate_page ( $site_id, $page, $per_page ) {
			global $wpdb;

			$results = [
				'messages' => []
			];

			$source_blog_id = $site_id;
			$target_blog_id = get_current_site()->blog_id;

			$rows = $wpdb->get_results(
				$wpdb->prepare(
					"SELECT product.id AS product_id, product.name AS product_name, brand.id AS brand_id, brand.name AS brand_name
						FROM {$wpdb->get_blog_prefix($source_blog_id)}bw_winners_products product
						INNER JOIN  {$wpdb->get_blog_prefix($source_blog_id)}bw_winners_brands brand ON product.brand_id = brand.id
						LIMIT %d, %d",
					[ ( $page - 1 ) * $per_page, $per_page ]
				),
				ARRAY_A
			);

			if ( $wpdb->last_error ) {
				throw new \Exception( $wpdb->last_error );
			}

			$count = intval( $wpdb->get_var(
				"SELECT COUNT(*)
					FROM {$wpdb->get_blog_prefix($source_blog_id)}bw_winners_products product
					INNER JOIN  {$wpdb->get_blog_prefix($source_blog_id)}bw_winners_brands brand ON product.brand_id = brand.id"
			) );

			if ( $wpdb->last_error ) {
				throw new \Exception( $wpdb->last_error );
			}

			$results['total_pages'] = ceil( $count / $per_page );

			foreach ( $rows as $index => $source ) {
				$target = $wpdb->get_row(
					$wpdb->prepare(
						"SELECT product.id AS product_id, brand.id AS brand_id
						FROM {$wpdb->prefix}bw_winners_v2_products product
						INNER JOIN {$wpdb->prefix}bw_winners_v2_brands brand
						WHERE product.name = %s AND brand.name = %s",
						[ $source['product_name'], $source['brand_name'] ]
					),
					ARRAY_A
				);

				$results['messages'][] = "Populating brand {$source['brand_name']} and product {$source['product_name']}.";

				if ( $target ) {
					$this->migrate_post(
						$source_blog_id,
						$source['product_id'],
						$target_blog_id,
						$target['product_id'],
						true
					);

					$this->migrate_post(
						$source_blog_id,
						$source['brand_id'],
						$target_blog_id,
						$target['brand_id'],
						true
					);
				}
			}
			return $results;
		}

		public function migrate_post(
			$source_blog_id,
			$source_post_id,
			$target_blog_id,
			$target_post_id,
			$include_core_taxonomies = false
		) {
			/**
			 * -------------------------------------------------
			 * Copy Featured Image
			 * -------------------------------------------------
			 */
			$this->copy_featured_image_between_posts( $source_blog_id, $source_post_id, $target_blog_id, $target_post_id );

			/**
			 * -------------------------------------------------
			 * Get source post data
			 * -------------------------------------------------
			 */
			switch_to_blog( $source_blog_id );
			$source_post = get_post( $source_post_id );
			if ( ! $source_post ) {
				restore_current_blog();
				return false;
			}

			$acf_fields = function_exists( 'get_fields' ) ? get_fields( $source_post_id ) : [];
			$all_meta   = get_post_meta( $source_post_id );
			$taxonomies = get_object_taxonomies( $source_post->post_type, 'objects' );
			restore_current_blog();

			/**
			 * -------------------------------------------------
			 * Update target post
			 * -------------------------------------------------
			 */
			switch_to_blog( $target_blog_id );

			// 1. Core post fields
			wp_update_post( [
				'ID'           => $target_post_id,
				'post_title'   => $source_post->post_title,
				'post_content' => $source_post->post_content,
				'post_excerpt' => $source_post->post_excerpt,
			] );

			// 2. ACF fields (multisite-safe)

			$migrated_acf_fields = [];

			if ( function_exists( 'get_fields' ) && function_exists( 'update_field' ) && ! empty( $acf_fields ) ) {
				// Get all ACF fields from source blog first
				switch_to_blog( $source_blog_id );
				$acf_fields_source = get_fields( $source_post_id ) ?: [];
				restore_current_blog();

				foreach ( $acf_fields_source as $field_name => $value ) {
					
					$migrated_acf_fields[] = $field_name;

					switch_to_blog( $source_blog_id );
					$field_object_source = function_exists('get_field_object') ? get_field_object($field_name, $source_post_id) : null;
					restore_current_blog();

					if ( ! $field_object_source ) {
						continue;
					}

					// Handle image fields
					if ( $field_object_source['type'] === 'image' && ! empty( $value ) ) {
						$source_attachment_id = is_numeric($value) ? (int)$value : (is_array($value) && isset($value['ID']) ? (int)$value['ID'] : null);
						if ( $source_attachment_id ) {
							$new_attachment_id = $this->copy_attachment_between_blogs(
								$source_blog_id,
								$source_attachment_id,
								$target_blog_id,
								$target_post_id
							);

							if ( $new_attachment_id ) {
								// Check field return type on target blog
								switch_to_blog( $target_blog_id );
								$field_object_target = get_field_object($field_name, $target_post_id);
								$return_format = $field_object_target['return_format'] ?? 'id';
								$update_value = $return_format === 'id' ? $new_attachment_id : [
									'ID'          => $new_attachment_id,
									'url'         => wp_get_attachment_url($new_attachment_id),
									'title'       => get_post($new_attachment_id)->post_title ?? '',
									'alt'         => get_post_meta($new_attachment_id, '_wp_attachment_image_alt', true),
									'caption'     => get_post($new_attachment_id)->post_excerpt ?? '',
									'description' => get_post($new_attachment_id)->post_content ?? '',
								];
								
								update_field($field_object_target['key'], $update_value, $target_post_id);
								restore_current_blog();
								continue;
							}
						}
					}

					// Default copy for non-image fields
					switch_to_blog( $target_blog_id );
					update_field($field_name, $value, $target_post_id);
					restore_current_blog();
				}
			}

			// 3. Non-ACF post meta
			foreach ( $all_meta as $meta_key => $values ) {
				if ( str_starts_with( $meta_key, '_' ) || in_array( $meta_key, [ 'edit_lock', 'edit_last' ], true ) ) {
					continue;
				}

				// Skip fields that were migrated via ACF
				if ( in_array( $meta_key, $migrated_acf_fields, true ) ) {
					continue;
				}

				delete_post_meta( $target_post_id, $meta_key );
				foreach ( $values as $value ) {
					add_post_meta( $target_post_id, $meta_key, maybe_unserialize( $value ) );
				}
			}

			// 4. Taxonomies
			foreach ( $taxonomies as $taxonomy => $tax_obj ) {

				if ( ! $include_core_taxonomies && in_array( $taxonomy, [ 'category', 'post_tag' ], true ) ) {
					continue;
				}

				switch_to_blog( $source_blog_id );
				$source_terms = wp_get_object_terms( $source_post_id, $taxonomy, [ 'orderby' => 'term_id' ] );
				restore_current_blog();

				if ( empty( $source_terms ) || is_wp_error( $source_terms ) ) {
					continue;
				}

				$target_term_ids = [];
				foreach ( $source_terms as $term ) {
					$target_term_id = $this->migrate_term( $term, $taxonomy, $target_blog_id );
					if ( $target_term_id ) {
						$target_term_ids[] = $target_term_id;
					}
				}

				if ( $target_term_ids ) {
					wp_set_object_terms( $target_post_id, $target_term_ids, $taxonomy, false );
				}
			}

			restore_current_blog();

			return true;
		}

		public function migrate_term( $term, $taxonomy, $target_blog_id ) {

			// Check if term already exists
			switch_to_blog( $target_blog_id );

			$existing = get_term_by( 'slug', $term->slug, $taxonomy );
			if ( $existing ) {
				restore_current_blog();
				return (int) $existing->term_id;
			}

			restore_current_blog();

			// Create parent first (if any)
			$parent_id = 0;
			if ( $term->parent ) {
				$parent = get_term( $term->parent, $taxonomy );
				if ( $parent && ! is_wp_error( $parent ) ) {
					$parent_id = $this->migrate_term( $parent, $taxonomy, $target_blog_id );
				}
			}

			// Create term
			switch_to_blog( $target_blog_id );

			$result = wp_insert_term(
				$term->name,
				$taxonomy,
				[
					'slug'        => $term->slug,
					'description' => $term->description,
					'parent'      => $parent_id,
				]
			);

			restore_current_blog();

			if ( is_wp_error( $result ) ) {
				return false;
			}

			return (int) $result['term_id'];
		}

		public function copy_attachment_between_blogs(
			$source_blog_id,
			$attachment_id,
			$target_blog_id,
			$parent_post_id = 0
		) {
			// Same blog → reuse
			if ( $source_blog_id === $target_blog_id ) {
				return $attachment_id;
			}

			// -------------------------------------------------
			// Check if already migrated
			// -------------------------------------------------
			switch_to_blog( $target_blog_id );

			$existing = get_posts( [
				'post_type'   => 'attachment',
				'post_status' => 'inherit',
				'meta_key'    => '_migrated_from_attachment',
				'meta_value'  => (string) $attachment_id,
				'fields'      => 'ids',
				'numberposts' => 1,
			] );

			if ( ! empty( $existing ) ) {
				restore_current_blog();
				return (int) $existing[0];
			}

			restore_current_blog();

			// -------------------------------------------------
			// Load source attachment
			// -------------------------------------------------
			switch_to_blog( $source_blog_id );

			$attachment = get_post( $attachment_id );
			$file_path  = get_attached_file( $attachment_id );

			restore_current_blog();

			if ( ! $attachment || ! file_exists( $file_path ) ) {
				return false;
			}

			// -------------------------------------------------
			// Copy file to target blog
			// -------------------------------------------------
			switch_to_blog( $target_blog_id );

			$upload = wp_upload_bits(
				basename( $file_path ),
				null,
				file_get_contents( $file_path )
			);

			if ( ! empty( $upload['error'] ) ) {
				restore_current_blog();
				return false;
			}

			// Insert attachment
			$new_attachment_id = wp_insert_attachment(
				[
					'post_title'     => $attachment->post_title,
					'post_content'   => $attachment->post_content,
					'post_mime_type' => $attachment->post_mime_type,
					'post_status'    => 'inherit',
				],
				$upload['file'],
				$parent_post_id
			);

			if ( ! $new_attachment_id ) {
				restore_current_blog();
				return false;
			}

			// -------------------------------------------------
			// Record source → target mapping (IDEMPOTENCY)
			// -------------------------------------------------
			add_post_meta(
				$new_attachment_id,
				'_migrated_from_attachment',
				(string) $attachment_id,
				true
			);

			// -------------------------------------------------
			// Generate metadata **while still in target blog**
			// -------------------------------------------------
			require_once ABSPATH . 'wp-admin/includes/image.php';
			$metadata = wp_generate_attachment_metadata(
				$new_attachment_id,
				$upload['file']
			);
			wp_update_attachment_metadata( $new_attachment_id, $metadata );

			// -------------------------------------------------
			// Now restore the original blog
			// -------------------------------------------------
			restore_current_blog();

			return $new_attachment_id;
		}

		public function copy_featured_image_between_posts(
			$source_blog_id,
			$source_post_id,
			$target_blog_id,
			$target_post_id
		) {
			// Skip if target already has a featured image
			switch_to_blog( $target_blog_id );
			if ( has_post_thumbnail( $target_post_id ) ) {
				restore_current_blog();
				return true;
			}
			restore_current_blog();

			// Get source thumbnail
			switch_to_blog( $source_blog_id );
			$thumbnail_id = get_post_thumbnail_id( $source_post_id );
			restore_current_blog();

			if ( ! $thumbnail_id ) {
				return false;
			}

			$new_attachment_id = $this->copy_attachment_between_blogs(
				$source_blog_id,
				$thumbnail_id,
				$target_blog_id,
				$target_post_id
			);

			if ( ! $new_attachment_id ) {
				return false;
			}

			switch_to_blog( $target_blog_id );
			set_post_thumbnail( $target_post_id, $new_attachment_id );
			restore_current_blog();

			return true;
		}
	}
}
