<?php

namespace Yuvayana\Acadlix\Common\REST\Front;

use WP_REST_Server;
use WP_Error;
use Yuvayana\Acadlix\Common\Models\Order;

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

class FrontCourseController
{
  protected $namespace = 'acadlix/v1';
  protected $base = 'front-course';

  public function register_routes()
  {
    register_rest_route(
      $this->namespace,
      '/' . $this->base . '/add-to-cart',
      [
        [
          'methods' => WP_REST_Server::CREATABLE,
          'callback' => [$this, 'post_add_to_cart'],
          'permission_callback' => [$this, 'check_permission'],
        ],
      ]
    );

    register_rest_route(
      $this->namespace,
      '/' . $this->base . '/buy-now',
      [
        [
          'methods' => WP_REST_Server::CREATABLE,
          'callback' => [$this, 'post_buy_now'],
          'permission_callback' => [$this, 'check_permission'],
        ],
      ]
    );

    register_rest_route(
      $this->namespace,
      '/' . $this->base . '/start-now',
      [
        [
          'methods' => WP_REST_Server::CREATABLE,
          'callback' => [$this, 'post_start_now'],
          'permission_callback' => [$this, 'check_permission'],
        ],
      ]
    );

    register_rest_route(
      $this->namespace,
      '/' . $this->base . '/add-wishlist',
      [
        [
          'methods' => WP_REST_Server::CREATABLE,
          'callback' => [$this, 'post_add_wishlist'],
          'permission_callback' => function () {
            return is_user_logged_in();
          },
        ],
      ]
    );
    register_rest_route(
      $this->namespace,
      '/' . $this->base . '/remove-wishlist',
      [
        [
          'methods' => WP_REST_Server::DELETABLE,
          'callback' => [$this, 'post_remove_wishlist'],
          'permission_callback' => function () {
            return is_user_logged_in();
          },
        ],
      ]
    );

    register_rest_route(
      $this->namespace,
      '/' . $this->base . '/submit-review',
      [
        [
          'methods' => WP_REST_Server::CREATABLE,
          'callback' => [$this, 'post_submit_review'],
          'permission_callback' => [$this, 'check_permission'],
        ],
      ]
    );

    register_rest_route(
      $this->namespace,
      '/' . $this->base . '/load-more-reviews',
      [
        [
          'methods' => WP_REST_Server::CREATABLE,
          'callback' => [$this, 'post_load_more_reviews'],
          'permission_callback' => [$this, 'check_permission'],
        ],
      ]
    );
  }

  public function post_add_to_cart($request)
  {
    $errors = [];
    $required_fields = array('item_id', 'type');
    $params = $request->get_json_params();
    if (is_array($params) && count($params) == 0) {
      return new WP_Error('no_data_found', __('Required item id and user_id', 'acadlix'), array('status' => 404));
    }

    foreach ($required_fields as $field) {
      $param = !empty($params[$field]) ? $params[$field] : $request->get_param($field);

      if (empty($param)) {
        /* translators: %s is the required field */
        $errors[] = sprintf(__('The %s parameter is required.', 'acadlix'), $field);
      }
    }

    if (!empty($errors)) {
      return new WP_Error('missing_params', implode(' ', $errors), array('status' => 400));
    }
    $res = array(
      'status' => 'success',
      'code' => array('status' => 200),
      'data' => ""
    );

    return rest_ensure_response($res);
  }

  public function post_buy_now($request)
  {
    $errors = [];
    $required_fields = array('item_id', 'type');

    // 1) Pre Parameter Filter: allow callers to mutate incoming params before validation
    $params = apply_filters('acadlix_pre_post_buy_now_params', $request->get_json_params(), $request);

    if (is_array($params) && count($params) == 0) {
      return new WP_Error('no_data_found', __('Required item id and user_id', 'acadlix'), array('status' => 404));
    }

    foreach ($required_fields as $field) {
      $param = !empty($params[$field]) ? $params[$field] : $request->get_param($field);

      if (empty($param)) {
        /* translators: %s is the required field */
        $errors[] = sprintf(__('The %s parameter is required.', 'acadlix'), $field);
      }
    }

    if (!empty($errors)) {
      return new WP_Error('missing_params', implode(' ', $errors), array('status' => 400));
    }

    // 2) Payload/Data Filter: normalize values before core execution
    $payload = apply_filters('acadlix_post_buy_now_payload', [
      'user_id' => (int) ($params['user_id'] ?? 0),
      'item_id' => $params['item_id'],
      'type' => $params['type'],
      'cart_token' => $params['cart_token'] ?? null,
      'token_expiry' => $params['token_expiry'] ?? 0,
    ], $params);

    if ($payload['user_id'] === 0 && empty($payload['cart_token'])) {
      return new WP_Error('missing_params', sprintf(__('The %s parameter is required.', 'acadlix'), 'cart_token'), array('status' => 400));
    }

    if ($payload['user_id'] === 0) {
      $carts = acadlix()
        ->model()
        ->courseCart()
        ->where("cart_token", $payload['cart_token'])
        ->get();

      if (count($carts) > 0) {
        foreach ($carts as $cart) {
          $cart->update([
            'token_expiry' => $payload['token_expiry']
          ]);
        }
      }
    }

    $this->addToCart(
      $payload['cart_token'],
      $payload['item_id'],
      $payload['type'],
      $payload['user_id'],
      $payload['token_expiry']
    );

    $res = $this->successResponse('checkout');

    // 3) Lifecycle Action: trigger once after buy-now processing completes
    do_action('acadlix_post_buy_now', $res, $payload, $params);

    // 4) Outbound Response Filter: allow response augmentation
    $res = apply_filters('acadlix_post_buy_now_response', $res, $payload, $params);

    return rest_ensure_response($res);

  }

  protected function get_item($item_id, $type)
  {
    // 1) Pre-lookup filter: allow mutation of the lookup parameters.
    $args = apply_filters(
      'acadlix_get_item_args',
      [
        'item_id' => $item_id,
        'type' => $type,
      ],
      $item_id,
      $type
    );

    $item = null;
    if ($args['type'] === 'course') {
      $item = acadlix()
        ->model()
        ->course()
        ->ofCourse()
        ->find($args['item_id']);
    }

    // 2) Post-lookup action: expose the retrieved item to listeners.
    do_action('acadlix_get_item_retrieved', $item, $args);

    // 3) Result filter: allow modifications of the returned item.
    return apply_filters('acadlix_get_item_result', $item, $args);
  }

  protected function addToCart($cartToken, $itemId, $type, $userId, $expiry)
  {
    $cart = acadlix()
      ->model()
      ->courseCart()
      ->where('user_id', $userId)
      ->where('cart_token', $cartToken)
      ->where('item_id', $itemId)
      ->where('type', $type)
      ->first();

    if (!$cart) {
      acadlix()->model()->courseCart()->create([
        'cart_token' => $cartToken,
        'item_id' => $itemId,
        'type' => $type,
        'user_id' => $userId,
        'quantity' => 1,
        'token_expiry' => $expiry,
      ]);
    }
  }

  protected function createFreeOrder($userId, $item, $itemId, $type)
  {
    $order = acadlix()->model()->order()->create([
      'user_id' => $userId,
      'status' => Order::STATUS_PENDING,
      'extra_charges' => 0,
      'total_amount' => 0,
    ]);

    $order->order_items()->create([
      'item_id' => $itemId,
      'item_title' => $item->post_title,
      'type' => $type,
      'quantity' => 1,
      'price' => 0,
      'discount' => 0,
      'price_after_discount' => 0,
      'additional_fee' => 0,
      'tax' => 0,
      'price_after_tax' => 0,
    ]);

    $order->updateOrCreateMeta('payment_method', 'free');
    $order->success_order();

  }

  protected function successResponse($redirectTo, $data = [])
  {
    $pageId = $redirectTo === 'checkout'
      ? acadlix()->helper()->acadlix_get_option('acadlix_checkout_page_id')
      : acadlix()->helper()->acadlix_get_option('acadlix_dashboard_page_id');

    return [
      ...$data,
      'status' => 'success',
      'code' => ['status' => 200],
      'redirect' => esc_url(get_permalink($pageId)),
    ];
  }

  public function post_start_now($request)
  {
    // 1) Pre Parameter Filter: allow callers to mutate incoming params before validation
    $params = apply_filters('acadlix_pre_post_start_now_params', $request->get_json_params(), $request);

    if (is_array($params) && count($params) === 0) {
      return new WP_Error(
        'no_data_found',
        __('Required item_id and type', 'acadlix'),
        ['status' => 404]
      );
    }

    // ---------- Validate ----------
    foreach (['item_id', 'type'] as $field) {
      $param = !empty($params[$field]) ? $params[$field] : $request->get_param($field);

      if (empty($param)) {
        return new WP_Error(
          'missing_params',
          sprintf(__('The %s parameter is required.', 'acadlix'), $field),
          ['status' => 400]
        );
      }
    }

    // 2) Payload/Data Filter: normalize values before core execution
    $payload = apply_filters('acadlix_post_start_now_payload', [
      'user_id' => (int) ($params['user_id'] ?? 0),
      'item_id' => $params['item_id'],
      'type' => $params['type'],
      'cart_token' => $params['cart_token'] ?? null,
      'token_expiry' => $params['token_expiry'] ?? 0,
    ], $params);


    // ---------- Guest User ----------
    if ($payload['user_id'] === 0) {
      if (empty($payload['cart_token'])) {
        return new WP_Error(
          'missing_params',
          __('The cart_token parameter is required.', 'acadlix'),
          ['status' => 400]
        );
      }

      $this->addToCart($payload['cart_token'], $payload['item_id'], $payload['type'], 0, $payload['token_expiry']);

      $res = $this->successResponse('checkout');

      // 3) Lifecycle Action: guest checkout branch
      do_action('acadlix_post_start_now_guest', $res, $payload, $params);

      // 4) Outbound Response Filter: allow response augmentation
      $res = apply_filters('acadlix_post_start_now_response', $res, $payload, $params);

      return rest_ensure_response($res);
    }

    // ---------- Logged-in User ----------
    $item = $this->get_item($payload['item_id'], $payload['type']);

    if (!$item) {
      return new WP_Error(
        'item_not_found',
        __('Item not found', 'acadlix'),
        ['status' => 404]
      );
    }

    if ($item->isFree()) {
      if (!$item->isPurchasedBy($payload['user_id'])) {
        $this->createFreeOrder($payload['user_id'], $item, $payload['item_id'], $payload['type']);
      }

      $res = $this->successResponse('dashboard');
      do_action('acadlix_post_start_now_free_course', $res, $payload, $item, $params);
      $res = apply_filters('acadlix_post_start_now_response', $res, $payload, $params);

      return rest_ensure_response($res);
    }

    $this->addToCart($payload['cart_token'], $payload['item_id'], $payload['type'], $payload['user_id'], $payload['token_expiry']);

    $res = $this->successResponse('checkout');
    do_action('acadlix_post_start_now_paid_course', $res, $payload, $item, $params);
    $res = apply_filters('acadlix_post_start_now_response', $res, $payload, $params);

    return rest_ensure_response($res);
  }

  public function post_add_wishlist($request)
  {
    $errors = [];
    $required_fields = array('item_id', 'user_id', 'type');
    $params = $request->get_json_params();

    // 1. FILTER: Allow modification or short-circuiting of incoming parameters before validation
    $params = apply_filters('acadlix_pre_add_wishlist_params', $params, $request);

    if (is_array($params) && count($params) == 0) {
      return new WP_Error('no_data_found', __('Required item id, user_id, and type', 'acadlix'), array('status' => 404));
    }

    foreach ($required_fields as $field) {
      // Fallback to params array if get_param fails due to filter mutations
      $param = !empty($params[$field]) ? $params[$field] : $request->get_param($field);

      if (empty($param)) {
        /* translators: %s is the required field */
        $errors[] = sprintf(__('The %s parameter is required.', 'acadlix'), $field);
      }
    }

    if (!empty($errors)) {
      return new WP_Error('missing_params', implode(' ', $errors), array('status' => 400));
    }
    $user_meta = acadlix()->model()->userActivityMeta()
      ->ofWishlist()
      ->where('type_id', $params['item_id'])
      ->where('user_id', $params['user_id'])
      ->where('type', $params['type'])
      ->first();
    if (!$user_meta) {
      $insert_data = [
        'user_id' => $params['user_id'],
        'type' => $params['type'],
        'type_id' => $params['item_id'],
        'meta_key' => "wishlist", // phpcs:ignore
        'meta_value' => 1 // phpcs:ignore
      ];

      // 2. FILTER & ACTION: Before creating a brand new row
      $insert_data = apply_filters('acadlix_insert_wishlist_data', $insert_data, $params);
      do_action('acadlix_before_create_wishlist', $insert_data);

      $user_meta = acadlix()->model()->userActivityMeta()->create($insert_data);

      // 3. ACTION: Specific to a newly created row
      do_action('acadlix_created_wishlist', $user_meta, $insert_data);
    } else {
      $update_data = [
        'meta_value' => 1 // phpcs:ignore
      ];

      // 4. FILTER & ACTION: Before updating an existing row
      $update_data = apply_filters('acadlix_update_wishlist_data', $update_data, $user_meta, $params);
      do_action('acadlix_before_update_wishlist', $user_meta->id, $update_data, $user_meta);

      $user_meta->update($update_data);

      // 5. ACTION: Specific to an updated row
      do_action('acadlix_updated_wishlist', $user_meta->id, $user_meta);
    }

    /**
     * Hook: acadlix_wishlist_item_added
     * Fires when an item is added to the wishlist.
     *
     * @param object $user_meta The wishlist meta object.
     * @param array  $params    Request parameters (item_id, user_id, type).
     */
    do_action('acadlix_wishlist_item_added', $user_meta, $params);

    // 6. FILTER: Allow other extensions to format or append data to the final API response
    $res = array(
      'status' => 'success',
      'code' => array('status' => 200),
      'data' => $user_meta
    );
    $res = apply_filters('acadlix_add_wishlist_response', $res, $user_meta, $params);

    return rest_ensure_response($res);
  }

  public function post_remove_wishlist($request)
  {
    $errors = [];
    $required_fields = array('item_id', 'user_id', 'type');
    $params = $request->get_json_params();

    // 1. FILTER: Allow modification or short-circuiting of incoming parameters before validation
    $params = apply_filters('acadlix_pre_remove_wishlist_params', $params, $request);

    if (is_array($params) && count($params) == 0) {
      return new WP_Error('no_data_found', __('Required item id, user_id, and type', 'acadlix'), array('status' => 404));
    }

    foreach ($required_fields as $field) {
      $param = !empty($params[$field]) ? $params[$field] : $request->get_param($field);

      if (empty($param)) {
        /* translators: %s is the required field */
        $errors[] = sprintf(__('The %s parameter is required.', 'acadlix'), $field);
      }
    }

    if (!empty($errors)) {
      return new WP_Error('missing_params', implode(' ', $errors), array('status' => 400));
    }

    $wishlist = acadlix()->model()->userActivityMeta()
      ->ofWishlist()
      ->where('type_id', $params['item_id'])
      ->where('user_id', $params['user_id'])
      ->where('type', $params['type'])
      ->first();

    if ($wishlist) {
      // 2. ACTION (CRITICAL): Fires BEFORE the data is destroyed.
      // Third-party add-ons can read $wishlist properties before they vanish.
      do_action('acadlix_before_remove_wishlist', $wishlist->id, $wishlist, $params);

      $wishlist->delete();

      // 3. ACTION (PAST TENSE): Fires AFTER successful database deletion.
      // Perfect for clearing user data caches or tracking analytics.
      do_action('acadlix_wishlist_item_removed', $params['item_id'], $params['user_id'], $params);
    }
    $res = array(
      'status' => 'success',
      'code' => array('status' => 200),
      'message' => __('Course removed from the wishlist', 'acadlix')
    );

    // 4. FILTER: Allow other modules to modify or add payload metadata to the REST response
    $res = apply_filters('acadlix_remove_wishlist_response', $res, $params);

    return rest_ensure_response($res);
  }

  public function post_submit_review($request)
  {
    $errors = [];
    $required_fields = array('course_id', 'user_id', 'rating', 'review_text');

    // 1) Pre Parameter Filter: allow callers to mutate incoming params
    $params = apply_filters('acadlix_pre_post_submit_review_params', $request->get_json_params(), $request);

    if (is_array($params) && count($params) == 0) {
      return new WP_Error('no_data_found', __('Required course id and user_id', 'acadlix'), array('status' => 404));
    }

    foreach ($required_fields as $field) {
      $param = !empty($params[$field]) ? $params[$field] : $request->get_param($field);

      if (empty($param)) {
        /* translators: %s is the required field */
        $errors[] = sprintf(__('The %s parameter is required.', 'acadlix'), $field);
      }
    }

    if (!empty($errors)) {
      return new WP_Error('missing_params', implode(' ', $errors), array('status' => 400));
    }

    // 2) Payload/Data Filter: assemble payload and allow mutation
    $payload = apply_filters('acadlix_post_submit_review_payload', [
      'user_id' => $params['user_id'],
      'course_id' => $params['course_id'],
      'rating' => intval($params['rating']),
      'review_text' => sanitize_text_field($params['review_text']),
      'review_id' => $params['review_id'] ?? 0,
    ], $params);

    // 3) Core execution
    $review = acadlix()->model()->courseReview()->add_or_update_review(
      $payload['user_id'],
      $payload['course_id'],
      $payload['rating'],
      $payload['review_text'],
      $payload['review_id'] ?? 0
    );

    if (is_wp_error($review)) {
      return $review;
    }

    // 4) Lifecycle Action: conditional hooks based on create vs update
    if (empty($payload['review_id']) || intval($payload['review_id']) === 0) {
      do_action('acadlix_review_created', $review, $payload, $params);
    } else {
      do_action('acadlix_review_updated', $review, $payload, $params);
    }

    // 5) Outbound Response Filter: allow response augmentation
    $res = array(
      'status' => 'success',
      'code' => array('status' => 200),
      'data' => $review
    );
    $res = apply_filters('acadlix_post_submit_review_response', $res, $review, $params);

    return rest_ensure_response($res);
  }

  public function post_load_more_reviews($request)
  {
    $errors = [];
    $required_fields = array('course_id', 'current_page', 'skip_count', 'take_count');

    // 1) Pre Parameter Filter: allow callers to mutate incoming params
    $params = apply_filters('acadlix_pre_post_load_more_reviews_params', $request->get_json_params(), $request);

    if (is_array($params) && count($params) == 0) {
      return new WP_Error('no_data_found', __('Required course id and page number', 'acadlix'), array('status' => 404));
    }

    foreach ($required_fields as $field) {
      $param = !empty($params[$field]) ? $params[$field] : $request->get_param($field);

      if (empty($param) && $param !== 0) {
        /* translators: %s is the required field */
        $errors[] = sprintf(__('The %s parameter is required.', 'acadlix'), $field);
      }
    }

    if (!empty($errors)) {
      return new WP_Error('missing_params', implode(' ', $errors), array('status' => 400));
    }

    // 2) Payload/Data Filter: normalize and allow mutation
    $payload = apply_filters('acadlix_post_load_more_reviews_payload', [
      'course_id' => intval($params['course_id']),
      'current_page' => max(1, intval($params['current_page'])),
      'skip_count' => max(0, intval($params['skip_count'])),
      'take_count' => max(1, intval($params['take_count'])),
    ], $params);

    $reviews_query = acadlix()
      ->model()
      ->courseReview()
      ->ofCourseRating()
      ->ofApproved()
      ->where('comment_post_ID', $payload['course_id'])
      ->orderBy('comment_date', 'DESC');

    $total_reviews = $reviews_query->count();

    $reviews = $reviews_query
      ->skip($payload['skip_count'])
      ->take($payload['take_count'])
      ->get();

    setup_postdata(get_post($payload['course_id']));
    ob_start();
    acadlix()->view()->singleCourse()->course_main_reviews_list($reviews);
    $review_html = ob_get_clean();
    wp_reset_postdata();

    $res = array(
      'reviews' => $reviews,
      'reviews_html' => $review_html,
      'total_reviews' => $total_reviews,
      'next_page' => $payload['current_page'] + 1,
    );

    // 3) Lifecycle Action: allow listeners to react to this retrieval
    do_action('acadlix_post_load_more_reviews', $reviews, $payload, $params);

    // 4) Outbound Response Filter
    $res = apply_filters('acadlix_post_load_more_reviews_response', $res, $reviews, $payload, $params);

    return rest_ensure_response($res);
  }
  public function check_permission($request)
  {
    return wp_verify_nonce(
      $request->get_header('X-WP-Nonce'),
      'wp_rest'
    );
  }
}