<?php
// DESCRIPTION: REST API controller for sync log operations including listing, viewing,
// retrying failed syncs, deleting entries, and fetching aggregate stats.

namespace SheetWise\Api;

use SheetWise\Sync\SyncLogger;
use WP_REST_Server;

class SyncLogs extends Swise_REST_Controller {

	/**
	 * Route name
	 *
	 * @since 2.0.0
	 *
	 * @var string
	 */
	protected $base = 'sync-logs';

	/**
	 * Register routes
	 *
	 * @since 2.0.0
	 *
	 * @return void
	 */
	public function register_routes() {
		register_rest_route(
			$this->namespace,
			'/' . $this->base,
			[
				[
					'methods'             => WP_REST_Server::READABLE,
					'callback'            => [ $this, 'get_items' ],
					'permission_callback' => [ $this, 'permission_check' ],
					'args'                => [
						'integration_id' => [
							'type'              => 'integer',
							'sanitize_callback' => 'absint',
						],
						'status'         => [
							'type'              => 'string',
							'sanitize_callback' => 'sanitize_text_field',
						],
						'date_from'      => [
							'type'              => 'string',
							'sanitize_callback' => 'sanitize_text_field',
						],
						'date_to'        => [
							'type'              => 'string',
							'sanitize_callback' => 'sanitize_text_field',
						],
						'page'           => [
							'type'              => 'integer',
							'default'           => 1,
							'sanitize_callback' => 'absint',
						],
						'per_page'       => [
							'type'              => 'integer',
							'default'           => 20,
							'sanitize_callback' => 'absint',
						],
					],
				],
			]
		);

		register_rest_route(
			$this->namespace,
			'/' . $this->base . '/stats',
			[
				[
					'methods'             => WP_REST_Server::READABLE,
					'callback'            => [ $this, 'get_stats' ],
					'permission_callback' => [ $this, 'permission_check' ],
				],
			]
		);

		register_rest_route(
			$this->namespace,
			'/' . $this->base . '/(?P<id>[\d]+)',
			[
				[
					'methods'             => WP_REST_Server::READABLE,
					'callback'            => [ $this, 'get_item' ],
					'permission_callback' => [ $this, 'permission_check' ],
				],
			]
		);

		register_rest_route(
			$this->namespace,
			'/' . $this->base . '/(?P<id>[\d]+)/retry',
			[
				[
					'methods'             => WP_REST_Server::CREATABLE,
					'callback'            => [ $this, 'retry_item' ],
					'permission_callback' => [ $this, 'permission_check' ],
				],
			]
		);

		register_rest_route(
			$this->namespace,
			'/' . $this->base . '/(?P<id>[\d]+)',
			[
				[
					'methods'             => WP_REST_Server::DELETABLE,
					'callback'            => [ $this, 'delete_item' ],
					'permission_callback' => [ $this, 'permission_check' ],
				],
			]
		);
	}

	/**
	 * Get paginated list of sync logs
	 *
	 * @since 2.0.0
	 *
	 * @param \WP_REST_Request $request
	 *
	 * @return \WP_REST_Response
	 */
	public function get_items( $request ) {
		$logger = new SyncLogger();

		$result = $logger->get_logs( [
			'integration_id' => $request->get_param( 'integration_id' ),
			'status'         => $request->get_param( 'status' ),
			'date_from'      => $request->get_param( 'date_from' ),
			'date_to'        => $request->get_param( 'date_to' ),
			'page'           => $request->get_param( 'page' ),
			'per_page'       => $request->get_param( 'per_page' ),
		] );

		// Attach integration titles for display
		foreach ( $result['items'] as &$item ) {
			$integration  = get_post( $item->integration_id );
			$item->integration_title = $integration ? $integration->post_title : '';
		}

		return rest_ensure_response( [
			'code'    => 200,
			'success' => true,
			'data'    => $result['items'],
			'total'   => $result['total'],
			'pages'   => $result['pages'],
		] );
	}

	/**
	 * Get a single sync log entry
	 *
	 * @since 2.0.0
	 *
	 * @param \WP_REST_Request $request
	 *
	 * @return \WP_REST_Response
	 */
	public function get_item( $request ) {
		$logger = new SyncLogger();
		$log    = $logger->get_log( $request->get_param( 'id' ) );

		if ( ! $log ) {
			return $this->error_response( new \WP_Error( 'not_found', __( 'Sync log entry not found.', 'sheet-wise' ) ) );
		}

		// Attach integration title
		$integration       = get_post( $log->integration_id );
		$log->integration_title = $integration ? $integration->post_title : '';

		return rest_ensure_response( [
			'code'    => 200,
			'success' => true,
			'data'    => $log,
		] );
	}

	/**
	 * Retry a failed or dead-lettered sync
	 *
	 * Re-enqueues the original sync data via Action Scheduler
	 *
	 * @since 2.0.0
	 *
	 * @param \WP_REST_Request $request
	 *
	 * @return \WP_REST_Response
	 */
	public function retry_item( $request ) {
		$logger = new SyncLogger();
		$log    = $logger->get_log( $request->get_param( 'id' ) );

		if ( ! $log ) {
			return $this->error_response( new \WP_Error( 'not_found', __( 'Sync log entry not found.', 'sheet-wise' ) ) );
		}

		if ( ! in_array( $log->status, [ 'failed', 'dead_lettered' ], true ) ) {
			return $this->error_response(
				new \WP_Error( 'invalid_status', __( 'Only failed or dead-lettered syncs can be retried.', 'sheet-wise' ) )
			);
		}

		$data_payload = json_decode( $log->data_payload, true );

		if ( empty( $data_payload ) || empty( $log->hook ) ) {
			return $this->error_response(
				new \WP_Error( 'missing_data', __( 'This sync entry does not have enough data to retry.', 'sheet-wise' ) )
			);
		}

		// Re-enqueue the sync via Action Scheduler
		$action_args = [
			'hook'   => $log->hook,
			'values' => $data_payload,
			'type'   => 'retry',
			'id'     => $log->integration_id,
		];

		as_enqueue_async_action(
			'sheetwise_scheduled_' . $log->hook,
			[ $action_args ],
			'swise_' . explode( '_', $log->hook )[0]
		);

		// Update the log entry status to retrying
		$logger->update_log( $log->id, [ 'status' => 'retrying' ] );

		return rest_ensure_response( [
			'code'    => 200,
			'success' => true,
			'message' => __( 'Sync has been re-queued for processing.', 'sheet-wise' ),
		] );
	}

	/**
	 * Delete a sync log entry
	 *
	 * @since 2.0.0
	 *
	 * @param \WP_REST_Request $request
	 *
	 * @return \WP_REST_Response
	 */
	public function delete_item( $request ) {
		$logger  = new SyncLogger();
		$deleted = $logger->delete_log( $request->get_param( 'id' ) );

		if ( ! $deleted ) {
			return $this->error_response( new \WP_Error( 'delete_failed', __( 'Failed to delete sync log entry.', 'sheet-wise' ) ) );
		}

		return rest_ensure_response( [
			'code'    => 200,
			'success' => true,
			'message' => __( 'Sync log entry deleted.', 'sheet-wise' ),
		] );
	}

	/**
	 * Get aggregate sync stats
	 *
	 * @since 2.0.0
	 *
	 * @param \WP_REST_Request $request
	 *
	 * @return \WP_REST_Response
	 */
	public function get_stats( $request ) {
		$logger = new SyncLogger();
		$stats  = $logger->get_stats();

		return rest_ensure_response( [
			'code'    => 200,
			'success' => true,
			'data'    => $stats,
		] );
	}
}
