<?php
/**
 * Newsletter form builder + shortcode renderer with anti-bot honeypot and rate limit.
 *
 * @package SuiteMkt3k
 */

namespace SuiteMkt3k\Modules\Newsletter;

use SuiteMkt3k\Frontend\Frontend;
use SuiteMkt3k\Installer;
use SuiteMkt3k\Modules\Subscribers\Subscriber_Manager;
use SuiteMkt3k\Security\Capabilities;
use SuiteMkt3k\Security\Nonces;
use SuiteMkt3k\Security\Rate_Limiter;
use SuiteMkt3k\Utils\Sanitizer;

defined( 'ABSPATH' ) || exit;
// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching

final class Newsletter_Form {

	public static function register(): void {
		add_shortcode( 'suitemkt3k_newsletter_form', array( __CLASS__, 'render_shortcode' ) );
		add_action( 'rest_api_init', array( __CLASS__, 'register_routes' ) );
		add_action( 'admin_post_suitemkt3k_form_save', array( __CLASS__, 'handle_save' ) );
		add_action( 'wp_enqueue_scripts', array( __CLASS__, 'maybe_enqueue_assets' ) );
	}

	/**
	 * Preload assets when the shortcode is in post content (widgets/footer call render_shortcode).
	 */
	public static function maybe_enqueue_assets(): void {
		if ( is_admin() ) {
			return;
		}
		global $post;
		if ( $post instanceof \WP_Post && has_shortcode( $post->post_content, 'suitemkt3k_newsletter_form' ) ) {
			Frontend::enqueue_public_assets();
		}
	}

	public static function table(): string {
		return Installer::table( 'newsletter_forms' );
	}

	public static function default_design(): array {
		return array(
			'title'          => __( 'Subscribe to our newsletter', 'suitemkt3k' ),
			'description'    => __( 'Get our best offers in your inbox.', 'suitemkt3k' ),
			'fields'         => array(
				array( 'key' => 'name',  'label' => __( 'Name', 'suitemkt3k' ), 'required' => false ),
				array( 'key' => 'email', 'label' => __( 'Email', 'suitemkt3k' ), 'required' => true ),
			),
			'cta_label'      => __( 'Subscribe', 'suitemkt3k' ),
			'cta_text_color' => '#FFFFFF',
			'success_text'   => __( 'Thanks! You are subscribed.', 'suitemkt3k' ),
			'accent'         => '#2AB2E5',
			'text_color'     => '#0F172A',
			'bg_color'       => '#FFFFFF',
			'border_color'   => '#E2E8F0',
			'consent_text'   => __( 'I agree to receive marketing emails and accept the privacy policy.', 'suitemkt3k' ),
			'field_radius'   => 8,
			'button_radius'  => 10,
			'show_labels'    => true,
			'label_name'     => __( 'Name', 'suitemkt3k' ),
			'label_email'    => __( 'Email', 'suitemkt3k' ),
			'label_phone'    => __( 'Phone', 'suitemkt3k' ),
			'label_birth'    => __( 'Birth date', 'suitemkt3k' ),
		);
	}

	/**
	 * Build the fields list from show_* flags and custom labels posted by the builder.
	 */
	public static function fields_from_flags( array $flags, array $labels = array() ): array {
		$fields = array(
			array( 'key' => 'email', 'label' => $labels['email'] ?? __( 'Email', 'suitemkt3k' ), 'required' => true ),
		);
		if ( ! empty( $flags['show_name'] ) ) {
			array_unshift( $fields, array( 'key' => 'name', 'label' => $labels['name'] ?? __( 'Name', 'suitemkt3k' ), 'required' => false ) );
		}
		if ( ! empty( $flags['show_phone'] ) ) {
			$fields[] = array( 'key' => 'phone', 'label' => $labels['phone'] ?? __( 'Phone', 'suitemkt3k' ), 'required' => false );
		}
		if ( ! empty( $flags['show_birth'] ) ) {
			$fields[] = array( 'key' => 'birth_date', 'label' => $labels['birth'] ?? __( 'Birth date', 'suitemkt3k' ), 'required' => false );
		}
		return $fields;
	}

	public static function get( int $id ): ?array {
		global $wpdb;
		$row = $wpdb->get_row( $wpdb->prepare( 'SELECT * FROM %i WHERE id = %d', self::table(), $id ), ARRAY_A );
		if ( ! $row ) {
			return null;
		}
		$design = self::default_design();
		$decoded = json_decode( (string) $row['design_json'], true );
		if ( is_array( $decoded ) ) {
			$design = array_replace_recursive( $design, $decoded );
		}
		$row['design'] = $design;
		unset( $row['design_json'] );
		return $row;
	}

	public static function list(): array {
		global $wpdb;
		$rows = $wpdb->get_results( $wpdb->prepare( 'SELECT id,name,created_at FROM %i ORDER BY id DESC', self::table() ), ARRAY_A );
		return is_array( $rows ) ? $rows : array();
	}

	public static function save( array $data, int $id = 0 ): int {
		global $wpdb;
		$raw = isset( $data['design'] ) && is_array( $data['design'] ) ? $data['design'] : array();
		$flags = array(
			'show_name'  => ! empty( $raw['show_name'] ),
			'show_phone' => ! empty( $raw['show_phone'] ),
			'show_birth' => ! empty( $raw['show_birth'] ),
		);
		$labels = array(
			'name'  => Sanitizer::text( $raw['label_name']  ?? '', 80 ),
			'email' => Sanitizer::text( $raw['label_email'] ?? '', 80 ),
			'phone' => Sanitizer::text( $raw['label_phone'] ?? '', 80 ),
			'birth' => Sanitizer::text( $raw['label_birth'] ?? '', 80 ),
		);
		// Cast numeric/bool fields.
		$raw['field_radius']  = isset( $raw['field_radius'] )  ? max( 0, min( 40, (int) $raw['field_radius'] ) )  : 8;
		$raw['button_radius'] = isset( $raw['button_radius'] ) ? max( 0, min( 40, (int) $raw['button_radius'] ) ) : 10;
		$raw['show_labels']   = ! empty( $raw['show_labels'] );
		unset( $raw['show_name'], $raw['show_phone'], $raw['show_birth'] );
		$raw['fields'] = self::fields_from_flags( $flags, $labels );
		$design = array_replace_recursive( self::default_design(), Sanitizer::recursive_text( $raw ) );

		$payload = array(
			'name'        => Sanitizer::text( $data['name'] ?? '', 190 ),
			'design_json' => wp_json_encode( $design ),
		);
		if ( $id > 0 ) {
			$wpdb->update( self::table(), $payload, array( 'id' => $id ) );
			return $id;
		}
		$wpdb->insert( self::table(), $payload );
		return (int) $wpdb->insert_id;
	}

	public static function handle_save(): void {
		Capabilities::ensure( Capabilities::EDIT_CAMPAIGN );
		check_admin_referer( Nonces::ADMIN_ACTION, '_wpnonce' );
		$id   = max( 0, (int) \SuiteMkt3k\Utils\Sanitizer::post( 'id', 'int' ) );
		$name = \SuiteMkt3k\Utils\Sanitizer::text( \SuiteMkt3k\Utils\Sanitizer::post( 'name', 'text' ), 190 );
		$design = \SuiteMkt3k\Utils\Sanitizer::post_array( 'design' );
		$id = self::save( array( 'name' => $name, 'design' => $design ), $id );
		wp_safe_redirect( add_query_arg( array( 'view' => 'forms', 'form' => 'edit', 'form_id' => $id, 'updated' => '1' ), admin_url( 'admin.php?page=suitemkt3k-newsletter' ) ) );
		exit;
	}

	public static function register_routes(): void {
		register_rest_route(
			SUITEMKT3K_REST_NAMESPACE,
			'/public/subscribe',
			array(
				'methods'             => 'POST',
				'permission_callback' => '__return_true',
				'callback'            => array( __CLASS__, 'handle_submit' ),
			)
		);
	}

	public static function handle_submit( \WP_REST_Request $request ) {
		$identifier = hash( 'sha256', Rate_Limiter::visitor_id() . '|subscribe' );
		if ( ! Rate_Limiter::check( 'subscribe', $identifier, 6, 60 ) ) {
			return new \WP_REST_Response( array( 'ok' => false, 'message' => __( 'Too many attempts. Please try again later.', 'suitemkt3k' ) ), 429 );
		}
		$honey = (string) $request->get_param( 'website' );
		if ( '' !== $honey ) {
			return new \WP_REST_Response( array( 'ok' => true ), 200 );
		}
		$nonce = (string) $request->get_param( '_wpnonce' );
		if ( ! wp_verify_nonce( $nonce, 'wp_rest' ) ) {
			return new \WP_REST_Response( array( 'ok' => false, 'message' => __( 'Security check failed.', 'suitemkt3k' ) ), 403 );
		}

		$email = Sanitizer::email( $request->get_param( 'email' ) ?? '' );
		if ( '' === $email ) {
			return new \WP_REST_Response( array( 'ok' => false, 'message' => __( 'A valid email is required.', 'suitemkt3k' ) ), 400 );
		}
		$consent = filter_var( $request->get_param( 'consent' ), FILTER_VALIDATE_BOOLEAN );
		if ( ! $consent ) {
			return new \WP_REST_Response( array( 'ok' => false, 'message' => __( 'Please accept the privacy policy.', 'suitemkt3k' ) ), 400 );
		}

		Subscriber_Manager::upsert(
			array(
				'name'                 => $request->get_param( 'name' ) ?? '',
				'email'                => $email,
				'birth_date'           => $request->get_param( 'birth_date' ) ?? '',
				'source_type'          => 'newsletter_form',
				'source_campaign_id'   => (int) ( $request->get_param( 'form_id' ) ?? 0 ),
				'source_campaign_name' => (string) ( $request->get_param( 'form_name' ) ?? '' ),
				'ip'                   => \SuiteMkt3k\Utils\Sanitizer::server( 'REMOTE_ADDR', 'text' ),
				'locale'               => get_locale(),
			)
		);

		return new \WP_REST_Response( array( 'ok' => true, 'message' => __( 'Thanks! You are subscribed.', 'suitemkt3k' ) ), 200 );
	}

	public static function render_shortcode( $atts ): string {
		$atts = shortcode_atts( array( 'id' => 0 ), $atts, 'suitemkt3k_newsletter_form' );
		$form = self::get( (int) $atts['id'] );
		if ( ! $form ) {
			return '';
		}
		Frontend::enqueue_public_assets();
		$d              = $form['design'];
		$show_labels    = ! empty( $d['show_labels'] );
		$field_radius   = (int) ( $d['field_radius']  ?? 8 );
		$button_radius  = (int) ( $d['button_radius'] ?? 10 );
		ob_start();
		?>
		<form class="wmk-form" method="post" action="#" data-form-id="<?php echo esc_attr( (string) $form['id'] ); ?>" novalidate
			style="--wmk-accent: <?php echo esc_attr( $d['accent'] ); ?>; --wmk-text: <?php echo esc_attr( $d['text_color'] ); ?>; --wmk-bg: <?php echo esc_attr( $d['bg_color'] ); ?>; --wmk-border: <?php echo esc_attr( $d['border_color'] ); ?>; --wmk-cta-text: <?php echo esc_attr( $d['cta_text_color'] ?? '#FFFFFF' ); ?>; --wmk-field-radius: <?php echo (int) $field_radius; ?>px; --wmk-form-radius: <?php echo (int) $button_radius; ?>px;">
			<input type="hidden" name="_wpnonce" value="<?php echo esc_attr( wp_create_nonce( 'wp_rest' ) ); ?>">
			<input type="hidden" name="form_id" value="<?php echo esc_attr( (string) $form['id'] ); ?>">
			<input type="hidden" name="form_name" value="<?php echo esc_attr( (string) $form['name'] ); ?>">
			<input type="text" name="website" value="" tabindex="-1" autocomplete="off" style="position:absolute;left:-9999px;">
			<?php if ( $d['title'] ) : ?>
				<h3 class="wmk-form-title"><?php echo esc_html( $d['title'] ); ?></h3>
			<?php endif; ?>
			<?php if ( $d['description'] ) : ?>
				<p class="wmk-form-desc"><?php echo esc_html( $d['description'] ); ?></p>
			<?php endif; ?>
			<?php foreach ( (array) $d['fields'] as $field ) : ?>
				<label class="wmk-form-field">
					<?php if ( $show_labels ) : ?>
						<span><?php echo esc_html( (string) $field['label'] ); ?><?php echo ! empty( $field['required'] ) ? ' *' : ''; ?></span>
					<?php endif; ?>
					<input
						type="<?php echo 'email' === $field['key'] ? 'email' : ( 'birth_date' === $field['key'] ? 'date' : ( 'phone' === $field['key'] ? 'tel' : 'text' ) ); ?>"
						name="<?php echo esc_attr( (string) $field['key'] ); ?>"
						placeholder="<?php echo esc_attr( (string) $field['label'] . ( ! empty( $field['required'] ) ? ' *' : '' ) ); ?>"
						style="border-radius: <?php echo (int) $field_radius; ?>px;"
						<?php echo ! empty( $field['required'] ) ? 'required' : ''; ?>>
				</label>
			<?php endforeach; ?>
			<label class="wmk-form-consent">
				<input type="checkbox" name="consent" required>
				<span><?php echo esc_html( (string) $d['consent_text'] ); ?></span>
			</label>
			<button type="submit" class="wmk-form-cta" style="border-radius: <?php echo (int) $button_radius; ?>px;"><?php echo esc_html( (string) $d['cta_label'] ); ?></button>
			<div class="wmk-form-message" hidden></div>
		</form>
		<?php
		return (string) ob_get_clean();
	}
}
