<?php

namespace Yuvayana\Acadlix\Common\REST\Front;

use WP_REST_Server;

defined('ABSPATH') || exit();

class FrontStatisticController
{
  protected $namespace = 'acadlix/v1';
  protected $base = 'front-statistic';

  public function register_routes()
  {
    register_rest_route(
      $this->namespace,
      '/' . $this->base,
      array(
        array(
          'methods' => WP_REST_Server::READABLE,
          'callback' => array($this, 'get_statistic_by_user_id'),
          'permission_callback' => array($this, 'check_permission'),
          'args' => array(
            'user_id' => array(
              'validate_callback' => function ($param, $request, $key) {
                return is_numeric($param);
              }
            ),
          ),
        )
      )
    );

    register_rest_route(
      $this->namespace,
      '/' . $this->base . '/(?P<statistic_id>[\d]+)/statistic',
      array(
        array(
          'methods' => WP_REST_Server::READABLE,
          'callback' => array($this, 'get_statistic_by_statistic_id'),
          'permission_callback' => array($this, 'check_permission'),
          'args' => array(
            'statistic_id' => array(
              'validate_callback' => function ($param, $request, $key) {
                return is_numeric($param);
              }
            ),
          ),
        )
      )
    );
  }

  public function get_statistic_by_user_id($request)
  {
    // 1) Pre-parameter filter: allow callers to mutate incoming params before validation
    $params = apply_filters('acadlix_pre_get_statistic_by_user_id_params', $request->get_params(), $request);

    $res = [];

    $user_id = $params['user_id'] ?? $request->get_param('user_id');
    $search = $params['search'] ?? $request->get_param('search') ?? '';
    $category_ids = $params['category_ids'] ?? $request->get_param('category_ids') ?? [];

    // Validate required fields
    if (empty($user_id)) {
      return new WP_Error(
        'missing_id',
        __('User id is required.', 'acadlix'),
        ['status' => 400]
      );
    }

    // 2) Payload/Data Filter: normalize paging and other values before execution
    $payload = apply_filters('acadlix_get_statistic_by_user_id_payload', [
      'user_id' => intval($user_id),
      'search' => (string) $search,
      'category_ids' => is_array($category_ids) ? $category_ids : [$category_ids],
      'page' => max(0, intval($params['page'] ?? 0)),
      'pageSize' => max(1, intval($params['pageSize'] ?? 10)),
    ], $params);

    $skip = $payload['page'] * $payload['pageSize'];

    $res['categories'] = acadlix()->model()->category()->all();
    $stat_ref = acadlix()->model()->statisticRef()
      ->with('quiz')
      ->where('user_id', $payload['user_id'])
      ->when(!empty($payload['category_ids']), function ($query) use ($payload) {
        $query->whereHas('quiz.quiz_categories', function ($q) use ($payload) {
          $q->whereIn('term_id', $payload['category_ids']);
        });
      })
      ->when(!empty($payload['search']), function ($query) use ($payload) {
        $query->whereHas('quiz', function ($q) use ($payload) {
          $q->where('post_title', 'like', '%' . $payload['search'] . '%');
        });
      })
      ->orderBy("id", "desc");

    $res['total'] = $stat_ref->count();
    $res['stat_refs'] = $stat_ref->skip($skip)->take($payload['pageSize'])->get();

    // 3) Lifecycle Action: expose retrieval to listeners
    do_action('acadlix_get_statistic_by_user_id', $res, $stat_ref, $payload, $params);

    // 4) Outbound Response Filter: allow other modules to modify the REST response
    $res = apply_filters('acadlix_get_statistic_by_user_id_response', $res, $stat_ref, $payload, $params);

    return rest_ensure_response($res);
  }

  public function get_statistic_by_statistic_id($request)
  {
    // 1) Pre-parameter filter: allow callers to mutate incoming params before validation
    $params = apply_filters('acadlix_pre_get_statistic_by_statistic_id_params', $request->get_params(), $request);

    $res = [];
    $statistic_id = $params['statistic_id'] ?? $request['statistic_id'] ?? $request->get_param('statistic_id');

    $user_id = $params['user_id'] ?? $request->get_param('user_id');
    // Validate required fields
    if (empty($user_id)) {
      return new WP_Error(
        'missing_id',
        __('User id is required.', 'acadlix'),
        ['status' => 400]
      );
    }

    // Validate required fields
    if (empty($statistic_id)) {
      return new WP_Error(
        'missing_id',
        __('Statistic id is required.', 'acadlix'),
        ['status' => 400]
      );
    }

    // 2) Payload/Data Filter: normalize values before core execution
    $payload = apply_filters('acadlix_get_statistic_by_statistic_id_payload', [
      'statistic_id' => intval($statistic_id),
      'user_id' => intval($user_id),
    ], $params);

    $stat_ref = acadlix()->model()->statisticRef()->find($payload['statistic_id']);

    $appends = apply_filters('acadlix_get_statistic_by_statistic_id_quiz_appends', [
      'rendered_post_content',
      'rendered_metas',
      'category',
      'languages',
      'rendered_questions',
    ], $stat_ref, $payload, $params);

    $res['quiz'] = $stat_ref ? acadlix()->model()->quiz()->ofQuiz()->find($stat_ref->quiz_id)->setAppends($appends) : null;
    $res['statistic_ref'] = $stat_ref;
    $res['statistic'] = $stat_ref ? $stat_ref->statistics()->with("question")->get() : [];

    // 3) Lifecycle Action: expose retrieval to listeners
    do_action('acadlix_get_statistic_by_statistic_id', $res, $stat_ref, $payload, $params);

    // 4) Outbound Response Filter: allow response modification
    $res = apply_filters('acadlix_get_statistic_by_statistic_id_response', $res, $stat_ref, $payload, $params);

    return rest_ensure_response($res);
  }

  public function check_permission($request)
  {
    if (!is_user_logged_in()) {
      return new WP_Error('not_logged_in', 'Login required', ['status' => 401]);
    }

    $user_id = absint($request->get_param('user_id') ?? 0);

    if ($user_id && get_current_user_id() !== $user_id) {
      return new WP_Error('forbidden', 'Access denied', ['status' => 403]);
    }

    return true;
  }
}