<?php
/**
 * Import format detector + normalizer
 *
 * Accepts raw JSON (any supported SlideMind export format) and returns an
 * ImportManifest. Supported inputs:
 *
 * - `format: "slidemind-export-v1"` (FullExporter, flat sections)
 * - `slidemind_export_version: "2.0"` + `export_type: "bulk"` (BulkDataManager hierarchical)
 * - `slidemind_export_version: "2.0"` + `export_type: "courses|modules|slides"` (BulkDataManager per-type)
 * - `slidemind_export_version: "1.0"` + per-item / per-type (ConfigExporter)
 *
 * @package SlideMind\Core
 * @since   0.6.0
 */

namespace SlideMind\Core;

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

class ImportParser {

	const FORMAT_V1      = 'slidemind-export-v1';
	const FORMAT_V2_BULK = 'v2.0-bulk';

	/**
	 * Parse raw JSON into an ImportManifest.
	 *
	 * @param string $json Raw file or textarea contents.
	 * @return ImportManifest|\WP_Error
	 */
	public function parse( string $json ): ImportManifest|\WP_Error {
		$data = json_decode( $json, true );
		if ( ! is_array( $data ) ) {
			return new \WP_Error( 'invalid_json', __( 'The file is not a valid JSON document.', 'slidemind' ) );
		}

		if ( isset( $data['format'] ) && $data['format'] === self::FORMAT_V1 ) {
			return $this->parse_v1( $data );
		}

		$version = isset( $data['slidemind_export_version'] ) ? (string) $data['slidemind_export_version'] : '';
		$type    = isset( $data['export_type'] ) ? (string) $data['export_type'] : '';

		if ( $version === '2.0' && $type === 'bulk' ) {
			return $this->parse_v2_bulk( $data );
		}

		$legacy_types = [ 'course', 'formation', 'courses', 'module', 'modules', 'slide', 'slides' ];
		if ( in_array( $version, [ '1.0', '2.0' ], true ) && in_array( $type, $legacy_types, true ) ) {
			return $this->parse_v1_legacy( $data, $version );
		}

		return new \WP_Error(
			'unsupported_format',
			__( 'Unrecognized export format. Supported: slidemind-export-v1, v2.0 bulk backup, v1.0/v2.0 per-item export.', 'slidemind' )
		);
	}

	// -------------------------------------------------------------------
	// slidemind-export-v1 (FullExporter)
	// -------------------------------------------------------------------

	private function parse_v1( array $data ): ImportManifest {
		$manifest                   = new ImportManifest();
		$manifest->source_format    = self::FORMAT_V1;
		$manifest->generated_at     = isset( $data['generated_at'] ) ? (string) $data['generated_at'] : '';
		$manifest->source_site_url  = isset( $data['site_url'] ) ? (string) $data['site_url'] : '';
		$manifest->plugin_version   = isset( $data['plugin_version'] ) ? (string) $data['plugin_version'] : '';

		$sections = isset( $data['sections'] ) && is_array( $data['sections'] ) ? $data['sections'] : [];

		// Courses — file_ref = course_<source_id>
		foreach ( $sections['courses'] ?? [] as $course ) {
			if ( ! is_array( $course ) ) {
				continue;
			}
			$manifest->courses[] = [
				'file_ref'   => 'course_' . (int) ( $course['id'] ?? 0 ),
				'title'      => (string) ( $course['title'] ?? '' ),
				'status'     => (string) ( $course['status'] ?? 'publish' ),
				'theme'      => (string) ( $course['theme'] ?? '' ),
				'objectives' => (string) ( $course['objectives'] ?? '' ),
				'content'    => (string) ( $course['content'] ?? '' ),
			];
		}

		// Modules — file_ref = module_<source_id>; parent_course_ref mapped from parent_course_id
		foreach ( $sections['modules'] ?? [] as $module ) {
			if ( ! is_array( $module ) ) {
				continue;
			}
			$parent_course_id = (int) ( $module['parent_course_id'] ?? 0 );
			$manifest->modules[] = [
				'file_ref'          => 'module_' . (int) ( $module['id'] ?? 0 ),
				'parent_course_ref' => $parent_course_id > 0 ? 'course_' . $parent_course_id : null,
				'title'             => (string) ( $module['title'] ?? '' ),
				'status'            => (string) ( $module['status'] ?? 'publish' ),
				'subject'           => (string) ( $module['subject'] ?? '' ),
				'context'           => (string) ( $module['context'] ?? '' ),
			];
		}

		// Slides — same pattern
		foreach ( $sections['slides'] ?? [] as $slide ) {
			if ( ! is_array( $slide ) ) {
				continue;
			}
			$parent_module_id = (int) ( $slide['parent_module_id'] ?? 0 );
			$parent_course_id = (int) ( $slide['parent_course_id'] ?? 0 );
			$slide_payload = $slide;
			unset( $slide_payload['id'], $slide_payload['parent_module_id'], $slide_payload['parent_course_id'] );
			$slide_payload['file_ref']          = 'slide_' . (int) ( $slide['id'] ?? 0 );
			$slide_payload['parent_module_ref'] = $parent_module_id > 0 ? 'module_' . $parent_module_id : null;
			$slide_payload['parent_course_ref'] = $parent_course_id > 0 ? 'course_' . $parent_course_id : null;
			$manifest->slides[] = $slide_payload;
		}

		// Templates — file_ref prefers slug when available (slug-based crc32 id from FullExporter)
		foreach ( $sections['templates'] ?? [] as $i => $tpl ) {
			if ( ! is_array( $tpl ) ) {
				continue;
			}
			$slug = isset( $tpl['slug'] ) ? (string) $tpl['slug'] : '';
			$tpl_payload             = $tpl;
			$tpl_payload['file_ref'] = 'template_' . ( $slug !== '' ? preg_replace( '/[^A-Za-z0-9]/', '_', $slug ) : $i );
			$manifest->templates[]   = $tpl_payload;
		}

		// Memory variables — carried as-is (never imported)
		foreach ( $sections['memory_variables'] ?? [] as $mv ) {
			if ( is_array( $mv ) ) {
				$manifest->memory_variables[] = $mv;
			}
		}

		// Memory definitions
		foreach ( $sections['memory_definitions'] ?? [] as $def ) {
			if ( is_array( $def ) ) {
				$manifest->memory_definitions[] = $def;
			}
		}

		// Settings
		if ( isset( $sections['settings'] ) && is_array( $sections['settings'] ) ) {
			$manifest->settings = $sections['settings'];
		}

		return $manifest;
	}

	// -------------------------------------------------------------------
	// v2.0 bulk (BulkDataManager)
	// -------------------------------------------------------------------

	private function parse_v2_bulk( array $data ): ImportManifest {
		$manifest                  = new ImportManifest();
		$manifest->source_format   = self::FORMAT_V2_BULK;
		$manifest->generated_at    = isset( $data['exported_at'] ) ? (string) $data['exported_at'] : '';
		$manifest->source_site_url = '';
		$manifest->plugin_version  = isset( $data['plugin_version'] ) ? (string) $data['plugin_version'] : '';

		$course_index = 0;
		$module_index = 0;
		$slide_index  = 0;

		// Courses — each carries nested 'modules' with nested 'slides'
		foreach ( $data['courses'] ?? [] as $course_export ) {
			if ( ! is_array( $course_export ) ) {
				continue;
			}
			$course_ref        = 'course_' . $course_index;
			$course_payload    = $course_export['course'] ?? $course_export['formation'] ?? [];
			$manifest->courses[] = [
				'file_ref'   => $course_ref,
				'title'      => (string) ( $course_payload['title'] ?? '' ),
				'status'     => 'publish',
				'theme'      => (string) ( $course_payload['theme'] ?? '' ),
				'objectives' => (string) ( $course_payload['objectives'] ?? '' ),
				'content'    => (string) ( $course_payload['content'] ?? '' ),
			];
			$course_index++;

			foreach ( $course_export['modules'] ?? [] as $module ) {
				if ( ! is_array( $module ) ) {
					continue;
				}
				$module_ref         = 'module_' . $module_index;
				$manifest->modules[] = [
					'file_ref'          => $module_ref,
					'parent_course_ref' => $course_ref,
					'title'             => (string) ( $module['title'] ?? '' ),
					'status'            => 'publish',
					'subject'           => (string) ( $module['subject'] ?? '' ),
					'context'           => (string) ( $module['context'] ?? '' ),
				];
				$module_index++;

				foreach ( $module['slides'] ?? [] as $slide ) {
					if ( ! is_array( $slide ) ) {
						continue;
					}
					$slide_ref                 = 'slide_' . $slide_index;
					$slide_payload             = $slide;
					$slide_payload['file_ref']          = $slide_ref;
					$slide_payload['parent_module_ref'] = $module_ref;
					$slide_payload['parent_course_ref'] = $course_ref;
					$manifest->slides[]        = $slide_payload;
					$slide_index++;
				}
			}
		}

		// Orphan modules — carry parent_course_ref = null → holder at import
		foreach ( $data['orphan_modules'] ?? [] as $orphan_export ) {
			if ( ! is_array( $orphan_export ) ) {
				continue;
			}
			$module_ref          = 'module_' . $module_index;
			$module_payload      = $orphan_export['module'] ?? [];
			$manifest->modules[] = [
				'file_ref'          => $module_ref,
				'parent_course_ref' => null,
				'title'             => (string) ( $module_payload['title'] ?? '' ),
				'status'            => 'publish',
				'subject'           => (string) ( $module_payload['subject'] ?? '' ),
				'context'           => (string) ( $module_payload['context'] ?? '' ),
			];
			$module_index++;

			foreach ( $orphan_export['slides'] ?? [] as $slide ) {
				if ( ! is_array( $slide ) ) {
					continue;
				}
				$slide_ref                          = 'slide_' . $slide_index;
				$slide_payload                      = $slide;
				$slide_payload['file_ref']          = $slide_ref;
				$slide_payload['parent_module_ref'] = $module_ref;
				$slide_payload['parent_course_ref'] = null;
				$manifest->slides[]                 = $slide_payload;
				$slide_index++;
			}
		}

		// Orphan slides — parent refs null
		foreach ( $data['orphan_slides'] ?? [] as $slide_export ) {
			if ( ! is_array( $slide_export ) ) {
				continue;
			}
			$slide_payload = isset( $slide_export['slide'] ) && is_array( $slide_export['slide'] ) ? $slide_export['slide'] : $slide_export;
			$slide_ref                          = 'slide_' . $slide_index;
			$slide_payload['file_ref']          = $slide_ref;
			$slide_payload['parent_module_ref'] = null;
			$slide_payload['parent_course_ref'] = null;
			$manifest->slides[]                 = $slide_payload;
			$slide_index++;
		}

		foreach ( $data['templates'] ?? [] as $i => $tpl ) {
			if ( ! is_array( $tpl ) ) {
				continue;
			}
			$tpl_payload              = $tpl;
			$tpl_payload['file_ref']  = 'template_' . $i;
			$manifest->templates[]    = $tpl_payload;
		}

		foreach ( $data['memory_definitions'] ?? [] as $def ) {
			if ( is_array( $def ) ) {
				$manifest->memory_definitions[] = $def;
			}
		}

		if ( isset( $data['settings'] ) && is_array( $data['settings'] ) ) {
			$manifest->settings = $data['settings'];
		}

		return $manifest;
	}

	// -------------------------------------------------------------------
	// v1.0 legacy per-item / per-type (ConfigExporter)
	// -------------------------------------------------------------------

	private function parse_v1_legacy( array $data, string $version = '1.0' ): ImportManifest {
		$type                    = isset( $data['export_type'] ) ? (string) $data['export_type'] : '';
		$manifest                = new ImportManifest();
		$manifest->source_format = 'v' . $version . '-' . $type;
		$manifest->generated_at  = isset( $data['exported_at'] ) ? (string) $data['exported_at'] : '';

		switch ( $type ) {
			case 'course':
			case 'formation':
				$course_payload = $data['course'] ?? $data['formation'] ?? [];
				if ( ! is_array( $course_payload ) ) {
					$course_payload = [];
				}
				$course_ref     = 'course_0';
				$manifest->courses[] = [
					'file_ref'   => $course_ref,
					'title'      => (string) ( $course_payload['title'] ?? '' ),
					'status'     => 'publish',
					'theme'      => (string) ( $course_payload['theme'] ?? '' ),
					'objectives' => (string) ( $course_payload['objectives'] ?? '' ),
					'content'    => (string) ( $course_payload['content'] ?? '' ),
				];

				$module_index = 0;
				$slide_index  = 0;
				foreach ( $data['modules'] ?? [] as $module ) {
					if ( ! is_array( $module ) ) {
						continue;
					}
					$module_ref          = 'module_' . $module_index;
					$manifest->modules[] = [
						'file_ref'          => $module_ref,
						'parent_course_ref' => $course_ref,
						'title'             => (string) ( $module['title'] ?? '' ),
						'status'            => 'publish',
						'subject'           => (string) ( $module['subject'] ?? '' ),
						'context'           => (string) ( $module['context'] ?? '' ),
					];
					$module_index++;

					foreach ( $module['slides'] ?? [] as $slide ) {
						if ( ! is_array( $slide ) ) {
							continue;
						}
						$slide_payload                      = $slide;
						$slide_payload['file_ref']          = 'slide_' . $slide_index;
						$slide_payload['parent_module_ref'] = $module_ref;
						$slide_payload['parent_course_ref'] = $course_ref;
						$manifest->slides[]                 = $slide_payload;
						$slide_index++;
					}
				}
				break;

			case 'courses':
				foreach ( $data['courses'] ?? [] as $i => $course_payload ) {
					if ( ! is_array( $course_payload ) ) {
						continue;
					}
					$manifest->courses[] = [
						'file_ref'   => 'course_' . $i,
						'title'      => (string) ( $course_payload['title'] ?? '' ),
						'status'     => 'publish',
						'theme'      => (string) ( $course_payload['theme'] ?? '' ),
						'objectives' => (string) ( $course_payload['objectives'] ?? '' ),
						'content'    => (string) ( $course_payload['content'] ?? '' ),
					];
				}
				break;

			case 'module':
				$module_payload = $data['module'] ?? [];
				if ( ! is_array( $module_payload ) ) {
					$module_payload = [];
				}
				$module_ref           = 'module_0';
				$manifest->modules[]  = [
					'file_ref'          => $module_ref,
					'parent_course_ref' => null,
					'title'             => (string) ( $module_payload['title'] ?? '' ),
					'status'            => 'publish',
					'subject'           => (string) ( $module_payload['subject'] ?? '' ),
					'context'           => (string) ( $module_payload['context'] ?? '' ),
				];

				$slide_index = 0;
				foreach ( $data['slides'] ?? [] as $slide ) {
					if ( ! is_array( $slide ) ) {
						continue;
					}
					$slide_payload                      = $slide;
					$slide_payload['file_ref']          = 'slide_' . $slide_index;
					$slide_payload['parent_module_ref'] = $module_ref;
					$slide_payload['parent_course_ref'] = null;
					$manifest->slides[]                 = $slide_payload;
					$slide_index++;
				}
				break;

			case 'modules':
				foreach ( $data['modules'] ?? [] as $i => $module_payload ) {
					if ( ! is_array( $module_payload ) ) {
						continue;
					}
					$manifest->modules[] = [
						'file_ref'          => 'module_' . $i,
						'parent_course_ref' => null,
						'title'             => (string) ( $module_payload['title'] ?? '' ),
						'status'            => 'publish',
						'subject'           => (string) ( $module_payload['subject'] ?? '' ),
						'context'           => (string) ( $module_payload['context'] ?? '' ),
					];
				}
				break;

			case 'slide':
				$slide_payload = $data['slide'] ?? [];
				if ( ! is_array( $slide_payload ) ) {
					$slide_payload = [];
				}
				$slide_payload['file_ref']          = 'slide_0';
				$slide_payload['parent_module_ref'] = null;
				$slide_payload['parent_course_ref'] = null;
				$manifest->slides[]                 = $slide_payload;
				break;

			case 'slides':
				foreach ( $data['slides'] ?? [] as $i => $slide_payload ) {
					if ( ! is_array( $slide_payload ) ) {
						continue;
					}
					$slide_payload['file_ref']          = 'slide_' . $i;
					$slide_payload['parent_module_ref'] = null;
					$slide_payload['parent_course_ref'] = null;
					$manifest->slides[]                 = $slide_payload;
				}
				break;
		}

		return $manifest;
	}
}
