<?php
/**
 * Extension Loader Class
 *
 * Provides a minimal developer API for third-party addons.
 *
 * @package Polanger_Dashboard_Tools
 */

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

class PDT_Extension_Loader {

  /**
   * Registered module definitions.
   *
   * @var array<string,array>
   */
  private $modules = array();

  /**
   * Constructor.
   */
  public function __construct() {
    $this->discover_manifest_modules();
  }

  /**
   * Register a module definition.
   *
   * @param array $module Module config.
   * @return bool
   */
  public function register_module( $module ) {
    if ( ! is_array( $module ) ) {
      return false;
    }

    $raw_slug = isset( $module['slug'] ) ? $module['slug'] : '';
    $slug     = sanitize_key( $raw_slug );

    if ( '' === $slug ) {
      return false;
    }

    $title = '';
    if ( isset( $module['title'] ) ) {
      $title = sanitize_text_field( $module['title'] );
    } elseif ( isset( $module['name'] ) ) {
      $title = sanitize_text_field( $module['name'] );
    }

    if ( '' === $title ) {
      $title = $slug;
    }

    $description = isset( $module['description'] ) ? sanitize_text_field( $module['description'] ) : '';
    $page_slug   = isset( $module['page_slug'] ) ? $this->sanitize_page_slug( $module['page_slug'] ) : '';
    $version     = isset( $module['version'] ) ? sanitize_text_field( $module['version'] ) : '';
    $requires    = isset( $module['requires'] ) ? sanitize_text_field( $module['requires'] ) : '';
    $is_core     = ! empty( $module['is_core'] );

    $this->modules[ $slug ] = array(
      'slug'        => $slug,
      'title'       => $title,
      'description' => $description,
      'page_slug'   => $page_slug,
      'version'     => $version,
      'requires'    => $requires,
      'is_core'     => $is_core,
      'source'      => isset( $module['source'] ) ? sanitize_text_field( $module['source'] ) : 'runtime',
    );

    return true;
  }

  /**
   * Return all registered modules.
   *
   * @return array<string,array>
   */
  public function get_modules() {
    return $this->modules;
  }

  /**
   * Inject loader-registered addons into addons registry output.
   *
   * @param array $addons Existing addons.
   * @return array
   */
  public function inject_registered_addons( $addons ) {
    if ( ! is_array( $addons ) ) {
      $addons = array();
    }

    foreach ( $this->modules as $module_slug => $module ) {
      if ( isset( $addons[ $module_slug ] ) ) {
        continue;
      }

      $addons[ $module_slug ] = array(
        'title'       => $module['title'],
        'description' => $module['description'],
        'status'      => 'inactive',
        'slug'        => $module['page_slug'],
        'is_core'     => ! empty( $module['is_core'] ),
      );
    }

    return $addons;
  }

  /**
   * Discover addon manifests under the plugin addons directory.
   *
   * @return void
   */
  private function discover_manifest_modules() {
    $manifest_files = glob( PDT_PLUGIN_DIR . 'addons/*/polanger-addon.json' );

    if ( ! is_array( $manifest_files ) || empty( $manifest_files ) ) {
      return;
    }

    foreach ( $manifest_files as $manifest_file ) {
      $manifest = $this->read_manifest( $manifest_file );

      if ( empty( $manifest ) || ! is_array( $manifest ) ) {
        continue;
      }

      $module = array(
        'name'        => isset( $manifest['name'] ) ? $manifest['name'] : '',
        'slug'        => isset( $manifest['slug'] ) ? $manifest['slug'] : '',
        'version'     => isset( $manifest['version'] ) ? $manifest['version'] : '',
        'requires'    => isset( $manifest['requires'] ) ? $manifest['requires'] : '',
        'description' => isset( $manifest['description'] ) ? $manifest['description'] : '',
        'page_slug'   => isset( $manifest['page_slug'] ) ? $manifest['page_slug'] : '',
        'is_core'     => ! empty( $manifest['is_core'] ),
        'source'      => 'manifest',
      );

      $this->register_module( $module );
    }
  }

  /**
   * Read and decode manifest JSON file.
   *
   * @param string $manifest_file Full manifest path.
   * @return array
   */
  private function read_manifest( $manifest_file ) {
    if ( ! file_exists( $manifest_file ) || ! is_readable( $manifest_file ) ) {
      return array();
    }

    $json = file_get_contents( $manifest_file );

    if ( false === $json ) {
      return array();
    }

    $decoded = json_decode( $json, true );
    return is_array( $decoded ) ? $decoded : array();
  }

  /**
   * Normalize addon page slugs while preserving allowed query arguments such as tabs.
   *
   * @param string $page_slug Raw page slug.
   * @return string
   */
  private function sanitize_page_slug( $page_slug ) {
    $page_slug = sanitize_text_field( (string) $page_slug );
    $page_slug = preg_replace( '/[^a-zA-Z0-9_\-&=]/', '', $page_slug );

    return is_string( $page_slug ) ? $page_slug : '';
  }
}
