<?php
/**
 * Notion REST Routes
 *
 * @package Sequensy\Integrations\Notion
 * @since 1.0.0
 */

declare(strict_types=1);

namespace Sequensy\Integrations\Notion\Rest;

use Sequensy\Integrations\Notion\NotionApi;
use Sequensy\Rest\AbstractIntegrationRoutes;
use Sequensy\Rest\IntegrationRouteDescriptor;
use WP_REST_Request;
use WP_REST_Response;
use WP_Error;

// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
	die;
}

/**
 * Class NotionRoutes
 *
 * Registers Notion integration REST routes.
 */
class NotionRoutes extends AbstractIntegrationRoutes {

	/**
	 * Configure the integration route descriptor.
	 *
	 * @return IntegrationRouteDescriptor
	 */
	protected function configure(): IntegrationRouteDescriptor {
		return new IntegrationRouteDescriptor(
			slug: 'notion',
			display_name: __( 'Notion', 'sequensy' ),
			credential_fields: array(
				'api_key' => array(
					'required' => true,
					'type'     => 'string',
				),
			),
		);
	}

	/**
	 * Create a Notion API instance with the given credentials.
	 *
	 * @param array $credentials Credential values with 'api_key'.
	 * @return NotionApi API client instance.
	 */
	protected function create_api( array $credentials ): object {
		return new NotionApi( $credentials['api_key'] );
	}

	/**
	 * Register integration-specific sub-routes.
	 *
	 * @return void
	 */
	protected function register_sub_routes(): void {
		$this->register_connection_get_route( 'databases', array( $this, 'get_databases' ) );
		$this->register_connection_get_route(
			'databases/(?P<database_id>[a-zA-Z0-9-]+)',
			array( $this, 'get_database_schema' )
		);
		$this->register_connection_get_route( 'pages', array( $this, 'get_pages' ) );
	}

	/**
	 * Get available databases for a connection.
	 *
	 * @param WP_REST_Request $request Full data about the request.
	 * @return WP_REST_Response|WP_Error Response object or error.
	 */
	public function get_databases( WP_REST_Request $request ): WP_REST_Response|WP_Error {
		$connection_id = $request->get_param( 'connection_id' );

		return $this->api_call_with_connection(
			$connection_id,
			function ( NotionApi $api ) {
				$result = $api->list_databases();

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

				$databases = $result['data']['results'] ?? array();

				return array_map(
					function ( array $db ) {
						$title = '';
						if ( ! empty( $db['title'] ) ) {
							$title = implode(
								'',
								array_map(
									fn( array $t ) => $t['plain_text'] ?? '',
									$db['title']
								)
							);
						}

						return array(
							'id'    => $db['id'],
							'title' => $title,
						);
					},
					$databases
				);
			}
		);
	}

	/**
	 * Get available pages for a connection.
	 *
	 * @param WP_REST_Request $request Full data about the request.
	 * @return WP_REST_Response|WP_Error Response object or error.
	 */
	public function get_pages( WP_REST_Request $request ): WP_REST_Response|WP_Error {
		$connection_id = $request->get_param( 'connection_id' );

		return $this->api_call_with_connection(
			$connection_id,
			function ( NotionApi $api ) {
				$result = $api->search_pages();

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

				$pages = $result['data']['results'] ?? array();

				return array_map(
					function ( array $page ) {
						$title = '';
						if ( ! empty( $page['properties'] ) ) {
							foreach ( $page['properties'] as $prop ) {
								if ( isset( $prop['type'] ) && 'title' === $prop['type'] && ! empty( $prop['title'] ) ) {
									$title = implode(
										'',
										array_map(
											fn( array $t ) => $t['plain_text'] ?? '',
											$prop['title']
										)
									);
									break;
								}
							}
						}

						return array(
							'id'    => $page['id'],
							'title' => $title ? $title : __( 'Untitled', 'sequensy' ),
						);
					},
					$pages
				);
			}
		);
	}

	/**
	 * Get database schema (properties) for a specific database.
	 *
	 * @param WP_REST_Request $request Full data about the request.
	 * @return WP_REST_Response|WP_Error Response object or error.
	 */
	public function get_database_schema( WP_REST_Request $request ): WP_REST_Response|WP_Error {
		$connection_id = $request->get_param( 'connection_id' );
		$database_id   = $request->get_param( 'database_id' );

		return $this->api_call_with_connection(
			$connection_id,
			function ( NotionApi $api ) use ( $database_id ) {
				$result = $api->get_database( $database_id );

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

				$properties = $result['data']['properties'] ?? array();

				// Filter out the title property — actions have a dedicated title field.
				$properties = array_filter(
					$properties,
					fn( array $prop ) => ( $prop['type'] ?? '' ) !== 'title'
				);

				return array_map(
					function ( array $prop, string $name ) {
						return array(
							'name' => $name,
							'type' => $prop['type'] ?? 'unknown',
						);
					},
					$properties,
					array_keys( $properties )
				);
			}
		);
	}
}
