<?php

namespace Fab\Plugin\Helper;

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

/**
 * Add extra layer for WordPress functions
 *
 * @package    Fab
 * @subpackage Fab\Wordpress
 */

trait Asset {

    /**
     * Get file content
     * - Get plugin file content either from url or from local file
     * - This is required to load assets correctly
     *
     * @param string $path Path to the file.
     * @return string
     */
    public function get_file_content( $path ) {
        // Build the full URL to the file.
        $url = FAB_PLUGIN_URL . ltrim( $path, '/' );

        // Attempt to fetch the file remotely.
        $connect = wp_remote_get( $url, array( 'sslverify' => false ) );

        // If no error and response code is 200, return the remote content.
        if ( ! is_wp_error( $connect ) && wp_remote_retrieve_response_code( $connect ) === 200 ) {
            return wp_remote_retrieve_body( $connect );
        }

        // If remote fetch fails, try to load the file from local plugin path.
        $file = trailingslashit( FAB_PLUGIN_PATH ) . ltrim( $path, '/' );
        if ( file_exists( $file ) ) {
            // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
            return file_get_contents( $file );
        }

        // Return false if both remote and local fetch failed.
        return false;
    }

    /**
     * WordPress enqueue style
     *
     * @param   string $handle     Name of the script. Should be unique.
     * @param   string $src        Full URL of the script, or path of the script relative to the WordPress root directory.
     * @param   array  $deps       An array of registered script handles this script depends on.
     * @param   string $ver        String specifying script version number, if it has one, which is added to the URL as a query string for cache busting purposes.
     * @param   bool   $media      The media for which this stylesheet has been defined.
     * @return void
     */
    public function wp_enqueue_style( $handle, $src = '', $deps = array(), $ver = false, $media = 'all' ) {
        if ( ! strpos( $src, '//' ) ) {
            $file = sprintf( '%sassets/%s', json_decode( FAB_PATH )->plugin_path, $src );
            $src  = sprintf( '%sassets/%s', json_decode( FAB_PATH )->plugin_url, $src );
            if ( ! file_exists( $file ) ) {
                return;
            }
        }
        wp_enqueue_style( $handle, $src, $deps, ! $ver ? FAB_VERSION : $ver, $media );
    }

    /**
     * Enqueue a script in WordPress
     *
     * This function registers and enqueues a script in WordPress. It allows you to specify
     * the script's URL, dependencies, version, and whether it should be loaded in the footer.
     *
     * @param string $handle     Unique name for the script. Used to identify the script.
     * @param string $src        The full URL or path to the script relative to the WordPress root directory.
     * @param array  $deps       An array of handles of scripts that must be loaded before this one. Default is an empty array.
     * @param string $ver        Optional. The script version number, added as a query string for cache busting. Default is false.
     * @param bool   $in_footer  Optional. Whether to enqueue the script in the footer. Default is false (enqueued in the head).
     */
    public function wp_enqueue_script( $handle, $src = '', $deps = array(), $ver = false, $in_footer = false ) {
        if ( ! strpos( $src, '//' ) ) {
            $file = sprintf( '%sassets/%s', FAB_PLUGIN_PATH, $src );
            $src  = sprintf( '%sassets/%s', FAB_PLUGIN_URL, $src );
            if ( ! file_exists( $file ) ) {
                return;
            }
        }

        wp_enqueue_script( $handle, $src, $deps, ! $ver ? FAB_VERSION : $ver, $in_footer );
    }

    /**
     * WordPress enqueue script component
     *
     * @param   string $handle     Name of the script. Should be unique.
     * @param   string $src        Full URL of the script, or path of the script relative to the WordPress root directory.
     * @param   array  $deps       An array of registered script handles this script depends on.
     * @param   string $ver        String specifying script version number, if it has one, which is added to the URL as a query string for cache busting purposes.
     * @param   bool   $in_footer      Whether to enqueue the script before </body> instead of in the <head>.
     * @return void
     */
    public function wp_enqueue_script_component( $handle, $src = '', $deps = array(), $ver = false, $in_footer = false ) {
        // Read manifest.json.
        $manifest = json_decode( $this->get_file_content( 'assets/build/manifest.json' ) );

        // Check if HMR_DEV is true.
        if ( defined( 'HMR_DEV' ) && HMR_DEV ) {
            $src    = sprintf( 'http://localhost:%s/%s', HMR_DEV_PORT, $manifest->{$src}->src );
            $deps[] = 'fab-vite';
        } else {
            $src = 'build/' . $manifest->{$src}->file;
        }

        // Add module scripts.
        add_filter(
            'fab_module_scripts',
            function ( $scripts ) use ( $handle ) {
                $scripts[] = $handle;
                return $scripts;
            }
        );

        $this->wp_enqueue_script( $handle, $src, $deps, $ver, $in_footer );
    }

    /**
     * WordPress enqueue style sass
     *
     * @param   string $handle     Name of the script. Should be unique.
     * @param   string $src        Full URL of the script, or path of the script relative to the WordPress root directory.
     * @param   array  $deps       An array of registered script handles this script depends on.
     * @param   string $ver        String specifying script version number, if it has one, which is added to the URL as a query string for cache busting purposes.
     * @param   string $media      The media for which this stylesheet has been defined.
     * @return void
     */
    public function wp_enqueue_style_sass( $handle, $src = '', $deps = array(), $ver = false, $media = 'all' ) {
        $manifest = json_decode( $this->get_file_content( 'assets/build/manifest-sass.json' ) );
        $src      = str_replace( 'assets/', '', $manifest->{$src} );
        $this->wp_enqueue_style( $handle, $src, $deps, $ver, $media );
    }

    /**
     * WordPress enqueue script typescript
     *
     * @param   string $handle     Name of the script. Should be unique.
     * @param   string $src        Full URL of the script, or path of the script relative to the WordPress root directory.
     * @param   array  $deps       An array of registered script handles this script depends on.
     * @param   string $ver        String specifying script version number, if it has one, which is added to the URL as a query string for cache busting purposes.
     * @param   bool   $in_footer      Whether to enqueue the script before </body> instead of in the <head>.
     * @return void
     */
    public function wp_enqueue_script_typescript( $handle, $src = '', $deps = array(), $ver = false, $in_footer = false ) {
        $manifest = json_decode( $this->get_file_content( 'assets/build/manifest.json' ) );
        $src      = 'build/' . $manifest->{$src}->file;
        $this->wp_enqueue_script( $handle, $src, $deps, $ver, $in_footer );
    }

    /**
     * Enqueue vendor assets
     *
     * @param string $location Vendor location backend/frontend.
     * @return void
     */
    public function enqueue_vendor( $location ) {
        $vendors = json_decode( $this->get_file_content( 'assets/vendor/vendor.json' ) );
        $vendors = apply_filters( 'fab_enqueue_vendor', $vendors->{$location} );
        foreach ( $vendors as $asset_id => $asset ) {
            $asset = (object) $asset;
            if ( str_ends_with( $asset->src, '.css' ) ) {
                $this->wp_enqueue_style( $asset_id, $asset->src );
            } elseif ( str_ends_with( $asset->src, '.js' ) ) {
                $this->wp_enqueue_script( $asset_id, $asset->src, array(), '', isset( $asset->in_footer ) ? true : false );
            }
        }
    }
}
