<?php
declare(strict_types=1);

namespace Wohno\Plugin\Ajax;

use Wohno\Plugin\Render\ListingsRenderer;
use Wohno\Plugin\Shortcode\ListingsShortcode;

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

/**
 * `admin-ajax` endpoint that renders a live preview for the settings-page
 * shortcode generator.
 *
 * Admin-only (`manage_options`) + nonce-protected. Renders through the same
 * {@see ListingsShortcode} path as the real shortcode, so layout, columns,
 * search and "load more" all behave exactly like on the front end. When there
 * are no real listings yet (no key / no results), it falls back to a faithful
 * mock built from the SAME renderer + card template, so the generator always
 * shows a realistic preview.
 */
final class Preview {

	public const ACTION = 'wohno_preview';
	public const NONCE  = 'wohno_preview';

	/** Attributes the generator may pass through to the shortcode. */
	private const ALLOWED = array(
		'city',
		'zip',
		'q',
		'property_type',
		'rooms_min',
		'rooms_max',
		'rent_max',
		'wbs_only',
		'limit',
		'columns',
		'layout',
		'search',
		'load_more',
	);

	/**
	 * Constructor.
	 *
	 * @param ListingsShortcode $shortcode The listings shortcode renderer.
	 * @param ListingsRenderer  $renderer  The HTML renderer (mock fallback).
	 */
	public function __construct(
		private readonly ListingsShortcode $shortcode,
		private readonly ListingsRenderer $renderer
	) {
	}

	/**
	 * Register the (logged-in only) AJAX handler.
	 *
	 * @return void
	 */
	public function register(): void {
		add_action( 'wp_ajax_' . self::ACTION, array( $this, 'handle' ) );
	}

	/**
	 * Render the preview and emit a JSON response.
	 *
	 * @return void
	 */
	public function handle(): void {
		if ( ! check_ajax_referer( self::NONCE, 'nonce', false ) ) {
			wp_send_json_error( array( 'message' => __( 'Sicherheitsprüfung fehlgeschlagen.', 'wohno' ) ), 403 );
		}
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'Keine Berechtigung.', 'wohno' ) ), 403 );
		}

		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- each value is sanitized via sanitize_text_field() in the ALLOWED-key loop below.
		$raw  = isset( $_POST['atts'] ) && is_array( $_POST['atts'] ) ? wp_unslash( $_POST['atts'] ) : array();
		$atts = array();
		foreach ( self::ALLOWED as $key ) {
			if ( isset( $raw[ $key ] ) ) {
				$atts[ $key ] = sanitize_text_field( (string) $raw[ $key ] );
			}
		}

		// Same render path as the public shortcode (errors surface to admins).
		$html = $this->shortcode->render( $atts );

		// No real listings rendered (missing key / no results) → faithful mock so
		// the preview is never empty.
		if ( false === strpos( $html, 'wohno-card' ) && false === strpos( $html, 'wohno-map' ) ) {
			$html = $this->mock_render( $atts );
		}

		wp_send_json_success( array( 'html' => $html ) );
	}

	/**
	 * Render a detail-accurate mock through the real renderer + card template.
	 *
	 * @param array<string, string> $atts Generator attributes.
	 * @return string
	 */
	private function mock_render( array $atts ): string {
		$layout = isset( $atts['layout'] ) ? strtolower( (string) $atts['layout'] ) : 'grid';
		$opts   = array(
			'columns'   => isset( $atts['columns'] ) ? (int) $atts['columns'] : 3,
			'layout'    => ListingsRenderer::sanitize_layout( $layout ),
			'load_more' => false,
		);

		$listings = $this->mock_listings();
		$body     = 'map' === $layout
			? $this->renderer->map( $listings, $opts )
			: $this->renderer->grid( $listings, $opts );

		$search_on = isset( $atts['search'] )
			&& ! in_array( strtolower( (string) $atts['search'] ), array( '', '0', 'false', 'no' ), true );
		$form      = $search_on
			? $this->renderer->search_form(
				$atts,
				array(
					'action'    => admin_url( 'admin.php' ),
					'preserved' => array(),
				)
			)
			: '';

		$note = '<p class="wohno-gen__demo-note">'
			. esc_html__( 'Beispieldaten — sobald dein API-Key Inserate liefert, erscheinen sie hier.', 'wohno' )
			. '</p>';

		return $note . $form . $body;
	}

	/**
	 * A small set of realistic sample listings (bundled SVG images), shaped like
	 * the public DTO so the card + modal render exactly as for real data.
	 *
	 * @return array<int, array<string, mixed>>
	 */
	private function mock_listings(): array {
		$img     = static fn ( string $file, string $alt ): array => array(
			'url' => WOHNO_PLUGIN_URL . 'assets/img/' . $file,
			'alt' => $alt,
		);
		$gallery = array(
			$img( 'demo-1.svg', __( 'Wohnzimmer', 'wohno' ) ),
			$img( 'demo-2.svg', __( 'Küche', 'wohno' ) ),
			$img( 'demo-3.svg', __( 'Schlafzimmer', 'wohno' ) ),
		);

		return array(
			array(
				'id'            => 'demo-1',
				'slug'          => null,
				'title'         => __( 'Helle 3-Zimmer-Wohnung mit Balkon', 'wohno' ),
				'description'   => __( 'Großzügig geschnittene Wohnung in ruhiger Lage: lichtdurchflutetes Wohnzimmer, moderne Einbauküche und ein sonniger Balkon. Nahverkehr, Einkaufsmöglichkeiten und Parks sind fußläufig erreichbar.', 'wohno' ),
				'street'        => __( 'Musterstraße', 'wohno' ),
				'houseNumber'   => '12',
				'zipCode'       => '50667',
				'city'          => __( 'Köln', 'wohno' ),
				'district'      => __( 'Altstadt', 'wohno' ),
				'latitude'      => 50.9384,
				'longitude'     => 6.9582,
				'isDiscrete'    => false,
				'rooms'         => 3,
				'bedrooms'      => 2,
				'bathrooms'     => 1,
				'livingArea'    => 78,
				'rentCold'      => 98000,
				'rentWarm'      => 120000,
				'propertyType'  => 'apartment',
				'offerType'     => 'rent',
				'availableFrom' => '2026-08-01',
				'images'        => $gallery,
			),
			array(
				'id'                   => 'demo-2',
				'slug'                 => null,
				'title'                => __( 'Gemütliches Studio im Zentrum', 'wohno' ),
				'description'          => __( 'Kompaktes, modern möbliertes Studio – ideal für Singles oder Pendler. Effiziente Raumaufteilung, hochwertige Ausstattung und eine top-zentrale Lage.', 'wohno' ),
				'street'               => __( 'Beispielweg', 'wohno' ),
				'houseNumber'          => '4',
				'zipCode'              => '10115',
				'city'                 => __( 'Berlin', 'wohno' ),
				'district'             => __( 'Mitte', 'wohno' ),
				'latitude'             => 52.5321,
				'longitude'            => 13.3849,
				'isDiscrete'           => false,
				'rooms'                => 1,
				'bedrooms'             => 1,
				'bathrooms'            => 1,
				'livingArea'           => 34,
				'rentCold'             => 72000,
				'rentWarm'             => 85000,
				'propertyType'         => 'studio',
				'offerType'            => 'rent',
				'availableImmediately' => true,
				'images'               => array( $gallery[1], $gallery[2] ),
			),
			array(
				'id'            => 'demo-3',
				'slug'          => null,
				'title'         => __( 'Familienfreundliches Reihenhaus mit Garten', 'wohno' ),
				'description'   => __( 'Charmantes Reihenhaus über zwei Etagen mit eigenem Garten, Stellplatz und ausgebautem Keller. Ruhige, grüne Nachbarschaft mit Schulen und Kitas in der Nähe.', 'wohno' ),
				'street'        => __( 'Gartenstraße', 'wohno' ),
				'houseNumber'   => '27',
				'zipCode'       => '52072',
				'city'          => __( 'Aachen', 'wohno' ),
				'district'      => __( 'Laurensberg', 'wohno' ),
				'latitude'      => 50.7892,
				'longitude'     => 6.0512,
				'isDiscrete'    => false,
				'rooms'         => 5,
				'bedrooms'      => 4,
				'bathrooms'     => 2,
				'livingArea'    => 138,
				'rentCold'      => 165000,
				'rentWarm'      => 198000,
				'propertyType'  => 'house',
				'offerType'     => 'rent',
				'availableFrom' => '2026-09-15',
				'images'        => $gallery,
			),
		);
	}
}
