<?php

namespace GOS\GravityOps\Core\SuiteCore\Admin;

use Exception;
use GOS\GravityOps\Core\SuiteCore\SuiteCore;
use GOS\TrustedLogin\Config;
use GOS\TrustedLogin\Client;
use GOS\TrustedLogin\Form;
use GOS\TrustedLogin\Logging;
use GOS\TrustedLogin\SiteAccess;
use GOS\TrustedLogin\SupportUser;

/**
 * TrustedLogin integration for GravityOps.
 *
 * This class handles the secure support access feature using the TrustedLogin library.
 * It integrates with Freemius to automatically include license keys in the support request.
 */
class TrustedLogin {

	/**
	 * The unique identifier for this integration.
	 */
	const ID = 'gravityops_trustedlogin';

	/**
	 * API key.
     *
	 * @var string
	 */
	const TL_API_KEY = 'd7818caaf4075548';

	/**
	 * TrustedLogin client instance.
	 *
	 * @var Client|null
	 */
	private $client = null;

	/**
	 * SuiteCore instance.
	 *
	 * @var SuiteCore
	 */
	private SuiteCore $core;

	/**
	 * Class constructor.
	 *
	 * @param SuiteCore $core SuiteCore instance.
	 */
	public function __construct( SuiteCore $core ) {
		$this->core = $core;
		try {
			$config_data  = $this->get_config();
			$this->client = new Client(
				new Config( $config_data )
			);
		} catch ( Exception $e ) {
			// Silently fail if TL cannot be initialized, to avoid crashing the admin.
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				error_log( 'GravityOps TrustedLogin initialization failed: ' . $e->getMessage() );
			}
		}
	}

	/**
	 * Returns the TrustedLogin configuration array.
	 *
	 * @return array
	 */
	public function get_config() {
		$vendor_default = [
			'namespace'    => self::ID,
			'title'        => 'GravityOps',
			'email'        => 'support@brightleafdigital.io',
			'website'      => 'https://brightleafdigital.io',
			'support_url'  => 'https://brightleafdigital.io/support/',
			'display_name' => 'GravityOps Support',
			'logo_url'     => $this->core->suite_menu()->get_icon(),
		];

		$api_key = $this->core->config()->get_trustedlogin_api_key();
		$vendor  = $this->core->config()->get_trustedlogin_vendor();
		$vendor  = is_array( $vendor ) ? array_merge( $vendor_default, $vendor ) : $vendor_default;

		$config = [
			'auth'            => [
				'api_key' => $api_key,
			],
			'menu'            => [
				'slug' => false, // We handle menu registration ourselves.
			],
			'decay'           => 604800, // Access expires in one week.
			'role'            => 'administrator',
			'clone_role'      => false,
			'logging'         => [
				'enabled' => false,
			],
			'vendor'          => $vendor,
			'register_assets' => true,
			'paths'           => [
				'css' => $this->resolve_trustedlogin_css(),
			],
			'webhook'         => [
				'url'           => $this->core->config()->get_trustedlogin_webhook_url(),
				'debug_data'    => true,
				'create_ticket' => true,
			],
		];

		// Try to find a license key from any active Freemius instance in the suite.
		$license_key = $this->get_license_key();
		if ( $license_key ) {
			$config['auth']['license_key'] = $license_key;
		}

		return $config;
	}

	/**
	 * Attempts to retrieve a license key from registered Freemius instances.
	 *
	 * @return string|null
	 */
	private function get_license_key() {
		// Known Freemius instance getter functions for GravityOps plugins.
		$fs_getters = [
			'gvfgm_fs',   // Global Variables
			'iawgf_fs',   // Integrate Asana
			'menfgf_fs',  // Mass Email
			'rfsgf_fs',   // Recurring Submissions
			'kvfgv_fs',   // Kanban View
		// 'gravityops_forum_fs', // Forum
		];

		foreach ( $fs_getters as $func ) {
			if ( ! function_exists( $func ) ) {
				continue;
			}

			$fs = $func();

			if ( ! method_exists( $fs, 'is_registered' ) || ! $fs->is_registered() ) {
				continue;
			}

			// Try to get the current license.
			$license = method_exists( $fs, '_get_license' ) ? $fs->_get_license() : null;

			// Fallback to available premium licenses if no current license is found.
			if ( ! $license && method_exists( $fs, 'get_available_premium_licenses' ) ) {
				$licenses = $fs->get_available_premium_licenses();
				if ( ! empty( $licenses ) ) {
					$license = reset( $licenses );
				}
			}

			if ( $license && ! empty( $license->secret_key ) ) {
				return $license->secret_key;
			}
		}

		return null;
	}

	/**
	 * Renders the TrustedLogin support authentication screen.
	 *
	 * @return void
	 */
	public function render_support_screen() {
		try {
			$config_data = $this->get_config();
			$tl_config   = new Config( $config_data );
			$tl_logging  = new Logging( $tl_config );
			$tl_form     = new Form(
				$tl_config,
				$tl_logging,
				new SupportUser( $tl_config, $tl_logging ),
				new SiteAccess( $tl_config, $tl_logging )
			);

			echo '<div class="gops-tl-logo-wrapper">';
			echo '<img src="' . esc_url( $this->core->suite_menu()->get_icon() ) . '" alt="GravityOps" class="gops-tl-logo" />';
			echo '<span class="gops-tl-brand">GravityOps</span>';
			echo '</div>';

			$tl_form->print_auth_screen();
		} catch ( Exception $e ) {
			echo '<div class="notice notice-error"><p>' . esc_html( $e->getMessage() ) . '</p></div>';
		}
	}

	/**
	 * Resolve the TrustedLogin stylesheet URL.
	 *
	 * @return string
	 */
	private function resolve_trustedlogin_css(): string {
		$assets = $this->core->shell()->resolve_assets_urls();
		if ( empty( $assets['base_url'] ) ) {
			return '';
		}
		return trailingslashit( $assets['base_url'] ) . 'css/trustedlogin.css';
	}
}


/**
 * Send TrustedLogin webhook payloads as JSON.
 */
add_filter(
    'http_request_args',
    function ( $args, $url ) {
        if ( ! is_string( $url ) || false === strpos( $url, '/wp-json/trustedlogin/v1/webhook' ) ) {
            return $args;
        }

        if ( empty( $args['body'] ) || ! is_array( $args['body'] ) ) {
            return $args;
        }

        $encoded = wp_json_encode( $args['body'] );
        if ( false === $encoded ) {
            return $args;
        }

        $headers = [];
        if ( isset( $args['headers'] ) && is_array( $args['headers'] ) ) {
            $headers = $args['headers'];
        }

        $headers['Content-Type'] = 'application/json; charset=utf-8';
        $args['headers']         = $headers;
        $args['body']            = $encoded;

        return $args;
    },
    10,
    2
);
