<?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' ));
        }
        $manifest = null;
        if ( isset( $data['format'] ) && $data['format'] === self::FORMAT_V1 ) {
            $manifest = $this->parse_v1( $data );
        } else {
            $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' ) {
                $manifest = $this->parse_v2_bulk( $data );
            } else {
                $legacy_types = [
                    'course',
                    'formation',
                    'courses',
                    'module',
                    'modules',
                    'slide',
                    'slides'
                ];
                if ( in_array( $version, ['1.0', '2.0'], true ) && in_array( $type, $legacy_types, true ) ) {
                    $manifest = $this->parse_v1_legacy( $data, $version );
                }
            }
        }
        if ( null === $manifest ) {
            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' ));
        }
        $manifest->courses = [];
        $manifest->modules = [];
        $manifest->templates = [];
        foreach ( $manifest->slides as &$free_slide ) {
            $free_slide['parent_module_ref'] = null;
            $free_slide['parent_course_ref'] = null;
        }
        unset($free_slide);
        return $manifest;
    }

    // -------------------------------------------------------------------
    // 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;
    }

}
