<?php
namespace Consolety;

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

/**
 * Main Plugin class (Singleton)
 */
class Plugin {

    private static $instance = null;

    private $api;
    private $admin;
    private $guest_posts;
    private $guest_posts_ajax;
    private $link_monitor;
    private $campaigns;

    public static function instance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    private function __construct() {
        // Token key migratie (eenmalig, backward compat)
        $oldToken = get_option('consolety_api_token');
        $newToken = get_option('consolety_trust_token');
        if (!empty($oldToken) && empty($newToken)) {
            update_option('consolety_trust_token', $oldToken);
            delete_option('consolety_api_token');
        }

        $this->load_dependencies();
        $this->init_hooks();
    }

    private function load_dependencies() {
        require_once CONSOLETY_PLUGIN_DIR . 'includes/class-api.php';
        require_once CONSOLETY_PLUGIN_DIR . 'includes/class-admin.php';
        require_once CONSOLETY_PLUGIN_DIR . 'includes/class-points-economy.php';
        require_once CONSOLETY_PLUGIN_DIR . 'includes/class-guest-posts.php';
        require_once CONSOLETY_PLUGIN_DIR . 'includes/class-link-monitor.php';
        require_once CONSOLETY_PLUGIN_DIR . 'includes/class-campaigns.php';
        require_once CONSOLETY_PLUGIN_DIR . 'includes/ajax/class-guest-posts-ajax-handler.php';

        $this->api = new Api();
        $this->admin = new Admin($this->api);
        $this->guest_posts = new GuestPosts($this->api);
        $this->link_monitor = new LinkMonitor();
        $this->link_monitor->init();
        $this->campaigns = new Campaigns($this->api);
        $this->guest_posts_ajax = new Ajax\GuestPostsAjaxHandler($this->api);
        $this->guest_posts_ajax->register();
    }

    private function init_hooks() {
        // Handle OAuth callback
        add_action('admin_init', [$this, 'handle_oauth_callback']);

        // Schedule heartbeat
        add_action('init', [$this, 'schedule_heartbeat']);
        add_action('consolety_heartbeat', [$this, 'send_heartbeat']);
    }

    /**
     * Handle OAuth callback from Hub
     *
     * Security: validates one-time nonce to ensure callback originated
     * from our own OAuth initiation (prevents token injection via URL).
     */
    public function handle_oauth_callback() {
        if (!isset($_GET['page']) || sanitize_text_field(wp_unslash($_GET['page'])) !== 'consolety') { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            return;
        }

        // Security: Only administrators can complete OAuth connection
        if (!current_user_can('manage_options')) {
            return;
        }

        // Check for OAuth token in URL
        if (isset($_GET['oauth_token']) && !empty($_GET['oauth_token'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            $token = sanitize_text_field(wp_unslash($_GET['oauth_token'])); // phpcs:ignore WordPress.Security.NonceVerification.Recommended

            // Verify one-time OAuth nonce (prevents token injection attacks)
            $callbackNonce = isset($_GET['oauth_nonce']) ? sanitize_text_field(wp_unslash($_GET['oauth_nonce'])) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            $storedNonce = get_transient('consolety_oauth_nonce');

            if (empty($callbackNonce) || empty($storedNonce) || !hash_equals($storedNonce, $callbackNonce)) {
                // Nonce mismatch or missing -- reject the callback
                delete_transient('consolety_oauth_nonce');
                wp_safe_redirect(admin_url('admin.php?page=consolety&error=invalid_callback'));
                exit;
            }

            // Consume the nonce (one-time use)
            delete_transient('consolety_oauth_nonce');

            // Save token
            update_option('consolety_trust_token', $token);

            // Register site with Hub
            $this->api->setToken($token);
            $result = $this->api->registerSite();

            if (!$result || empty($result['data']['site_id'])) {
                // Registration failed -- clean up token, don't show "connected"
                delete_option('consolety_trust_token');
                wp_safe_redirect(admin_url('admin.php?page=consolety&error=registration_failed'));
                exit;
            }

            update_option('consolety_site_id', $result['data']['site_id']);

            // Fetch initial status (credits, tier, etc.)
            $this->refresh_status();

            // Attempt live GSC metrics refresh so dashboard shows real data immediately
            // First attempt with 10s timeout; if GSC is cold (new connection), retry once after 3s
            $metricsResult = $this->api->refreshMetrics(['timeout' => 10]);
            if (empty($metricsResult['success']) || !isset($metricsResult['data']['metrics'])) {
                sleep(3);
                $metricsResult = $this->api->refreshMetrics(['timeout' => 15]);
            }
            if (!empty($metricsResult['success']) && isset($metricsResult['data']['metrics'])) {
                update_option('consolety_metrics', $metricsResult['data']['metrics']);
            }

            // Redirect to clean URL
            wp_safe_redirect(admin_url('admin.php?page=consolety&connected=1'));
            exit;
        }
    }

    /**
     * Refresh status from Hub
     */
    public function refresh_status() {
        $status = $this->api->fetchSiteStatus();

        if ($status && isset($status['data'])) {
            $data = $status['data'];

            if (isset($data['metrics'])) {
                update_option('consolety_metrics', $data['metrics']);
            }

            if (isset($data['site_id'])) {
                update_option('consolety_site_id', $data['site_id']);
            }

            // Store credits and tier info
            $siteInfo = get_option('consolety_site_info', []);
            if (isset($data['credits'])) {
                $siteInfo['credits'] = $data['credits'];
            }
            if (isset($data['points'])) {
                $siteInfo['credits'] = $data['points']; // Alias
            }
            if (isset($data['credits_reserved'])) {
                $siteInfo['credits_reserved'] = $data['credits_reserved'];
            }
            if (isset($data['subscription_tier'])) {
                $siteInfo['subscription_tier'] = $data['subscription_tier'];
            }
            if (isset($data['tier'])) {
                $siteInfo['tier'] = $data['tier'];
            }
            update_option('consolety_site_info', $siteInfo);
        }

        return $status;
    }

    /**
     * Schedule heartbeat cron
     */
    public function schedule_heartbeat() {
        if (!wp_next_scheduled('consolety_heartbeat')) {
            wp_schedule_event(time(), 'hourly', 'consolety_heartbeat');
        }
    }

    /**
     * Send heartbeat to Hub
     */
    public function send_heartbeat() {
        if (!get_option('consolety_trust_token')) {
            return;
        }

        $result = $this->api->sendHeartbeat();

        // Store heartbeat timestamp for diagnostics
        if ($result && !empty($result['success'])) {
            update_option('consolety_last_heartbeat', current_time('mysql'));
        }

        // Store webhook secret if provided
        if ($result && isset($result['data']['webhook_secret']) && $result['data']['secret_is_new']) {
            update_option('consolety_webhook_secret', $result['data']['webhook_secret']);
        }

        // Also refresh site status to sync tier/credits (catches Pro upgrades)
        $this->refresh_status();
    }

    /**
     * Check if site is connected
     */
    public function isConnected() {
        return $this->api->isConnected();
    }

    /**
     * Get API instance
     */
    public function api() {
        return $this->api;
    }

    /**
     * Get Admin instance
     */
    public function admin() {
        return $this->admin;
    }

    /**
     * Get GuestPosts instance
     */
    public function guestPosts() {
        return $this->guest_posts;
    }

    /**
     * Get LinkMonitor instance
     */
    public function linkMonitor() {
        return $this->link_monitor;
    }
}
