<?php
declare(strict_types=1);

namespace Wohno\Plugin\Shortcode;

use Wohno\Plugin\Api\Client;
use Wohno\Plugin\Api\ListingQuery;
use Wohno\Plugin\Render\ListingsRenderer;

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

/**
 * `[wohno_listings city="Köln" rooms_min="2" limit="9" columns="3"]`
 *
 * Server-side fetch + native render. Filter attributes map 1:1 to the API
 * query params; layout attributes (columns, show_discrete) drive the render.
 */
final class ListingsShortcode {

	/**
	 * Constructor.
	 *
	 * @param Client           $client   API client.
	 * @param ListingsRenderer $renderer HTML renderer.
	 */
	public function __construct(
		private readonly Client $client,
		private readonly ListingsRenderer $renderer
	) {
	}

	/**
	 * Register the `[wohno_listings]` shortcode.
	 *
	 * @return void
	 */
	public function register(): void {
		add_shortcode( 'wohno_listings', array( $this, 'render' ) );
	}

	/**
	 * Render the shortcode output.
	 *
	 * @param array<string, mixed>|string $atts Shortcode attributes.
	 * @return string Escaped HTML.
	 */
	public function render( $atts ): string {
		// Site-wide defaults from the settings page; a shortcode attribute always
		// wins over them. `map` is a valid default here (handled below), so we do
		// not run it through sanitize_layout (which is grid/cards/list only).
		$saved_layout    = strtolower( (string) get_option( 'wohno_default_layout', 'grid' ) );
		$default_layout  = in_array( $saved_layout, array( 'grid', 'cards', 'list', 'map' ), true ) ? $saved_layout : 'grid';
		$default_columns = min( 4, max( 1, (int) get_option( 'wohno_default_columns', 3 ) ) );

		$atts = shortcode_atts(
			array(
				'city'          => '',
				'zip'           => '',
				'rooms_min'     => '',
				'rooms_max'     => '',
				'rent_max'      => '',
				'property_type' => '',
				'wbs_only'      => '',
				'q'             => '',
				'limit'         => 9,
				'columns'       => $default_columns,
				'show_discrete' => '',
				'load_more'     => '1',
				'layout'        => $default_layout,
				'search'        => '',
			),
			is_array( $atts ) ? $atts : array(),
			'wohno_listings'
		);

		$search_on = ! in_array( strtolower( (string) $atts['search'] ), array( '', '0', 'false', 'no' ), true );

		// Keep the author-defined (static) attributes separate from the visitor's
		// submitted selection: only the static view may seed the prewarm registry.
		$base_atts = $atts;

		// With the filter bar on, the visitor's submitted selection fully
		// overrides the shortcode defaults (empty field = cleared).
		if ( $search_on ) {
			$atts = array_merge( $atts, ListingQuery::request_values() );
		}

		$params = ListingQuery::from_atts( $atts );
		// Visitor-driven ($_GET) queries must not poison the prewarm registry;
		// seed it from the author's static view instead (see prewarm_register).
		$result = $this->client->listings( $params, ! $search_on );
		if ( $search_on ) {
			$this->client->prewarm_register( ListingQuery::from_atts( $base_atts ) );
		}
		if ( is_wp_error( $result ) ) {
			// Public-safe: never leak the key or internals to visitors.
			if ( current_user_can( 'edit_posts' ) ) {
				return '<p class="wohno-error">' . esc_html( $result->get_error_message() ) . '</p>';
			}

			return '';
		}

		$opts = array(
			'columns'       => (int) $atts['columns'],
			'show_discrete' => ! empty( $atts['show_discrete'] ),
			'layout'        => ListingsRenderer::sanitize_layout( $atts['layout'] ),
			'query'         => $params,
			'pagination'    => $result['pagination'],
			'load_more'     => ! in_array( strtolower( (string) $atts['load_more'] ), array( '0', 'false', 'no', '' ), true ),
		);

		$results = 'map' === strtolower( (string) $atts['layout'] )
			? $this->renderer->map( $result['listings'], $opts )
			: $this->renderer->grid( $result['listings'], $opts );

		if ( ! $search_on ) {
			return $results;
		}

		$action = get_permalink();
		$form   = $this->renderer->search_form(
			$atts,
			array(
				'action'    => is_string( $action ) ? $action : home_url( '/' ),
				'preserved' => ListingQuery::preserved_query(),
			)
		);

		return $form . $results;
	}
}
