<?php

namespace Cookiez\Modules\Cookie\Rest;

use Cookiez\Classes\Rest\{
	Sanitizer,
	Validator,
};
use Cookiez\Classes\Enums\Cookie_Category;
use Cookiez\Classes\Utils;
use Cookiez\Modules\Cookie\Classes\{
	Enums\Cookie_Type,
	Route_Base,
};
use Cookiez\Modules\Cookie\Classes\Dto\Cookie_DTO;
use Cookiez\Modules\Cookie\Components\Cookie;

use RuntimeException;
use Throwable;
use WP_REST_Response;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class Create_Cookie
 * REST endpoint for creating manual cookies
 */
class Create_Cookie extends Route_Base {
	public string $path = '';

	public function get_methods(): array {
		return [ 'POST' ];
	}

	public function get_name(): string {
		return 'create-cookie';
	}

	protected function sanitize_fields(): array {
		return [
			'name' => Sanitizer::text(),
			'domain' => Sanitizer::text(),
			'duration' => Sanitizer::int(),
			'category' => Sanitizer::text(),
			'description' => Sanitizer::textarea(),
		];
	}

	protected function validate_fields(): array {
		return [
			'name' => ( new Validator() )
				->fn(
					fn( $value ) => Utils::is_valid_cookie_name( $value ),
					[ 'message' => esc_html__( 'Cookie name has invalid characters', 'cookiez' ) ]
				),
			'domain' => ( new Validator() )
				->fn(
					fn( $value ) => Utils::is_valid_cookie_domain( $value ),
					[ 'message' => esc_html__( 'Expected a valid domain', 'cookiez' ) ]
				)
				->nullable(),
			'duration' => ( new Validator() )
				->number( [
					'min' => 1,
					'message' => esc_html__( 'Expected a positive number', 'cookiez' ),
				] )
				->nullable(),
			'category' => ( new Validator() )
				->enum(
					Cookie_Category::class,
					[ 'message' => esc_html__( 'Expected a valid category value', 'cookiez' ) ]
				),
			'description' => ( new Validator() )
				->string( [
					'message' => esc_html__( 'Expected a string', 'cookiez' ),
				] )
				->nullable(),
		];
	}

	public function POST(): WP_REST_Response {
		try {
			$error = $this->verify_capability();

			if ( $error ) {
				return $error;
			}

			$validation_errors = $this->validate( $this->params );

			if ( ! empty( $validation_errors ) ) {
				return $this->respond_validation_error( $validation_errors );
			}

			$dto = Cookie_DTO::from_rest_api( $this->params );
			$dto->type = Cookie_Type::MANUAL;

			try {
				$created = ( new Cookie() )->create( $dto );
			} catch ( RuntimeException $e ) {
				if ( 'cookie_duplicate' === $e->getMessage() ) {
					return $this->respond_error_json( [
						'message' => esc_html__( 'Cookie with this name and domain already exists', 'cookiez' ),
						'code' => 'bad_request',
					], 409 );
				}

				throw $e;
			}

			return $this->respond_success_json( [
				'message' => esc_html__( 'Cookie created successfully', 'cookiez' ),
				'cookie_id' => $created->id,
			], 201 );
		} catch ( Throwable $t ) {
			return $this->respond_error_json( [
				'message' => $t->getMessage(),
				'code' => 'internal_server_error',
			], 500 );
		}
	}
}
