<?php

namespace Yuvayana\Acadlix\Common\REST\Admin;

use WP_Error;
use WP_REST_Server;
defined('ABSPATH') || exit();

class AdminAnnouncementController
{
  protected $namespace = 'acadlix/v1';

  protected $base = 'admin-announcement';

  public function register_routes()
  {
    register_rest_route(
      $this->namespace,
      '/' . $this->base,
      [
        [
          'methods' => WP_REST_Server::READABLE,
          'callback' => [$this, 'get_announcements'],
          'permission_callback' => function () {
            return current_user_can('acadlix_show_announcement');
          },
        ],
        [
          'methods' => WP_REST_Server::CREATABLE,
          'callback' => [$this, 'post_create_announcement'],
          'permission_callback' => function () {
            return current_user_can('acadlix_add_announcement');
          },
        ],
      ]
    );

    register_rest_route(
      $this->namespace,
      '/' . $this->base . '/create',
      [
        [
          'methods' => WP_REST_Server::READABLE,
          'callback' => [$this, 'get_create_announcement'],
          'permission_callback' => function () {
            return current_user_can('acadlix_add_announcement');
          },
        ],
      ]
    );

    register_rest_route(
      $this->namespace,
      '/' . $this->base . '/(?P<announcement_id>[\d]+)',
      [
        [
          'methods' => WP_REST_Server::READABLE,
          'callback' => [$this, 'get_announcement_by_id'],
          'permission_callback' => function () {
            return current_user_can('acadlix_edit_announcement');
          },
          'args' => array(
            'announcement_id' => array(
              'validate_callback' => function ($param, $request, $key) {
                return is_numeric($param);
              }
            ),
          ),
        ],
        [
          'methods' => WP_REST_Server::EDITABLE,
          'callback' => [$this, 'update_announcement_by_id'],
          'permission_callback' => function () {
            return current_user_can('acadlix_edit_announcement');
          },
          'args' => array(
            'announcement_id' => array(
              'validate_callback' => function ($param, $request, $key) {
                return is_numeric($param);
              }
            ),
          ),
        ],
        [
          'methods' => WP_REST_Server::DELETABLE,
          'callback' => [$this, 'delete_announcement_by_id'],
          'permission_callback' => function () {
            return current_user_can('acadlix_delete_announcement');
          },
          'args' => array(
            'announcement_id' => array(
              'validate_callback' => function ($param, $request, $key) {
                return is_numeric($param);
              }
            ),
          ),
        ],
      ]
    );

    register_rest_route(
      $this->namespace,
      '/' . $this->base . '/delete-bulk-announcement',
      [
        [
          'methods' => WP_REST_Server::DELETABLE,
          'callback' => [$this, 'delete_bulk_announcement'],
          'permission_callback' => function () {
            return current_user_can('acadlix_bulk_delete_announcement');
          },
        ],
      ]
    );
  }

  public function get_announcements($request)
  {
    $res = [];
    $params = $request->get_params();
    $search = isset($params['search']) ? trim((string) $params['search']) : '';
    $page = isset($params['page']) ? (int) $params['page'] : 0;
    $pageSize = isset($params['pageSize']) ? (int) $params['pageSize'] : 10;
    $skip = $page * $pageSize;
    $announcement = acadlix()
      ->model()
      ->announcement()
      ->ofAnnouncement()
      ->with(['course'])
      ->orderBy('ID', 'desc');
    if (!empty($search)) {
      $announcement->where(function ($query) use ($search) {
        $query->where('post_title', 'like', "%$search%")
          ->orWhereHas('course', function ($courseQuery) use ($search) {
            $courseQuery->where('post_title', 'like', "%$search%");
          });
      });
    }
    $res['total'] = $announcement->count();
    $res['announcements'] = $announcement->skip($skip)->take($pageSize)->get();
    return rest_ensure_response($res);
  }

  public function get_create_announcement($request)
  {
    $res = [];
    $res['courses'] = acadlix()
      ->model()
      ->course()
      ->ofCourse()
      ->ofPublish()
      ->without([
        'author',
        'metas',
        'course_categories',
        'course_tags',
      ])
      ->orderBy('ID', 'desc')
      ->get(['ID', 'post_title'])
      ->each
      ->setAppends([]);
    return rest_ensure_response($res);
  }

  public function post_create_announcement($request)
  {
    $res = [];
    $params = $request->get_json_params();
    $required_fields = array('title', 'post_parent', 'post_author', 'post_content');

    foreach ($required_fields as $field) {
      $param = $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_parameters', implode(' ', $errors), array('status' => 400));
    }

    try {
      // Insert the announcement post
      $announcementId = acadlix()->model()->announcement()->insertAnnouncement([
        'post_title' => $params['title'],
        'post_content' => $params['post_content'],
        'post_author' => (int) $params['post_author'], // Assign to current user
        'post_parent' => (int) $params['post_parent'], // Assign to selected course
      ]);

      if (is_wp_error($announcementId)) {
        return new WP_Error(
          'announcement_creation_failed',
          __('Failed to create the announcement.', 'acadlix'),
          ['status' => 500, 'error' => $announcementId->get_error_message()]
        );
      }

      // Retrieve and return the announcement data
      $announcement = get_post($announcementId);
      if (!$announcement) {
        return new WP_Error(
          'announcement_not_found',
          __('Created announcement not found.', 'acadlix'),
          ['status' => 500]
        );
      }

      $res['announcement'] = $announcement;
      return rest_ensure_response($res);

    } catch (Exception $e) {
      return new WP_Error(
        'exception_occurred',
        $e->getMessage(),
        ['status' => 500]
      );
    }
  }

  public function get_announcement_by_id($request)
  {
    $res = [];
    $announcement_id = $request['announcement_id'];

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

    $announcement = acadlix()->model()->announcement()->find($announcement_id);
    if ($announcement) {
      $res['announcement'] = $announcement;
    }
    $res['courses'] = acadlix()
      ->model()
      ->course()
      ->ofCourse()
      ->ofPublish()
      ->without([
        'author',
        'metas',
        'course_categories',
        'course_tags',
      ])
      ->orderBy('ID', 'desc')
      ->get(['ID', 'post_title'])
      ->each
      ->setAppends([]);
    return rest_ensure_response($res);
  }

  public function update_announcement_by_id($request)
  {
    $res = [];
    $announcementId = $request['announcement_id'];
    $params = $request->get_json_params();
    $required_fields = array('title', 'post_parent', 'post_author', 'post_content');

    foreach ($required_fields as $field) {
      $param = $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_parameters', implode(' ', $errors), array('status' => 400));
    }

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

    try {
      // Update the announcement post
      $announcementId = acadlix()->model()->announcement()->updateAnnouncement($announcementId, [
        'post_title' => $params['title'],
        'post_content' => $params['post_content'],
        'post_author' => (int) $params['post_author'], // Assign to current user
        'post_parent' => (int) $params['post_parent'], // Assign to selected course
      ]);

      if (is_wp_error($announcementId)) {
        return new WP_Error(
          'announcement_updation_failed',
          __('Failed to update the announcement.', 'acadlix'),
          ['status' => 500, 'error' => $announcementId->get_error_message()]
        );
      }

      // Retrieve and return the announcement data
      $announcement = get_post($announcementId);
      if (!$announcement) {
        return new WP_Error(
          'announcement_not_found',
          __('Updated announcement not found.', 'acadlix'),
          ['status' => 500]
        );
      }

      $res['announcement'] = $announcement;
      return rest_ensure_response($res);

    } catch (Exception $e) {
      return new WP_Error(
        'exception_occurred',
        $e->getMessage(),
        ['status' => 500]
      );
    }

  }

  public function delete_announcement_by_id($request)
  {
    $res = [];
    $announcement_id = $request['announcement_id'];

    // Validate required fields
    if (empty($announcement_id)) {
      return new WP_Error(
        'missing_id',
        __('Announcement id is required.', 'acadlix'),
        ['status' => 400]
      );
    }
    $announcement = acadlix()->model()->announcement()->deleteAnnouncement($announcement_id);

    if (is_wp_error($announcement)) {
      return new WP_Error(
        'announcement_deletion_failed',
        __('Failed to delete the announcement.', 'acadlix'),
        ['status' => 500, 'error' => $announcement->get_error_message()]
      );
    }
    $res['message'] = __('Announcement successfully deleted.', 'acadlix');
    return rest_ensure_response($res);
  }

  public function delete_bulk_announcement($request)
  {
    $res = [];
    $params = $request->get_json_params();

    // Validate required fields
    if (!is_array($params['announcement_ids']) || count($params['announcement_ids']) == 0) {
      return new WP_Error(
        'missing_ids',
        __('Announcement ids is required.', 'acadlix'),
        ['status' => 400]
      );
    }

    foreach ($params['announcement_ids'] as $announcement_id) {
      if (empty($announcement_id)) {
        return new WP_Error(
          'missing_id',
          __('Announcement id is required.', 'acadlix'),
          ['status' => 400]
        );
      }
      $announcement = acadlix()->model()->announcement()->deleteAnnouncement($announcement_id);

      if (is_wp_error($announcement)) {
        return new WP_Error(
          'announcement_deletion_failed',
          __('Failed to delete the announcement.', 'acadlix'),
          ['status' => 500, 'error' => $announcement->get_error_message()]
        );
      }
    }
    $res['message'] = __('Announcements successfully deleted.', 'acadlix');
    return rest_ensure_response($res);
  }
}