<?php
/**
 * Lesending remote bridge (standalone script template)
 *
 * Install:
 * 1. Upload this file to the remote WordPress root (same folder as wp-config.php).
 *    You may rename it to any *.php name; use that URL in Lesending settings.
 * 2. Set LESENDING_BRIDGE_SECRET to a random string of at least 32 characters
 *    (same value as "Bridge secret" in Lesending settings).
 * 3. Set LESENDING_BRIDGE_USER_ID to a user ID that can publish posts (not 0).
 * 4. Optional: LESENDING_BRIDGE_ALLOWED_IPS as a comma-separated IP allowlist.
 *
 * Security: use HTTPS; strong secret; prefer IP allowlist on production.
 *
 * @package Lesending
 */

if ( ! defined( 'LESENDING_BRIDGE_SECRET' ) ) {
	define( 'LESENDING_BRIDGE_SECRET', 'REPLACE_ME_SET_LONG_RANDOM_SECRET' );
}
if ( ! defined( 'LESENDING_BRIDGE_USER_ID' ) ) {
	define( 'LESENDING_BRIDGE_USER_ID', 0 );
}
if ( ! defined( 'LESENDING_BRIDGE_ALLOWED_IPS' ) ) {
	define( 'LESENDING_BRIDGE_ALLOWED_IPS', '' );
}
if ( ! defined( 'LESENDING_BRIDGE_MAX_SIDELOAD' ) ) {
	define( 'LESENDING_BRIDGE_MAX_SIDELOAD', 30 );
}

header( 'Content-Type: application/json; charset=utf-8' );

/**
 * Fatal error handler: generic JSON only.
 */
function lesending_bridge_shutdown_json() {
	$lesending_err = error_get_last();
	if ( ! is_array( $lesending_err ) ) {
		return;
	}
	$lesending_fatal = array( E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR );
	if ( ! in_array( (int) $lesending_err['type'], $lesending_fatal, true ) ) {
		return;
	}
	if ( headers_sent() ) {
		return;
	}
	http_response_code( 500 );
	lesending_bridge_print_json(
		array(
			'ok'      => false,
			'message' => 'internal error',
		)
	);
}

register_shutdown_function( 'lesending_bridge_shutdown_json' );

/**
 * @param array<string,mixed> $lesending_data Data.
 * @return string
 */
function lesending_bridge_encode( $lesending_data ) {
	return (string) json_encode( $lesending_data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES );
}

/**
 * Output raw JSON for the API response.
 *
 * @param array<string,mixed> $lesending_data Data.
 */
function lesending_bridge_print_json( $lesending_data ) {
	// JSON API body must not be HTML-escaped.
	echo lesending_bridge_encode( $lesending_data ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}

/**
 * @return string
 */
/**
 * Polyfill sanitize helpers before WordPress loads.
 *
 * @param mixed $lesending_value Value.
 * @return string
 */
function lesending_bridge_unslash( $lesending_value ) {
	if ( function_exists( 'wp_unslash' ) ) {
		return (string) wp_unslash( $lesending_value );
	}
	return is_string( $lesending_value ) ? stripslashes( $lesending_value ) : (string) $lesending_value;
}

/**
 * @param mixed $lesending_value Value.
 * @return string
 */
function lesending_bridge_sanitize_text( $lesending_value ) {
	if ( function_exists( 'sanitize_text_field' ) ) {
		return sanitize_text_field( (string) $lesending_value );
	}
	return trim( strip_tags( (string) $lesending_value ) );
}

/**
 * @return string
 */
function lesending_bridge_read_secret_header() {
	if ( ! empty( $_SERVER['HTTP_X_LESENDING_SECRET'] ) ) {
		return lesending_bridge_sanitize_text( lesending_bridge_unslash( $_SERVER['HTTP_X_LESENDING_SECRET'] ) );
	}
	if ( function_exists( 'getallheaders' ) ) {
		$lesending_headers = getallheaders();
		if ( is_array( $lesending_headers ) ) {
			foreach ( $lesending_headers as $lesending_name => $lesending_value ) {
				if ( strtolower( (string) $lesending_name ) === 'x-lesending-secret' ) {
					return lesending_bridge_sanitize_text( (string) $lesending_value );
				}
			}
		}
	}
	return '';
}

/**
 * @return bool
 */
function lesending_bridge_secret_ok() {
	$lesending_key = lesending_bridge_read_secret_header();
	return $lesending_key !== '' && hash_equals( LESENDING_BRIDGE_SECRET, $lesending_key );
}

/**
 * @return bool
 */
function lesending_bridge_ip_allowed() {
	$lesending_list = trim( (string) LESENDING_BRIDGE_ALLOWED_IPS );
	if ( $lesending_list === '' ) {
		return true;
	}
	$lesending_remote = isset( $_SERVER['REMOTE_ADDR'] )
		? lesending_bridge_sanitize_text( lesending_bridge_unslash( $_SERVER['REMOTE_ADDR'] ) )
		: '';
	if ( $lesending_remote === '' ) {
		return false;
	}
	$lesending_allowed = array_filter( array_map( 'trim', explode( ',', $lesending_list ) ) );
	return in_array( $lesending_remote, $lesending_allowed, true );
}

/**
 * @param array<string,mixed> $lesending_data Data.
 * @param int                 $lesending_code HTTP status.
 */
function lesending_bridge_respond( $lesending_data, $lesending_code = 200 ) {
	if ( 200 !== (int) $lesending_code ) {
		http_response_code( (int) $lesending_code );
	}
	lesending_bridge_print_json( $lesending_data );
	exit;
}

/**
 * @param string $lesending_url Image URL.
 * @return int|\WP_Error
 */
function lesending_bridge_sideload_image( $lesending_url ) {
	$lesending_url = esc_url_raw( (string) $lesending_url );
	if ( $lesending_url === '' || 0 !== strpos( $lesending_url, 'https://' ) ) {
		return new WP_Error( 'lesending_bad_url', 'image url must be https' );
	}
	$lesending_tmp = download_url( $lesending_url, 60 );
	if ( is_wp_error( $lesending_tmp ) ) {
		return $lesending_tmp;
	}
	$lesending_path = wp_parse_url( $lesending_url, PHP_URL_PATH );
	$lesending_name = is_string( $lesending_path ) && $lesending_path !== '' ? basename( $lesending_path ) : 'image.jpg';
	$lesending_name = sanitize_file_name( $lesending_name );
	$lesending_check = wp_check_filetype_and_ext( $lesending_tmp, $lesending_name );
	$lesending_allowed = array( 'jpg', 'jpeg', 'jpe', 'png', 'gif', 'webp' );
	$lesending_type = isset( $lesending_check['type'] ) ? (string) $lesending_check['type'] : '';
	$lesending_ext  = isset( $lesending_check['ext'] ) ? strtolower( (string) $lesending_check['ext'] ) : '';
	if ( $lesending_ext === '' || ! in_array( $lesending_ext, $lesending_allowed, true ) || 0 !== strpos( $lesending_type, 'image/' ) ) {
		wp_delete_file( $lesending_tmp );
		return new WP_Error( 'lesending_bad_mime', 'not an allowed image type' );
	}
	if ( ! empty( $lesending_check['proper_filename'] ) ) {
		$lesending_name = $lesending_check['proper_filename'];
	}
	$lesending_file = array(
		'name'     => $lesending_name,
		'tmp_name' => $lesending_tmp,
	);
	$lesending_id = media_handle_sideload( $lesending_file, 0 );
	if ( is_wp_error( $lesending_id ) ) {
		wp_delete_file( $lesending_tmp );
		return $lesending_id;
	}
	return (int) $lesending_id;
}

/**
 * Main bridge request handler (keeps variables out of global scope).
 */
function lesending_bridge_main() {
	if ( ! is_string( LESENDING_BRIDGE_SECRET ) || LESENDING_BRIDGE_SECRET === '' || LESENDING_BRIDGE_SECRET === 'REPLACE_ME_SET_LONG_RANDOM_SECRET' ) {
		lesending_bridge_respond(
			array(
				'ok'      => false,
				'message' => 'Please edit this file and set LESENDING_BRIDGE_SECRET to a long random string (min 32 chars).',
			),
			503
		);
	}

	if ( strlen( LESENDING_BRIDGE_SECRET ) < 32 ) {
		lesending_bridge_respond(
			array(
				'ok'      => false,
				'message' => 'LESENDING_BRIDGE_SECRET must be at least 32 characters.',
			),
			503
		);
	}

	if ( ! lesending_bridge_ip_allowed() ) {
		lesending_bridge_respond( array( 'ok' => false, 'message' => 'forbidden' ), 403 );
	}

	// Authenticated API uses shared secret header (not a browser form nonce).
	$lesending_action_raw = isset( $_REQUEST['lesending_action'] ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended
		? lesending_bridge_sanitize_text( lesending_bridge_unslash( $_REQUEST['lesending_action'] ) ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended
		: '';
	$lesending_action = preg_match( '/^[a-z0-9_-]+$/', $lesending_action_raw ) ? $lesending_action_raw : '';

	if ( ! lesending_bridge_secret_ok() ) {
		lesending_bridge_respond( array( 'ok' => false, 'message' => 'forbidden' ), 403 );
	}

	if ( 'ping' === $lesending_action ) {
		$lesending_payload = array(
			'ok'     => true,
			'bridge' => 'pong',
		);
		$lesending_wp_load = dirname( __FILE__ ) . '/wp-load.php';
		if ( ! is_readable( $lesending_wp_load ) ) {
			$lesending_payload['wp_loaded'] = false;
			$lesending_payload['message']   = 'wp-load.php not found in WordPress root; publish will fail until the file is in the site root.';
		} else {
			$lesending_payload['wp_loaded'] = true;
		}
		lesending_bridge_respond( $lesending_payload );
	}

	if ( 'publish' !== $lesending_action ) {
		lesending_bridge_respond( array( 'ok' => false, 'message' => 'unknown action' ), 400 );
	}

	$lesending_method = isset( $_SERVER['REQUEST_METHOD'] )
		? strtoupper( lesending_bridge_sanitize_text( lesending_bridge_unslash( $_SERVER['REQUEST_METHOD'] ) ) )
		: '';
	if ( 'POST' !== $lesending_method ) {
		lesending_bridge_respond( array( 'ok' => false, 'message' => 'method not allowed' ), 405 );
	}

	if ( (int) LESENDING_BRIDGE_USER_ID <= 0 ) {
		lesending_bridge_respond(
			array(
				'ok'      => false,
				'message' => 'Set LESENDING_BRIDGE_USER_ID to a user who can publish posts.',
			),
			503
		);
	}

	$lesending_wp_load = dirname( __FILE__ ) . '/wp-load.php';
	if ( ! is_readable( $lesending_wp_load ) ) {
		lesending_bridge_respond(
			array(
				'ok'      => false,
				'message' => 'wp-load.php not found. Upload this file to the WordPress root directory.',
			),
			500
		);
	}

	require_once $lesending_wp_load;

	$lesending_raw  = file_get_contents( 'php://input' );
	$lesending_data = json_decode( is_string( $lesending_raw ) ? $lesending_raw : '', true );
	if ( ! is_array( $lesending_data ) ) {
		lesending_bridge_respond( array( 'ok' => false, 'message' => 'invalid json' ), 400 );
	}

	wp_set_current_user( (int) LESENDING_BRIDGE_USER_ID );
	if ( ! current_user_can( 'publish_posts' ) ) {
		lesending_bridge_respond( array( 'ok' => false, 'message' => 'configured user cannot publish posts' ), 403 );
	}

	$lesending_status = isset( $lesending_data['status'] ) ? (string) $lesending_data['status'] : 'draft';
	if ( ! in_array( $lesending_status, array( 'publish', 'draft', 'pending', 'private', 'future' ), true ) ) {
		$lesending_status = 'draft';
	}

	require_once ABSPATH . 'wp-admin/includes/file.php';
	require_once ABSPATH . 'wp-admin/includes/media.php';
	require_once ABSPATH . 'wp-admin/includes/image.php';

	$lesending_sideload_list = isset( $lesending_data['sideload_images'] ) && is_array( $lesending_data['sideload_images'] )
		? $lesending_data['sideload_images']
		: array();
	$lesending_max_side      = max( 0, (int) LESENDING_BRIDGE_MAX_SIDELOAD );
	$lesending_sideload_list = array_slice( $lesending_sideload_list, 0, $lesending_max_side );
	$lesending_url_map       = array();
	$lesending_id_map        = array();
	foreach ( $lesending_sideload_list as $lesending_src ) {
		$lesending_src = esc_url_raw( (string) $lesending_src );
		if ( $lesending_src === '' || isset( $lesending_id_map[ $lesending_src ] ) ) {
			continue;
		}
		$lesending_aid = lesending_bridge_sideload_image( $lesending_src );
		if ( is_wp_error( $lesending_aid ) || $lesending_aid <= 0 ) {
			continue;
		}
		$lesending_new_url = wp_get_attachment_url( $lesending_aid );
		if ( ! $lesending_new_url ) {
			continue;
		}
		$lesending_id_map[ $lesending_src ]  = $lesending_aid;
		$lesending_url_map[ $lesending_src ] = $lesending_new_url;
	}

	$lesending_postarr = array(
		'post_title'   => isset( $lesending_data['title'] ) ? $lesending_data['title'] : '',
		'post_content' => isset( $lesending_data['content'] ) ? $lesending_data['content'] : '',
		'post_excerpt' => isset( $lesending_data['excerpt'] ) ? $lesending_data['excerpt'] : '',
		'post_status'  => $lesending_status,
		'post_name'    => isset( $lesending_data['slug'] ) ? sanitize_title( (string) $lesending_data['slug'] ) : '',
		'post_type'    => 'post',
	);

	if ( ! empty( $lesending_url_map ) ) {
		uksort(
			$lesending_url_map,
			static function ( $lesending_a, $lesending_b ) {
				return strlen( $lesending_b ) - strlen( $lesending_a );
			}
		);
		$lesending_content_html = isset( $lesending_postarr['post_content'] ) ? (string) $lesending_postarr['post_content'] : '';
		$lesending_excerpt_html = isset( $lesending_postarr['post_excerpt'] ) ? (string) $lesending_postarr['post_excerpt'] : '';
		foreach ( $lesending_url_map as $lesending_from => $lesending_to ) {
			$lesending_path = wp_parse_url( $lesending_from, PHP_URL_PATH );
			if ( is_string( $lesending_path ) && $lesending_path !== '' ) {
				$lesending_dir  = dirname( $lesending_path );
				$lesending_file = basename( $lesending_path );
				$lesending_name = preg_replace( '/\.[^.]+$/', '', $lesending_file );
				$lesending_ext  = pathinfo( $lesending_file, PATHINFO_EXTENSION );
				if ( $lesending_name !== '' && $lesending_ext !== '' ) {
					$lesending_pattern = '#https?://[^"\'\s<>]+' . preg_quote( $lesending_dir, '#' ) . '/' . preg_quote( $lesending_name, '#' ) . '(?:-\d+x\d+)?\.' . preg_quote( $lesending_ext, '#' ) . '#i';
					foreach ( array( $lesending_content_html, $lesending_excerpt_html ) as $lesending_html ) {
						if ( preg_match_all( $lesending_pattern, $lesending_html, $lesending_matches ) ) {
							foreach ( array_unique( $lesending_matches[0] ) as $lesending_variant ) {
								$lesending_url_map[ $lesending_variant ] = $lesending_to;
							}
						}
					}
				}
			}
		}
		uksort(
			$lesending_url_map,
			static function ( $lesending_a, $lesending_b ) {
				return strlen( $lesending_b ) - strlen( $lesending_a );
			}
		);
		foreach ( $lesending_url_map as $lesending_from => $lesending_to ) {
			$lesending_postarr['post_content'] = str_replace( $lesending_from, $lesending_to, $lesending_postarr['post_content'] );
			$lesending_postarr['post_excerpt'] = str_replace( $lesending_from, $lesending_to, $lesending_postarr['post_excerpt'] );
		}
	}

	$lesending_remote_id = isset( $lesending_data['remote_post_id'] ) ? (int) $lesending_data['remote_post_id'] : 0;
	if ( $lesending_remote_id > 0 ) {
		$lesending_exists = get_post( $lesending_remote_id );
		if ( ! $lesending_exists instanceof WP_Post || 'post' !== $lesending_exists->post_type ) {
			lesending_bridge_respond( array( 'ok' => false, 'message' => 'invalid remote_post_id' ), 400 );
		}
		if ( ! current_user_can( 'edit_post', $lesending_remote_id ) ) {
			lesending_bridge_respond( array( 'ok' => false, 'message' => 'cannot edit remote_post_id' ), 403 );
		}
		$lesending_postarr['ID'] = $lesending_remote_id;
		$lesending_post_id       = wp_update_post( wp_slash( $lesending_postarr ), true );
	} else {
		$lesending_post_id = wp_insert_post( wp_slash( $lesending_postarr ), true );
	}

	if ( is_wp_error( $lesending_post_id ) ) {
		lesending_bridge_respond(
			array(
				'ok'      => false,
				'message' => $lesending_post_id->get_error_message(),
			),
			500
		);
	}

	$lesending_featured_url = isset( $lesending_data['featured_image_url'] ) ? esc_url_raw( (string) $lesending_data['featured_image_url'] ) : '';
	if ( $lesending_featured_url !== '' ) {
		$lesending_featured_id = isset( $lesending_id_map[ $lesending_featured_url ] ) ? (int) $lesending_id_map[ $lesending_featured_url ] : 0;
		if ( $lesending_featured_id <= 0 ) {
			$lesending_aid = lesending_bridge_sideload_image( $lesending_featured_url );
			if ( ! is_wp_error( $lesending_aid ) && $lesending_aid > 0 ) {
				$lesending_featured_id = $lesending_aid;
			}
		}
		if ( $lesending_featured_id > 0 ) {
			set_post_thumbnail( (int) $lesending_post_id, $lesending_featured_id );
		}
	}

	$lesending_link = get_permalink( (int) $lesending_post_id );
	lesending_bridge_respond(
		array(
			'ok'   => true,
			'id'   => (int) $lesending_post_id,
			'link' => $lesending_link ? (string) $lesending_link : '',
		)
	);
}

lesending_bridge_main();
