<?php

namespace WeDevs\AppBridge\Integrations\WPERP\REST;

use WeDevs\AppBridge\Core\REST\BaseController;
use WP_REST_Response;
use WP_REST_Server;

/**
 * App bootstrap configuration endpoint.
 *
 * Serves the public site identity + push-notification config the WP ERP
 * mobile app needs at launch. This is intentionally readable without
 * authentication so the app can render its login/splash screen (title,
 * icon, locale) before a user signs in.
 *
 * The notification block is sourced from WP ERP's own OneSignal settings
 * (the HRM PushNotification module) so the WP ERP plugin remains the single
 * source of truth — App Bridge only reads and forwards it. The OneSignal
 * REST API key is a server-side secret and is deliberately NOT exposed.
 *
 * GET app-bridge/v1/wp-erp/app-config
 */
class AppConfigController extends BaseController {

	/**
	 * WP ERP OneSignal option group (HRM PushNotification module).
	 */
	const ERP_PUSH_OPTION_GROUP = 'erp_integration_settings_erp-push-notification';

	protected $namespace = 'app-bridge/v1/wp-erp';

	protected $rest_base = 'app-config';

	public function register_routes(): void {
		register_rest_route(
			$this->namespace,
			'/' . $this->rest_base,
			[
				[
					'methods'             => WP_REST_Server::READABLE,
					'callback'            => [ $this, 'get_config' ],
					'permission_callback' => '__return_true',
				],
			]
		);
	}

	/**
	 * Build the app bootstrap payload.
	 *
	 * @return WP_REST_Response
	 */
	public function get_config(): WP_REST_Response {
		$timezone  = wp_timezone();
		$now       = new \DateTime( 'now', $timezone );
		$site_icon = get_site_icon_url();

		$config = [
			'site_title'   => get_bloginfo( 'name' ),
			'tagline'      => get_bloginfo( 'description' ),
			'site_icon'    => $site_icon ? $site_icon : '',
			'timezone'     => wp_timezone_string(),
			'date_format'  => get_option( 'date_format' ),
			'time_format'  => get_option( 'time_format' ),
			'week_start_on' => (string) get_option( 'start_of_week' ),
			'language'     => get_bloginfo( 'language' ), // e.g. en-US
			'timezone_utc' => $now->format( 'P' ),        // e.g. +06:00
			'notification' => $this->notification_config(),
			'modules'      => $this->modules_config(),
			'extensions'   => $this->extensions_config(),
			'erp_pro'      => $this->erp_pro_config(),
		];

		/**
		 * Filter the WP ERP app bootstrap config before it is returned.
		 *
		 * @param array $config The assembled config payload.
		 */
		$config = apply_filters( 'app_bridge_wp_erp_app_config', $config );

		return rest_ensure_response( $config );
	}

	/**
	 * Read the push-notification config from WP ERP's OneSignal settings.
	 *
	 * @return array{enabled: bool, platform: string, id: string}
	 */
	private function notification_config(): array {
		$app_id = $this->erp_push_option( 'erp_push_onesignal_app_id' );

		return [
			'enabled'  => '' !== $app_id,
			'platform' => 'onesignal',
			'id'       => $app_id,
		];
	}

	/**
	 * Build the WP ERP module list.
	 *
	 * Flat list — each entry carries an `active` flag rather than nesting under
	 * active/inactive groups. Tolerates WP ERP not being loaded by returning an
	 * empty list.
	 *
	 * @return array<int, array{key: string, name: string, slug: string, description: string, active: bool}>
	 */
	private function modules_config(): array {
		if ( ! function_exists( 'wperp' ) || ! isset( wperp()->modules ) ) {
			return [];
		}

		$modules    = wperp()->modules;
		$all        = $modules->get_modules();
		$active_ids = array_keys( (array) $modules->get_active_modules() );

		$list = [];

		foreach ( $all as $key => $module ) {
			$list[] = [
				'key'         => (string) $key,
				'name'        => (string) ( $module['title'] ?? '' ),
				'slug'        => (string) ( $module['slug'] ?? '' ),
				'description' => (string) ( $module['description'] ?? '' ),
				'active'      => \in_array( (string) $key, $active_ids, true ),
			];
		}

		return $list;
	}

	/**
	 * Report ERP Pro availability.
	 *
	 * `installed` — ERP Pro plugin is present and bootstrapped.
	 * `active`    — ERP Pro is installed AND holds a valid license.
	 *
	 * @return array{installed: bool, active: bool}
	 */
	private function erp_pro_config(): array {
		$installed = function_exists( 'wp_erp_pro' ) && isset( wp_erp_pro()->update );

		return [
			'installed' => $installed,
			'active'    => $installed && (bool) wp_erp_pro()->update->is_valid_license(),
		];
	}

	/**
	 * Build the ERP Pro extension (paid module) list.
	 *
	 * Flat list — each entry carries an `active` flag. ERP Pro stores active
	 * extensions as a flat list of module ids. Tolerates ERP Pro not being
	 * installed/active by returning an empty list.
	 *
	 * @return array<int, array{key: string, name: string, path: string, description: string, version: string, thumbnail: string, active: bool}>
	 */
	private function extensions_config(): array {
		if ( ! function_exists( 'wp_erp_pro' ) || ! isset( wp_erp_pro()->module ) ) {
			return [];
		}

		$module      = wp_erp_pro()->module;
		$all_modules = $module->get_all_modules();
		$active_ids  = (array) $module->get_active_modules();

		$list = [];

		foreach ( $all_modules as $module_id => $extension ) {
			$list[] = [
				'key'         => (string) $module_id,
				'name'        => (string) ( $extension['name'] ?? '' ),
				'path'        => (string) ( $extension['path'] ?? '' ),
				'description' => (string) ( $extension['description'] ?? '' ),
				'version'     => (string) ( $extension['version'] ?? '' ),
				'thumbnail'   => (string) ( $extension['thumbnail'] ?? '' ),
				'active'      => \in_array( (string) $module_id, $active_ids, true ),
			];
		}

		return $list;
	}

	/**
	 * Fetch a single WP ERP push option, tolerating WP ERP not being loaded.
	 *
	 * @param string $field_id
	 * @return string
	 */
	private function erp_push_option( string $field_id ): string {
		if ( function_exists( 'erp_get_option' ) ) {
			return (string) erp_get_option( $field_id, self::ERP_PUSH_OPTION_GROUP, '' );
		}

		$group = get_option( self::ERP_PUSH_OPTION_GROUP, [] );

		return is_array( $group ) ? (string) ( $group[ $field_id ] ?? '' ) : '';
	}
}
