<?php

namespace ShopManagerPro\Filters;

use ShopManagerPro\Filters\DTO\Generated\Filter;
use ShopManagerPro\Filters\DTO\Generated\FilterConditionsItem;
use ShopManagerPro\Filters\DTO\Generated\FilterConditionsItemCombinator;
use ShopManagerPro\Filters\DTO\Generated\FilterConditionsItemField;
use ShopManagerPro\Filters\DTO\Generated\FilterConditionsItemFieldType;
use ShopManagerPro\Filters\DTO\Generated\FilterConditionsItemOperator;
use ShopManagerPro\Products\Fields\DTO\ProductFieldGroupType;
use ShopManagerPro\Products\Fields\FieldNameEncoderService;
use ShopManagerPro\Shared\Utils\Constants;

class FilterAPI {
	public static function getFilterSchema() {
		return ['type' => 'object', 'additionalProperties' => false, 'required' => ['id', 'name', 'conditions'], 'properties' => ['id' => ['type' => 'integer'], 'name' => ['type' => 'string'], 'conditions' => ['type' => 'array', 'items' => ['type' => 'object', 'additionalProperties' => false, 'required' => ['field', 'operator', 'value', 'not', 'combinator', 'enabled'], 'properties' => ['field' => ['type' => 'object', 'additionalProperties' => false, 'required' => ['type', 'key'], 'properties' => ['type' => ['type' => 'string', 'enum' => array_column(ProductFieldGroupType::cases(), 'value')], 'key' => ['type' => 'string']]], 'operator' => ['type' => 'string', 'enum' => ['contains', 'empty', 'ends_with', 'equals', 'greater_than_or_equal', 'greater_than', 'in', 'less_than_or_equal', 'less_than', 'starts_with']], 'value' => ['type' => ['string', 'number', 'boolean', 'array', 'null']], 'not' => ['type' => 'boolean'], 'combinator' => ['type' => 'string', 'enum' => ['AND', 'OR']], 'enabled' => ['type' => 'boolean']]]]]];
	}

	public static function getListSchema() {
		return ['title' => 'filters', 'type' => 'array', 'items' => self::getFilterSchema()];
	}

	public static function getEditSchema() {
		return ['name' => ['type' => 'string', 'required' => true, 'minLength' => 1, 'maxLength' => 60], 'conditions' => ['type' => 'array', 'required' => true, 'items' => self::getFilterSchema()['properties']['conditions']['items']]];
	}

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

	public static function registerRoutes() {
		register_rest_route(Constants::API_NAMESPACE, '/filters/get', [['methods' => 'GET', 'callback' => [self::class, 'getFilters'], 'permission_callback' => [\ShopManagerPro\Shared\CapabilityService::class, 'requireReadCapability']], 'schema' => fn () => self::getListSchema()]);
		register_rest_route(Constants::API_NAMESPACE, '/filters/create', [['methods' => 'POST', 'callback' => [self::class, 'createFilter'], 'permission_callback' => [\ShopManagerPro\Shared\CapabilityService::class, 'requireEditCapability'], 'args' => self::getEditSchema()], 'schema' => fn () => ['title' => 'createFilter', 'type' => 'object', 'additionalProperties' => false, 'required' => ['id'], 'properties' => ['id' => ['type' => 'integer']]]]);
		register_rest_route(Constants::API_NAMESPACE, '/filters/rename/(?P<id>\d+)', [['methods' => 'PUT', 'callback' => [self::class, 'renameFilter'], 'permission_callback' => [\ShopManagerPro\Shared\CapabilityService::class, 'requireEditCapability'], 'args' => ['id' => ['type' => 'integer', 'required' => true, 'validate_callback' => fn ($param) => is_numeric($param) && intval($param) > 0], 'name' => ['type' => 'string', 'required' => true]]], 'schema' => fn () => []]);
		register_rest_route(Constants::API_NAMESPACE, '/filters/update/(?P<id>\d+)', [['methods' => 'PUT', 'callback' => [self::class, 'updateFilter'], 'permission_callback' => [\ShopManagerPro\Shared\CapabilityService::class, 'requireEditCapability'], 'args' => array_merge(['id' => ['type' => 'integer', 'required' => true, 'validate_callback' => fn ($param) => is_numeric($param) && intval($param) > 0]], self::getEditSchema())], 'schema' => fn () => []]);
		register_rest_route(Constants::API_NAMESPACE, '/filters/delete/(?P<id>\d+)', [['methods' => 'DELETE', 'callback' => [self::class, 'deleteFilter'], 'permission_callback' => [\ShopManagerPro\Shared\CapabilityService::class, 'requireEditCapability']], 'schema' => fn () => []]);
	}

	public static function getFilters(\WP_REST_Request $request) {
		$filters = FilterRepository::getFilters();
		$filters = array_map(fn ($filter) => $filter->toJson(), $filters);

		return rest_ensure_response($filters);
	}

	private static function validateFilterName(?string $name): ?\WP_Error {
		if (empty($name)) {
			return new \WP_Error('missing_name', 'Name is required', ['status' => 400]);
		} $length = strlen($name);
		if ($length > 60) {
			return new \WP_Error('invalid_name_length', 'Name must be between 1 and 60 characters', ['status' => 400]);
		}

return null;
	}

	public static function createFilter(\WP_REST_Request $request) {
		$filter = Filter::buildFromInput(json_decode($request->get_body()));
		$filterId = FilterRepository::createFilter($filter);

		return rest_ensure_response(['id' => $filterId]);
	}

	public static function renameFilter(\WP_REST_Request $request) {
		$params = $request->get_params();
		$id = intval($request['id']);
		$nameError = self::validateFilterName($params['name'] ?? null);
		if ($nameError) {
			return $nameError;
		} $filters = FilterRepository::getFilters();
		$found = array_find($filters, function ($filter) use ($id) { return $filter->getId() === $id; });
		if (!$found) {
			return new \WP_Error('invalid_id', 'Invalid filter ID', ['status' => 400]);
		} FilterRepository::renameFilter($id, $params['name']);

		return new \WP_REST_Response(null, 204);
	}

	public static function updateFilter(\WP_REST_Request $request) {
		$params = $request->get_params();
		$id = intval($request['id']);
		$filters = FilterRepository::getFilters();
		if (!isset($filters[$id])) {
			return new \WP_Error('invalid_id', 'Invalid filter ID', ['status' => 400]);
		} $oldFilter = $filters[$id];
		$conditions = [];
		if (!empty($params['conditions']) && is_array($params['conditions'])) {
			foreach ($params['conditions'] as $index => $conditionData) {
				$decoded = FieldNameEncoderService::decode($conditionData['field']);
				$field = new FilterConditionsItemField(type: FilterConditionsItemFieldType::from($decoded['type']->value), key: $decoded['field']);
				$conditions[] = new FilterConditionsItem(field: $field, operator: FilterConditionsItemOperator::from($conditionData['operator']), value: $conditionData['value'], not: (bool) $conditionData['not'], combinator: FilterConditionsItemCombinator::from($conditionData['combinator']), enabled: (bool) $conditionData['enabled']);
			}
		} $filter = new Filter(id: $id, name: $params['name'], conditions: $conditions);
		FilterRepository::updateFilter($filter);

		return new \WP_REST_Response(null, 204);
	}

	public static function deleteFilter(\WP_REST_Request $request) {
		$id = intval($request['id']);
		if ($id <= 0) {
			return new \WP_Error('invalid_id', 'Invalid filter ID', ['status' => 400]);
		} FilterRepository::deleteFilter($id);

		return new \WP_REST_Response(null, 204);
	}
}
