<?php

namespace ShopManagerPro\Jobs;

use ShopManagerPro\Products\ProductAPI;

class JobAPI {
	public static function init() {
		add_action('rest_api_init', [self::class, 'registerRoutes']);
	}

	public static function registerRoutes() {
		register_rest_route(\ShopManagerPro\Shared\Utils\Constants::API_NAMESPACE, '/jobs', [['methods' => 'GET', 'callback' => [self::class, 'getJobs'], 'permission_callback' => [\ShopManagerPro\Shared\CapabilityService::class, 'requireReadCapability']], 'schema' => fn () => self::getJobsSchema()]);
		register_rest_route(\ShopManagerPro\Shared\Utils\Constants::API_NAMESPACE, '/jobs/(?P<id>\d+)', [['methods' => 'GET', 'callback' => [self::class, 'getJob'], 'permission_callback' => [\ShopManagerPro\Shared\CapabilityService::class, 'requireReadCapability'], 'args' => ['id' => ['type' => 'integer', 'required' => true, 'validate_callback' => fn ($param) => is_numeric($param) && intval($param) > 0]]], 'schema' => fn () => self::getJobSchema()]);
		register_rest_route(\ShopManagerPro\Shared\Utils\Constants::API_NAMESPACE, '/jobs/(?P<id>\d+)/stop', [['methods' => 'POST', 'callback' => [self::class, 'stopJob'], 'permission_callback' => [\ShopManagerPro\Shared\CapabilityService::class, 'requireEditCapability'], 'args' => ['id' => ['type' => 'integer', 'required' => true, 'validate_callback' => fn ($param) => is_numeric($param) && intval($param) > 0]]]]);
		register_rest_route(\ShopManagerPro\Shared\Utils\Constants::API_NAMESPACE, '/jobs/processQueue', [['methods' => 'POST', 'callback' => [self::class, 'processQueue'], 'permission_callback' => [\ShopManagerPro\Shared\CapabilityService::class, 'requireEditCapability']], 'schema' => fn () => ['title' => 'processQueue', 'type' => 'object', 'additionalProperties' => false, 'required' => ['success', 'message'], 'properties' => ['success' => ['type' => 'boolean'], 'message' => ['type' => 'string']]]]);
	}

	public static function getJobSchema() {
		return ['title' => 'job', 'type' => 'object', 'additionalProperties' => false, 'required' => ['id', 'type', 'actions', 'status', 'totalItems', 'processedItems', 'startTime', 'finishTime', 'user'], 'properties' => ['id' => ['type' => 'integer'], 'type' => ['type' => 'string', 'enum' => ['product_update']], 'actions' => ProductAPI::getProductBulkEditSchema(true)['properties']['actions'], 'status' => ['type' => 'string', 'enum' => ['pending', 'running', 'finished_successfully', 'finished_with_errors', 'stopped']], 'totalItems' => ['type' => 'integer'], 'processedItems' => ['type' => 'integer'], 'startTime' => ['type' => 'string', 'format' => 'date-time'], 'finishTime' => ['type' => ['string', 'null'], 'format' => 'date-time'], 'user' => ['anyOf' => [['type' => ['object'], 'required' => ['id', 'name'], 'additionalProperties' => false, 'properties' => ['id' => ['type' => 'integer'], 'name' => ['type' => 'string']]], ['type' => 'null']]], 'products' => ['type' => 'object', 'additionalProperties' => ['type' => 'object', 'required' => ['id', 'status', 'changes', 'creationTime', 'finishTime'], 'properties' => ['id' => ['type' => 'integer'], 'status' => ['type' => 'string', 'enum' => ['pending', 'success', 'error']], 'creationTime' => ['type' => 'string', 'format' => 'date-time'], 'finishTime' => ['type' => ['string', 'null'], 'format' => 'date-time'], 'changes' => ['type' => 'object', 'additionalProperties' => false, 'properties' => ProductAPI::getProductChangeSchema()], 'error' => ['anyOf' => [['type' => ['object'], 'required' => ['field', 'expected', 'actual'], 'additionalProperties' => false, 'properties' => ['code' => ['type' => 'string', 'enum' => ['value_mismatch'], 'default' => 'value_mismatch'], 'field' => ['type' => 'string'], 'expected' => ['type' => ['string', 'number', 'array', 'null']], 'actual' => ['type' => ['string', 'number', 'array', 'null']]]], ['type' => ['object'], 'required' => ['message'], 'additionalProperties' => false, 'properties' => ['code' => ['type' => 'string', 'enum' => ['unknown_error'], 'default' => 'unknown_error'], 'message' => ['type' => 'string']]]]]]]]]];
	}

	public static function getJobsSchema() {
		return ['title' => 'jobs', 'type' => 'array', 'items' => self::getJobSchema()];
	}

	public static function getJobs(\WP_REST_Request $request) {
		$jobs = JobRepository::getJobs();
		$jobs = array_map(fn ($job) => $job->toJson(), $jobs);
		$jobs = array_values($jobs);

		return rest_ensure_response($jobs);
	}

	public static function getJob(\WP_REST_Request $request) {
		$id = intval($request['id']);
		$job = JobRepository::getJob($id, true);
		if (!$job) {
			return new \WP_REST_Response(['code' => 'job_not_found', 'message' => sprintf('Job with ID %d not found', $id), 'data' => ['status' => 404]], 404);
		}

return rest_ensure_response($job->toJson());
	}

	public static function stopJob(\WP_REST_Request $request) {
		$id = intval($request['id']);
		$job = JobRepository::getJob($id);
		if (!$job) {
			return new \WP_REST_Response(['code' => 'job_not_found', 'message' => sprintf('Job with ID %d not found', $id), 'data' => ['status' => 404]], 404);
		} if (JobUtil::isFinished($job)) {
			return new \WP_REST_Response(['code' => 'job_already_finished', 'message' => sprintf('Job with ID %d is already finished and cannot be stopped', $id), 'data' => ['status' => 400]], 400);
		} JobRepository::stopJob($id);

		return rest_ensure_response(['success' => true, 'message' => sprintf('Job with ID %d has been stopped', $id)]);
	}

	public static function processQueue(\WP_REST_Request $request) {
		global $wpdb;
		$unfinishedJobCount = $wpdb->get_var('SELECT COUNT(*) FROM '.\ShopManagerPro\Shared\DatabaseManagerService::$jobsTableName." WHERE status IN ('pending' , 'running')");
		if (!$unfinishedJobCount) {
			return rest_ensure_response(['success' => false, 'message' => 'No unfinished jobs found']);
		} \ShopManagerPro\Shared\Utils\Logger::info('Manually triggering ActionScheduler queue processing', ['unfinished_count' => $unfinishedJobCount]);
		try {
			$processed = \ActionScheduler::runner()->run();

			return rest_ensure_response(['success' => true, 'message' => 'Job queue processed', 'processed' => $processed]);
		} catch (\Throwable $e) {
			\ShopManagerPro\Shared\Utils\Logger::exception('Error triggering ActionScheduler queue processing', $e);

			return new \WP_REST_Response(['code' => 'processing_error', 'message' => 'Failed to trigger queue processing', 'data' => ['status' => 500]], 500);
		}
	}
}
