<?php
/**
 * @package Hafenstudios\Leadlotse
 */

namespace Hafenstudios\Leadlotse\Rest;

use Hafenstudios\Leadlotse\Forms\DefinitionSchema;
use Hafenstudios\Leadlotse\Forms\FormPostType;
use Hafenstudios\Leadlotse\Support\ProFeatures;

defined( 'ABSPATH' ) || exit;

/**
 * REST: Formulare CRUD (`leadlotse/v1/forms`), Capability `hs_manage_forms` (D8).
 * Auch die Admin-UI (Etappe 3) nutzt ausschliesslich diese Endpunkte.
 *
 * Hier sitzt der verbindliche Pro-Gate des Plugins (L-P1): jede Definition
 * laeuft durch ProFeatures::check_definition() - der Builder graut die
 * gesperrten Flaechen nur zusaetzlich aus.
 */
final class FormsController {

	public const REST_NAMESPACE = 'leadlotse/v1';

	private DefinitionSchema $schema;

	/**
	 * @param DefinitionSchema $schema Definitions-Schema.
	 */
	public function __construct( DefinitionSchema $schema ) {
		$this->schema = $schema;
	}

	/**
	 * Registriert die Routen.
	 *
	 * @return void
	 */
	public function register_routes(): void {
		register_rest_route(
			self::REST_NAMESPACE,
			'/forms',
			array(
				array(
					'methods'             => \WP_REST_Server::READABLE,
					'callback'            => array( $this, 'list_forms' ),
					'permission_callback' => array( $this, 'can_manage' ),
					'args'                => array(
						'page'     => array(
							'type'    => 'integer',
							'default' => 1,
							'minimum' => 1,
						),
						'per_page' => array(
							'type'    => 'integer',
							'default' => 20,
							'minimum' => 1,
							'maximum' => 100,
						),
						'search'   => array(
							'type'              => 'string',
							'default'           => '',
							'sanitize_callback' => 'sanitize_text_field',
						),
					),
				),
				array(
					'methods'             => \WP_REST_Server::CREATABLE,
					'callback'            => array( $this, 'create_form' ),
					'permission_callback' => array( $this, 'can_manage' ),
				),
			)
		);

		register_rest_route(
			self::REST_NAMESPACE,
			'/forms/(?P<id>\d+)',
			array(
				array(
					'methods'             => \WP_REST_Server::READABLE,
					'callback'            => array( $this, 'get_form' ),
					'permission_callback' => array( $this, 'can_manage' ),
				),
				array(
					'methods'             => \WP_REST_Server::EDITABLE,
					'callback'            => array( $this, 'update_form' ),
					'permission_callback' => array( $this, 'can_manage' ),
				),
				array(
					'methods'             => \WP_REST_Server::DELETABLE,
					'callback'            => array( $this, 'delete_form' ),
					'permission_callback' => array( $this, 'can_manage' ),
				),
			)
		);
	}

	/**
	 * Capability-Check.
	 *
	 * @return bool|\WP_Error
	 */
	public function can_manage() {
		if ( current_user_can( 'hs_manage_forms' ) ) {
			return true;
		}
		return new \WP_Error(
			'leadlotse_forbidden',
			__( 'Sie haben keine Berechtigung, Formulare zu verwalten. Bitte wenden Sie sich an eine Administratorin oder einen Administrator.', 'leadlotse' ),
			array( 'status' => rest_authorization_required_code() )
		);
	}

	/**
	 * GET /forms - Liste mit Pagination und Suche.
	 *
	 * @param \WP_REST_Request $request Request.
	 * @return \WP_REST_Response
	 */
	public function list_forms( \WP_REST_Request $request ): \WP_REST_Response {
		$page     = max( 1, (int) $request->get_param( 'page' ) );
		$per_page = min( 100, max( 1, (int) $request->get_param( 'per_page' ) ) );

		$query = new \WP_Query(
			array(
				'post_type'      => FormPostType::POST_TYPE,
				'post_status'    => array( 'publish', 'draft' ),
				'posts_per_page' => $per_page,
				'paged'          => $page,
				's'              => (string) $request->get_param( 'search' ),
				'orderby'        => 'date',
				'order'          => 'DESC',
			)
		);

		$items = array();
		foreach ( $query->posts as $post ) {
			$items[] = $this->prepare_form( $post );
		}

		$response = new \WP_REST_Response( $items, 200 );
		$response->header( 'X-WP-Total', (string) $query->found_posts );
		$response->header( 'X-WP-TotalPages', (string) $query->max_num_pages );
		return $response;
	}

	/**
	 * POST /forms - Formular anlegen.
	 *
	 * @param \WP_REST_Request $request Request.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public function create_form( \WP_REST_Request $request ) {
		$title = sanitize_text_field( (string) $request->get_param( 'title' ) );
		if ( '' === $title ) {
			$title = __( 'Neues Formular', 'leadlotse' );
		}

		$definition = $this->schema->sanitize( $request->get_param( 'definition' ) ?? array() );
		if ( is_wp_error( $definition ) ) {
			return $definition;
		}

		// Pro-Gate: ein neues Formular darf keine Pro-Funktion einschalten (L-P1).
		$blocked = ProFeatures::check_definition( $definition, null );
		if ( null !== $blocked ) {
			return $blocked;
		}

		$status  = 'publish' === (string) $request->get_param( 'status' ) ? 'publish' : 'draft';
		$form_id = wp_insert_post(
			array(
				'post_type'   => FormPostType::POST_TYPE,
				'post_title'  => $title,
				'post_status' => $status,
			),
			true
		);

		if ( is_wp_error( $form_id ) ) {
			return $form_id;
		}

		FormPostType::save_definition( (int) $form_id, $definition );

		return new \WP_REST_Response( $this->prepare_form( get_post( $form_id ) ), 201 );
	}

	/**
	 * GET /forms/{id}.
	 *
	 * @param \WP_REST_Request $request Request.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public function get_form( \WP_REST_Request $request ) {
		$post = $this->find_form( (int) $request->get_param( 'id' ) );
		if ( is_wp_error( $post ) ) {
			return $post;
		}
		return new \WP_REST_Response( $this->prepare_form( $post ), 200 );
	}

	/**
	 * PUT/PATCH /forms/{id}.
	 *
	 * @param \WP_REST_Request $request Request.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public function update_form( \WP_REST_Request $request ) {
		$post = $this->find_form( (int) $request->get_param( 'id' ) );
		if ( is_wp_error( $post ) ) {
			return $post;
		}

		// Definition zuerst pruefen: ein abgewiesener Speicherversuch darf auch
		// Titel und Status nicht halb veraendern.
		$definition     = null;
		$raw_definition = $request->get_param( 'definition' );
		if ( null !== $raw_definition ) {
			$definition = $this->schema->sanitize( $raw_definition );
			if ( is_wp_error( $definition ) ) {
				return $definition;
			}

			// Pro-Gate (L-P1): Bestandsschutz - was dieses Formular bereits
			// nutzt, bleibt speicherbar; NEU einschalten braucht eine Lizenz.
			$blocked = ProFeatures::check_definition( $definition, FormPostType::get_definition( $post->ID ) );
			if ( null !== $blocked ) {
				return $blocked;
			}
		}

		$update = array( 'ID' => $post->ID );

		$title = $request->get_param( 'title' );
		if ( null !== $title ) {
			$update['post_title'] = sanitize_text_field( (string) $title );
		}
		$status = (string) $request->get_param( 'status' );
		if ( in_array( $status, array( 'publish', 'draft' ), true ) ) {
			$update['post_status'] = $status;
		}

		$result = wp_update_post( $update, true );
		if ( is_wp_error( $result ) ) {
			return $result;
		}

		if ( null !== $definition ) {
			FormPostType::save_definition( $post->ID, $definition );
		}

		return new \WP_REST_Response( $this->prepare_form( get_post( $post->ID ) ), 200 );
	}

	/**
	 * DELETE /forms/{id} - in den Papierkorb.
	 *
	 * @param \WP_REST_Request $request Request.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public function delete_form( \WP_REST_Request $request ) {
		$post = $this->find_form( (int) $request->get_param( 'id' ) );
		if ( is_wp_error( $post ) ) {
			return $post;
		}

		$deleted = wp_trash_post( $post->ID );
		if ( ! $deleted ) {
			return new \WP_Error(
				'leadlotse_delete_failed',
				__( 'Das Formular konnte nicht geloescht werden. Bitte versuchen Sie es erneut.', 'leadlotse' ),
				array( 'status' => 500 )
			);
		}

		return new \WP_REST_Response( array( 'deleted' => true ), 200 );
	}

	/**
	 * Findet ein Formular oder liefert einen 404-Fehler.
	 *
	 * @param int $form_id Formular-ID.
	 * @return \WP_Post|\WP_Error
	 */
	private function find_form( int $form_id ) {
		$post = get_post( $form_id );
		if ( ! $post || FormPostType::POST_TYPE !== $post->post_type || 'trash' === $post->post_status ) {
			return new \WP_Error(
				'leadlotse_form_not_found',
				__( 'Das Formular wurde nicht gefunden. Bitte aktualisieren Sie die Formularliste.', 'leadlotse' ),
				array( 'status' => 404 )
			);
		}
		return $post;
	}

	/**
	 * Antwortformat eines Formulars.
	 *
	 * @param \WP_Post $post Formular-Post.
	 * @return array<string, mixed>
	 */
	private function prepare_form( \WP_Post $post ): array {
		return array(
			'id'         => $post->ID,
			'title'      => $post->post_title,
			'status'     => $post->post_status,
			'definition' => FormPostType::get_definition( $post->ID ),
			'created_at' => $post->post_date_gmt,
			'updated_at' => $post->post_modified_gmt,
		);
	}
}
