<?php

namespace Limb_Chatbot\Includes\Api\V1\Controllers;

use Limb_Chatbot\Includes\Repositories\Admin_Notifications_Repository;
use Limb_Chatbot\Includes\Services\Admin_Notifications_Enricher;
use Limb_Chatbot\Includes\Services\User_Sync_Tracker;
use Limb_Chatbot\Includes\Services\Helper;
use WP_Error;
use WP_REST_Request;
use WP_REST_Response;
use WP_REST_Server;

/**
 * Admin Notifications controller.
 *
 * Exposes admin-only endpoints to list and delete notification events
 * (stored in the `lbaic_channel_events` queue).
 */
class Admin_Notifications_Controller extends Rest_Controller {

	/**
	 * REST route base.
	 *
	 * @var string
	 */
	protected $rest_base = 'notifications';

	/**
	 * @var Admin_Notifications_Repository
	 */
	private Admin_Notifications_Repository $repository;

	/**
	 * @var Admin_Notifications_Enricher
	 */
	private Admin_Notifications_Enricher $enricher;

	public function __construct() {
		$this->repository = new Admin_Notifications_Repository();
		$this->enricher   = new Admin_Notifications_Enricher();
	}

	/**
	 * Registers REST routes.
	 *
	 * GET    /notifications
	 * DELETE /notifications/{id}
	 */
	public function register_routes(): void {
		register_rest_route( $this->namespace, '/' . $this->rest_base, [
			[
				'methods'             => WP_REST_Server::READABLE,
				'callback'            => [ $this, 'get_items' ],
				'permission_callback' => [ $this, 'permission_callback' ],
				'args'                => $this->get_collection_params(),
			],
		] );

		register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', [
			[
				'methods'             => WP_REST_Server::DELETABLE,
				'callback'            => [ $this, 'delete_item' ],
				'permission_callback' => [ $this, 'permission_callback' ],
				'args'                => [
					'id' => [
						'required'          => true,
						'type'              => 'integer',
						'sanitize_callback' => 'absint',
						'validate_callback' => function ( $value ) {
							return $value > 0;
						},
					],
				],
			],
		] );

		register_rest_route( $this->namespace, '/' . $this->rest_base . '/mark-read', [
			[
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => [ $this, 'mark_items_read' ],
				'permission_callback' => [ $this, 'permission_callback' ],
				'args'                => [
					'ids' => [
						'required'          => true,
						'description'       => __( 'Notification IDs to mark as read (array), or the string "all".', 'limb-chatbot' ),
						'sanitize_callback' => function ( $value ) {
							if ( is_string( $value ) && strtolower( trim( $value ) ) === 'all' ) {
								return 'all';
							}
							$value = is_array( $value ) ? $value : [];

							return array_values(
								array_unique(
									array_filter(
										array_map( 'absint', $value ),
										static function ( int $id ): bool {
											return $id > 0;
										}
									)
								)
							);
						},
						'validate_callback' => function ( $value ) {
							if ( is_string( $value ) && strtolower( trim( $value ) ) === 'all' ) {
								return true;
							}

							return is_array( $value ) && ! empty( $value );
						},
					],
				],
			],
		] );
	}

	/**
	 * Query params: pagination + order_by/order.
	 */
	public function get_collection_params(): array {
		return array_merge( parent::get_collection_params(), [
			'orderby'  => [
				'description'       => __( 'Sort the notifications collection by attribute.', 'limb-chatbot' ),
				'type'              => 'string',
				'default'           => 'created_at',
				'enum'              => [ 'created_at', 'id' ],
				'validate_callback' => 'rest_validate_request_arg',
				'sanitize_callback' => 'sanitize_key',
			],
			'order_by' => [
				'description'       => __( 'Alias of `orderby`.', 'limb-chatbot' ),
				'type'              => 'string',
				'default'           => 'created_at',
				'enum'              => [ 'created_at', 'id' ],
				'validate_callback' => 'rest_validate_request_arg',
				'sanitize_callback' => 'sanitize_key',
			],
			'order'    => [
				'description'       => __( 'Sort order: asc or desc.', 'limb-chatbot' ),
				'type'              => 'string',
				'default'           => 'desc',
				'enum'              => [ 'asc', 'desc' ],
				'validate_callback' => 'rest_validate_request_arg',
				'sanitize_callback' => 'sanitize_key',
			],
			'since'    => [
				'description'       => __( 'Optional Unix timestamp (seconds, like PHP `time()`); when set, returns events created after this point (continuous polling mode).',
					'limb-chatbot' ),
				'type'              => 'integer',
				'required'          => false,
				'sanitize_callback' => 'absint',
				'validate_callback' => function ( $value ) {
					// Allow 0/empty => treat as unset.
					$value = (int) $value;

					return $value >= 0;
				},
			],
		] );
	}

	/**
	 * Restrict access to logged-in website administrators.
	 */
	public function permission_callback( $request ): bool {
		if ( ! parent::permission_callback( $request ) ) {
			return false;
		}

		return current_user_can( 'manage_options' ) && (int) get_current_user_id() > 0;
	}

	/**
	 * GET /notifications
	 */
	public function get_items( $request ) {
		try {
			$admin_wp_user_id = (int) get_current_user_id();
			$since            = $request->get_param( 'since' );
			$server_time		= time();
			$events = $this->repository->get_events_for_admin(
				$admin_wp_user_id,
				$request->get_query_params()
			);
			$unread_total = $this->repository->get_unread_total_for_admin( $admin_wp_user_id );

			$enriched = $this->enricher->enrich( $events->get() );

			$collection = $events;
			// Replace items with enriched rows but keep pagination metadata.
			$collection->items = $enriched;

			// Pagination metadata is only meaningful in pagination mode.
			if ( empty( $since ) ) {
				$this->set_pagination_params( $collection, $request );
			}

			$collection->push_property( 'server_time', $server_time );
			$collection->push_property( 'unread_total', $unread_total );

			// Successful request: mark admin as "recently opened" for stale-email gating.
			( new User_Sync_Tracker() )->record_admin_settings_sync( $admin_wp_user_id );

			return rest_ensure_response( $collection );
		} catch ( \Exception $e ) {
			Helper::log( $e, __METHOD__ );

			return Helper::get_wp_error( $e );
		}
	}

	/**
	 * DELETE /notifications/{id}
	 */
	public function delete_item( $request ) {
		try {
			$admin_wp_user_id = (int) get_current_user_id();
			$event_id         = absint( $request->get_param( 'id' ) );

			$deleted = $this->repository->delete_event_for_admin( $admin_wp_user_id, $event_id );
			if ( ! $deleted ) {
				return new WP_Error( 'not_found',
					__( 'Notification not found.', 'limb-chatbot' ),
					[ 'id' => $event_id ] );
			}

			// Successful delete: mark admin as "recently opened" for stale-email gating.
			( new User_Sync_Tracker() )->record_admin_settings_sync( $admin_wp_user_id );

			return rest_ensure_response( [ 'deleted' => true ] );
		} catch ( \Exception $e ) {
			Helper::log( $e, __METHOD__ );

			return Helper::get_wp_error( $e );
		}
	}

	/**
	 * POST /notifications/mark-read
	 *
	 * Marks one or more admin notifications as read using event IDs.
	 */
	public function mark_items_read( $request ) {
		try {
			$admin_wp_user_id = (int) get_current_user_id();
			$ids              = $request->get_param( 'ids' );
			$ids              = ( is_string( $ids ) && strtolower( trim( $ids ) ) === 'all' )
				? 'all'
				: ( is_array( $ids ) ? $ids : [] );

			$updated = $this->repository->mark_events_as_read_for_admin( $admin_wp_user_id, $ids );

			// Successful state update: mark admin as "recently opened" for stale-email gating.
			( new User_Sync_Tracker() )->record_admin_settings_sync( $admin_wp_user_id );

			return rest_ensure_response(
				[
					'updated' => $updated,
					'ids'     => is_array( $ids ) ? array_values( array_map( 'absint', $ids ) ) : 'all',
				]
			);
		} catch ( \Exception $e ) {
			Helper::log( $e, __METHOD__ );

			return Helper::get_wp_error( $e );
		}
	}
}

