<?php
/**
 * Class for the widget importer.
 *
 * Code is mostly from the Widget Importer & Exporter plugin.
 *
 * @see https://wordpress.org/plugins/widget-importer-exporter/
 */

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

class Ocean_Widget_Importer {

    /**
     * Term ID mappings from import
     * @var array
     */
    public $processed_terms = array();

    /**
     * Process import file - this parses the widget data and returns it.
     *
     * @param string $file Path to the JSON file.
     */
    public function process_import_file( $file ) {
        if ( ! file_exists( $file ) ) {
            return new WP_Error( 'file_not_found', __( 'The specified file does not exist', 'ocean-extra' ) );
        }

        // Read file contents.
        $data = file_get_contents( $file );
        if ( false === $data ) {
            return new WP_Error( 'file_read_error', __( 'Unable to read widget data file.', 'ocean-extra' ) );
        }

        // Decode JSON data.
        $widget_data = json_decode( $data, true );
        if ( json_last_error() !== JSON_ERROR_NONE ) {
            return new WP_Error( 'json_parse_error', __( 'Invalid widget data format.', 'ocean-extra' ) );
        }

        // Import the widget data.
        return $this->import_data( $widget_data );
    }

    /**
     * Import widget JSON data.
     *
     * @global array $wp_registered_sidebars
     * @param array $data JSON widget data.
     * @return array $results Import results.
     */
    private function import_data( $data ) {
        global $wp_registered_sidebars;

        if ( empty( $data ) || ! is_array( $data ) ) {
            return new WP_Error( 'invalid_data', __( 'Invalid or empty widget data.', 'ocean-extra' ) );
        }

        $available_widgets = $this->available_widgets();
        $results = [];

        $widget_instances = [];
        foreach ( $available_widgets as $widget ) {
            $widget_instances[ $widget['id_base'] ] = get_option( 'widget_' . $widget['id_base'], [] );
        }

        foreach ( $data as $sidebar_id => $widgets ) {
            if ( 'wp_inactive_widgets' === $sidebar_id ) {
                continue;
            }

            $sidebar_exists = isset( $wp_registered_sidebars[ $sidebar_id ] );
            $use_sidebar_id = $sidebar_exists ? $sidebar_id : 'wp_inactive_widgets';

            $results[ $sidebar_id ] = [
                'name'         => $sidebar_exists ? $wp_registered_sidebars[ $sidebar_id ]['name'] : $sidebar_id,
                'message_type' => $sidebar_exists ? 'success' : 'error',
                'message'      => $sidebar_exists ? '' : __( 'Sidebar does not exist in theme. Moving widget to Inactive.', 'ocean-extra' ),
                'widgets'      => [],
            ];

            foreach ( $widgets as $widget_instance_id => $widget ) {
                $widget_result = $this->import_widget_instance( $widget_instance_id, $widget, $available_widgets, $widget_instances, $use_sidebar_id );
                $results[ $sidebar_id ]['widgets'][ $widget_instance_id ] = $widget_result;
            }
        }

        return $results;
    }

    /**
     * Import a single widget instance.
     *
     * @param string $widget_instance_id Widget instance ID.
     * @param array  $widget Widget data.
     * @param array  $available_widgets Available widgets.
     * @param array  $widget_instances Existing widget instances.
     * @param string $sidebar_id Target sidebar.
     * @return array Import result for the widget.
     */
    private function import_widget_instance( $widget_instance_id, $widget, $available_widgets, &$widget_instances, $sidebar_id ) {
        $id_base = preg_replace( '/-[0-9]+$/', '', $widget_instance_id );
        $instance_id_number = str_replace( $id_base . '-', '', $widget_instance_id );

        if ( ! array_key_exists( $id_base, $available_widgets ) ) {
            return [
                'name'         => $id_base,
                'title'        => __( 'Unknown Widget', 'ocean-extra' ),
                'message_type' => 'error',
                'message'      => __( 'This widget type is not supported on this site.', 'ocean-extra' ),
            ];
        }

        $widget = json_decode( json_encode( $widget ), true );

        $widget = $this->fix_custom_menu_widget_ids( $widget );

        if ( isset( $widget_instances[ $id_base ] ) ) {
            $existing_instances = get_option( 'sidebars_widgets' )[ $sidebar_id ] ?? [];

            foreach ( $widget_instances[ $id_base ] as $existing_id => $existing_widget ) {
                if ( in_array( "$id_base-$existing_id", $existing_instances, true ) && $existing_widget === $widget ) {
                    return [
                        'name'         => $available_widgets[ $id_base ]['name'],
                        'title'        => $widget['title'] ?? __( 'No Title', 'ocean-extra' ),
                        'message_type' => 'warning',
                        'message'      => __( 'Widget already exists.', 'ocean-extra' ),
                    ];
                }
            }
        }

        $widget_instances[ $id_base ][] = $widget;
        end( $widget_instances[ $id_base ] );
        $new_instance_id_number = key( $widget_instances[ $id_base ] );

        if ( '0' === strval( $new_instance_id_number ) ) {
            $new_instance_id_number = 1;
            $widget_instances[ $id_base ][ $new_instance_id_number ] = $widget_instances[ $id_base ][0];
            unset( $widget_instances[ $id_base ][0] );
        }

        if ( isset( $widget_instances[ $id_base ]['_multiwidget'] ) ) {
            $multiwidget = $widget_instances[ $id_base ]['_multiwidget'];
            unset( $widget_instances[ $id_base ]['_multiwidget'] );
            $widget_instances[ $id_base ]['_multiwidget'] = $multiwidget;
        }

        update_option( 'widget_' . $id_base, $widget_instances[ $id_base ] );

        $sidebars_widgets = get_option( 'sidebars_widgets', [] );
        $sidebars_widgets[ $sidebar_id ][] = "$id_base-$new_instance_id_number";
        update_option( 'sidebars_widgets', $sidebars_widgets );

        return [
            'name'         => $available_widgets[ $id_base ]['name'],
            'title'        => $widget['title'] ?? __( 'No Title', 'ocean-extra' ),
            'message_type' => 'success',
            'message'      => __( 'Widget imported successfully.', 'ocean-extra' ),
        ];
    }

    /**
     * Get all available widgets.
     *
     * @return array Available widgets.
     */
    private function available_widgets() {
        global $wp_registered_widget_controls;

        $available_widgets = [];

        foreach ( $wp_registered_widget_controls as $widget ) {
            if ( ! empty( $widget['id_base'] ) && ! isset( $available_widgets[ $widget['id_base']] ) ) {
                $available_widgets[ $widget['id_base'] ] = [
                    'id_base' => $widget['id_base'],
                    'name'    => $widget['name'],
                ];
            }
        }

        return $available_widgets;
    }

    /**
     * Fix menu IDs in nav_menu and ocean_custom_menu widgets after import
     *
     * @param array $widget Widget instance data
     * @return array Modified widget instance data
     */
    private function fix_custom_menu_widget_ids( $widget ) {

        if ( ! isset( $widget['nav_menu'] ) || empty( $widget['nav_menu'] ) || ! is_int( $widget['nav_menu'] ) ) {
            return $widget;
        }

        if ( ! isset( $this->processed_terms ) || empty( $this->processed_terms ) ) {
            return $widget;
        }

        $old_menu_id = $widget['nav_menu'];

        if ( isset( $this->processed_terms[ $old_menu_id ] ) ) {
            $widget['nav_menu'] = $this->processed_terms[ $old_menu_id ];
        }

        return $widget;
    }
}
