<?php

namespace Fab\Api;

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

use Fab\Interfaces\JIT_Interface;
use Fab\Helper\FABItem;

/**
 * Insights API
 *
 * @package    Fab
 * @subpackage Fab/Api
 */
class Insights extends Api implements JIT_Interface {

    /**
     * Fabs.
     *
     * @var array
     */
    protected $fabs = array();

    /**
     * Registers REST API routes for the Floating Awesome Button plugin.
     *
     * @return void
     */
    public function register_routes() {
        \register_rest_route(
            'fab/v1',
            '/insights',
            array(
                array(
                    'methods'             => \WP_REST_Server::CREATABLE,
                    'permission_callback' => function () {
                        return defined( 'FAB_REST_API_USER_IS_ADMIN' ) && FAB_REST_API_USER_IS_ADMIN;
                    },
                    'callback'            => array( $this, 'get_insights' ),
                ),
            )
        );
    }

    /**
     * Handles the REST API request
     *
     * @param WP_REST_Request $request Full details about the request.
     * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
     */
    public function get_insights( $request ) {
        // Verify nonce.
        $nonce = $request->get_header( 'X-WP-Nonce' );
        if ( ! wp_verify_nonce( $nonce, 'wp_rest' ) ) {
            return new \WP_Error(
                'rest_cookie_invalid_nonce',
                __( 'Nonce verification failed', 'floating-awesome-button' ),
                array( 'status' => 403 )
            );
        }

        // Get insight type.
        $type = $request->get_param( 'type' );
        if ( ! $type ) {
            return new \WP_Error(
                'invalid_insight_type',
                __( 'Invalid insight type', 'floating-awesome-button' ),
                array( 'status' => 400 )
            );
        }

        // Generate insights.
        $nocache = $request->get_param( 'nocache' );
        return new \WP_REST_Response(
            array(
                'success'  => true,
                'insights' => $this->generate_insights( $nocache, apply_filters( 'fab_insights_dashboard', array(), $type ) ),
            ),
            200
        );
    }

    /**
     * Generates insights.
     *
     * @param bool  $ignore_cache Whether to ignore the cache.
     * @param array $fab_insights FAB insights.
     * @return array
     */
    public function generate_insights( $ignore_cache = false, $fab_insights = array() ) {
        $insights = array();

        // If $fab_insights is empty, use the default insights.
        if ( empty( $fab_insights ) ) {
            return $insights;
        }

        // Load insights and check if any insight cache is missing.
        $missing_cache = array();
        foreach ( $fab_insights as $key => $insight ) {
            $cache = $insight->get_transient();

            // If cache is false, add to missing cache.
            if ( false === $cache ) {
                $missing_cache[] = $key;
            }

            $insights[ $key ] = $cache;
        }

        // If cache is ignored then mark all insights as missing.
        if ( $ignore_cache ) {
            $missing_cache = array_keys( $fab_insights );
        }

        // If any insight cache is missing, load all fabs.
        if ( ! empty( $missing_cache ) ) {
            $this->fabs = $this->load_all_fabs();
            foreach ( $missing_cache as $key ) {
                $insights[ $key ] = $fab_insights[ $key ]->generate_insight();
            }
        }

        return $insights;
    }

    /**
     * Loads all fabs
     *
     * @return array
     */
    public function load_all_fabs() {
        if ( ! empty( $this->fabs ) ) {
            return $this->fabs;
        }

        $fabs = get_posts(
            array(
                'posts_per_page' => -1,
                'post_type'      => 'fab',
                'post_status'    => array( 'publish', 'draft', 'trash', 'pending', 'private', 'scheduled' ),
                'orderby'        => 'post_date',
                'order'          => 'DESC',
            )
        );

        $fabs = ! empty( $fabs ) ? array_map(
            function ( $fab ) {
                try {
                    $fab_item = new FABItem( (int) $fab->ID );
                    $fab_data = $fab_item->getVars();
                    return $fab_data ?? null;
                } catch ( \Exception $e ) {
                    return null;
                }
            },
            $fabs
        ) : array();
        $fabs = array_filter( $fabs ); // Remove null values.

        // Set the fabs to the class property.
        $this->fabs = $fabs;

        return $fabs;
    }

    /*
    |--------------------------------------------------------------------------
    | Fulfill implemented interface contracts
    |--------------------------------------------------------------------------
     */

    /**
     * JIT Method.
     *
     * @return void
     */
    public static function jit() {
        // Register routes.
        add_action( 'rest_api_init', array( __CLASS__, 'jit_register_routes' ) );
    }
}
