<?php
/**
 * Options Page Builder — public helpers for themes and integrations.
 *
 * @package OptionsPageBuilder
 * @since 1.1.0
 */

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

/**
 * Find a field definition on an options page.
 *
 * @param string $page_slug Menu slug.
 * @param string $field_id  Field ID.
 * @return array<string, mixed>|null
 */
function wpps_opb_get_field_definition( string $page_slug, string $field_id ): ?array {
	$page_slug = sanitize_key( $page_slug );
	$field_id  = sanitize_key( $field_id );
	if ( $page_slug === '' || $field_id === '' ) {
		return null;
	}

	$pages = get_option( 'wp_powersuite_opb_pages', [] );
	if ( ! is_array( $pages ) ) {
		return null;
	}

	foreach ( $pages as $page ) {
		if ( ! is_array( $page ) || sanitize_key( (string) ( $page['slug'] ?? '' ) ) !== $page_slug ) {
			continue;
		}
		foreach ( $page['fields'] ?? [] as $field ) {
			if ( ! is_array( $field ) ) {
				continue;
			}
			$fid = $field['field_id'] ?? $field['id'] ?? '';
			if ( sanitize_key( (string) $fid ) === $field_id ) {
				return $field;
			}
		}
		break;
	}

	return null;
}

/**
 * Get the builder default for a field (when no value has been saved).
 *
 * @param string $page_slug Menu slug.
 * @param string $field_id  Field ID.
 * @return mixed
 */
function wpps_opb_get_field_default( string $page_slug, string $field_id ): mixed {
	$field = wpps_opb_get_field_definition( $page_slug, $field_id );
	if ( $field === null || ! array_key_exists( 'default', $field ) ) {
		return '';
	}

	return $field['default'];
}

/**
 * Get a field value from an options page.
 *
 * @param string $page_slug Menu slug of the options page.
 * @param string $field_id  Field ID.
 * @param mixed  $default   Fallback when missing from storage and field definition.
 * @return mixed
 */
function wpps_opb_get( string $page_slug, string $field_id, mixed $default = '' ): mixed {
	$page_slug = sanitize_key( $page_slug );
	$field_id  = sanitize_key( $field_id );
	if ( $page_slug === '' || $field_id === '' ) {
		return $default;
	}

	$values = get_option( 'wp_powersuite_opb_' . $page_slug, [] );
	if ( is_array( $values ) && array_key_exists( $field_id, $values ) ) {
		return $values[ $field_id ];
	}

	$field_default = wpps_opb_get_field_default( $page_slug, $field_id );
	if ( $field_default !== '' && $field_default !== null ) {
		return $field_default;
	}

	return $default;
}

/**
 * Get all values for an options page (saved values merged with field defaults).
 *
 * @param string $page_slug Menu slug.
 * @return array<string, mixed>
 */
function wpps_opb_get_all( string $page_slug ): array {
	$page_slug = sanitize_key( $page_slug );
	if ( $page_slug === '' ) {
		return [];
	}

	$values = get_option( 'wp_powersuite_opb_' . $page_slug, [] );
	$values = is_array( $values ) ? $values : [];

	$pages = get_option( 'wp_powersuite_opb_pages', [] );
	if ( ! is_array( $pages ) ) {
		return $values;
	}

	foreach ( $pages as $page ) {
		if ( ! is_array( $page ) || sanitize_key( (string) ( $page['slug'] ?? '' ) ) !== $page_slug ) {
			continue;
		}
		foreach ( $page['fields'] ?? [] as $field ) {
			if ( ! is_array( $field ) || ( $field['type'] ?? '' ) === 'group' ) {
				continue;
			}
			$fid = $field['field_id'] ?? $field['id'] ?? '';
			$fid = sanitize_key( (string) $fid );
			if ( $fid === '' || array_key_exists( $fid, $values ) ) {
				continue;
			}
			if ( array_key_exists( 'default', $field ) && $field['default'] !== '' ) {
				$values[ $fid ] = $field['default'];
			}
		}
		break;
	}

	return $values;
}

/**
 * Resolve an image field value to a URL (attachment ID or legacy URL).
 *
 * @param mixed  $value Attachment ID or URL string.
 * @param string $size  Image size.
 * @return string
 */
function wpps_opb_get_image_url( mixed $value, string $size = 'full' ): string {
	if ( is_numeric( $value ) && (int) $value > 0 ) {
		$url = wp_get_attachment_image_url( (int) $value, $size );
		return is_string( $url ) ? $url : '';
	}

	if ( is_string( $value ) && $value !== '' ) {
		if ( filter_var( $value, FILTER_VALIDATE_URL ) ) {
			return esc_url_raw( $value );
		}
		if ( is_numeric( $value ) ) {
			$url = wp_get_attachment_image_url( (int) $value, $size );
			return is_string( $url ) ? $url : '';
		}
	}

	return '';
}

/**
 * Get attachment ID from an image field value.
 *
 * @param mixed $value Stored value.
 * @return int
 */
function wpps_opb_get_image_id( mixed $value ): int {
	if ( is_numeric( $value ) && (int) $value > 0 ) {
		return (int) $value;
	}

	if ( is_string( $value ) && $value !== '' && filter_var( $value, FILTER_VALIDATE_URL ) ) {
		$id = attachment_url_to_postid( $value );
		return $id > 0 ? $id : 0;
	}

	return 0;
}

/**
 * @return array<string, string>
 */
function wpps_opb_parse_field_options( array $field ): array {
	$opts = $field['options'] ?? '';
	if ( is_array( $opts ) ) {
		return $opts;
	}

	$out = [];
	foreach ( explode( "\n", (string) $opts ) as $line ) {
		$line = trim( $line );
		if ( $line === '' ) {
			continue;
		}
		if ( strpos( $line, '|' ) !== false ) {
			$p = explode( '|', $line, 2 );
			$out[ trim( $p[0] ) ] = trim( $p[1] ?? $p[0] );
		} elseif ( strpos( $line, ':' ) !== false ) {
			$p = explode( ':', $line, 2 );
			$out[ trim( $p[0] ) ] = trim( $p[1] ?? $p[0] );
		} else {
			$out[ $line ] = $line;
		}
	}

	return $out;
}

/**
 * Get display-ready value (images return URL; select/radio return labels).
 *
 * @param string $page_slug Menu slug.
 * @param string $field_id  Field ID.
 * @param mixed  $default   Default when missing.
 * @return mixed
 */
function wpps_opb_get_display( string $page_slug, string $field_id, mixed $default = '' ): mixed {
	$value = wpps_opb_get( $page_slug, $field_id, $default );
	$field = wpps_opb_get_field_definition( $page_slug, $field_id );
	if ( $field === null ) {
		return $value;
	}

	$type = sanitize_key( (string) ( $field['type'] ?? '' ) );

	if ( $type === 'message' ) {
		return (string) ( $field['message_content'] ?? '' );
	}

	if ( in_array( $type, [ 'image', 'file', 'gallery' ], true ) ) {
		$return_format = sanitize_key( (string) ( $field['return_format'] ?? 'id' ) );
		$is_multiple   = $type === 'gallery' || ! empty( $field['multiple'] );
		$ids           = $is_multiple
			? array_filter( array_map( 'absint', is_array( $value ) ? $value : explode( ',', (string) $value ) ) )
			: [ absint( $value ) ];

		if ( $return_format === 'url' ) {
			$urls = [];
			foreach ( $ids as $id ) {
				if ( $id <= 0 ) {
					continue;
				}
				if ( in_array( $type, [ 'image', 'gallery' ], true ) ) {
					$url = wpps_opb_get_image_url( $id );
				} else {
					$url = wp_get_attachment_url( $id );
					$url = is_string( $url ) ? $url : '';
				}
				if ( $url !== '' ) {
					$urls[] = $url;
				}
			}

			if ( $is_multiple ) {
				return $urls !== [] ? $urls : $default;
			}

			return $urls[0] ?? $default;
		}

		if ( $is_multiple ) {
			return $ids !== [] ? $ids : $default;
		}

		return $ids[0] > 0 ? $ids[0] : $default;
	}

	if ( $type === 'link' ) {
		$link = is_array( $value ) ? $value : [];
		if ( empty( $link['url'] ) ) {
			return $default;
		}

		return $link;
	}

	if ( $type === 'repeater' ) {
		return is_array( $value ) ? $value : $default;
	}

	if ( $type === 'wysiwyg' ) {
		return is_string( $value ) ? $value : $default;
	}

	if ( $type === 'select' && ! empty( $field['multiple'] ) ) {
		$choices = is_array( $value ) ? $value : array_filter( array_map( 'trim', explode( ',', (string) $value ) ) );
		if ( $choices === [] ) {
			return $default;
		}
		$opts   = wpps_opb_parse_field_options( $field );
		$labels = [];
		foreach ( $choices as $choice ) {
			$labels[] = $opts[ $choice ] ?? $choice;
		}

		return $labels;
	}

	if ( in_array( $type, [ 'select', 'radio' ], true ) ) {
		$choice = (string) $value;
		if ( $choice === '' ) {
			return $default;
		}
		$opts = wpps_opb_parse_field_options( $field );

		return $opts[ $choice ] ?? $choice;
	}

	if ( in_array( $type, [ 'checkbox', 'toggle' ], true ) ) {
		$checked = in_array( (string) $value, [ '1', 'on', 'yes', 'true' ], true );
		if ( $type === 'checkbox' && ! empty( $field['checkbox_label'] ) ) {
			return $checked ? (string) $field['checkbox_label'] : '';
		}

		return $checked ? __( 'Yes', 'wp-powersuite' ) : __( 'No', 'wp-powersuite' );
	}

	return $value;
}

/**
 * @return array<string, mixed>|null
 */
function wpps_opb_get_page_definition( string $page_slug ): ?array {
	$page_slug = sanitize_key( $page_slug );
	if ( $page_slug === '' ) {
		return null;
	}

	$pages = get_option( 'wp_powersuite_opb_pages', [] );
	if ( ! is_array( $pages ) ) {
		return null;
	}

	foreach ( $pages as $page ) {
		if ( ! is_array( $page ) ) {
			continue;
		}
		if ( sanitize_key( (string) ( $page['slug'] ?? '' ) ) === $page_slug ) {
			return $page;
		}
	}

	return null;
}

/**
 * @return array<int, array<string, string>>
 */
function wpps_opb_get_integratable_fields(): array {
	$pages = get_option( 'wp_powersuite_opb_pages', [] );
	if ( ! is_array( $pages ) ) {
		return [];
	}

	$fields = [];
	foreach ( $pages as $page ) {
		if ( ! is_array( $page ) || empty( $page['slug'] ) || empty( $page['fields'] ) || ! is_array( $page['fields'] ) ) {
			continue;
		}

		$slug       = sanitize_key( (string) $page['slug'] );
		$page_label = (string) ( $page['page_title'] ?? $page['menu_title'] ?? $slug );

		foreach ( $page['fields'] as $field ) {
			if ( ! is_array( $field ) || in_array( $field['type'] ?? '', [ 'group', 'message' ], true ) ) {
				continue;
			}

			$field_id = $field['field_id'] ?? $field['id'] ?? '';
			$field_id = sanitize_key( (string) $field_id );
			if ( $field_id === '' ) {
				continue;
			}

			$fields[] = [
				'page_slug'   => $slug,
				'page_label'  => $page_label,
				'field_id'    => $field_id,
				'field_label' => (string) ( $field['label'] ?? ucfirst( str_replace( '_', ' ', $field_id ) ) ),
				'type'        => sanitize_key( (string) ( $field['type'] ?? 'text' ) ),
			];
		}
	}

	return $fields;
}

function wpps_opb_page_exists( string $page_slug ): bool {
	return wpps_opb_get_page_definition( $page_slug ) !== null;
}

/**
 * Whether the current user may open and save an options page in wp-admin.
 */
function wpps_opb_user_can_manage_page( string $page_slug ): bool {
	$page = wpps_opb_get_page_definition( $page_slug );
	if ( $page === null ) {
		return false;
	}

	$cap = sanitize_key( (string) ( $page['capability'] ?? 'manage_options' ) );

	// Defense in depth for pages saved before capabilities were sanitized:
	// weak capabilities can't grant REST read access to arbitrary users.
	if ( in_array( $cap, [ '', 'read', 'exist' ], true ) && ! apply_filters( 'wp_powersuite_opb_allow_read_capability', false ) ) {
		$cap = 'edit_posts';
	}

	return current_user_can( $cap );
}

/**
 * Raw option values (including non-secret fields) require high privilege.
 */
function wpps_opb_user_can_read_raw_values( string $page_slug ): bool {
	if ( ! wpps_opb_page_exists( $page_slug ) ) {
		return false;
	}

	/**
	 * Capability required to retrieve raw stored option values over REST.
	 *
	 * @param string $capability Capability slug.
	 * @param string $page_slug  Page slug.
	 */
	$cap = apply_filters( 'wp_powersuite_opb_raw_values_capability', 'manage_options', $page_slug );
	$cap = is_string( $cap ) && $cap !== '' ? $cap : 'manage_options';

	return current_user_can( $cap );
}

/**
 * Mask secrets in a values array for REST / JS consumers.
 *
 * @param string               $page_slug Page slug.
 * @param array<string, mixed> $values    Raw values.
 * @return array<string, mixed>
 */
function wpps_opb_mask_secret_values( string $page_slug, array $values ): array {
	$page = wpps_opb_get_page_definition( $page_slug );
	if ( $page === null ) {
		return [];
	}

	$out = [];
	foreach ( $page['fields'] ?? [] as $field ) {
		if ( ! is_array( $field ) || in_array( $field['type'] ?? '', [ 'group', 'message' ], true ) ) {
			continue;
		}
		$fid = sanitize_key( (string) ( $field['field_id'] ?? $field['id'] ?? '' ) );
		if ( $fid === '' || ! array_key_exists( $fid, $values ) ) {
			continue;
		}
		if ( function_exists( 'wpps_opb_field_is_secret' ) && wpps_opb_field_is_secret( $field ) ) {
			$configured = $values[ $fid ] !== '' && $values[ $fid ] !== null;
			$out[ $fid ] = [
				'configured' => (bool) $configured,
				'value'      => '',
			];
			continue;
		}
		$out[ $fid ] = $values[ $fid ];
	}

	return $out;
}

/**
 * Whether the current user may read values over REST (matches admin capability).
 *
 * @deprecated 1.2.1 Use wpps_opb_user_can_manage_page().
 */
function wpps_opb_user_can_read_page( string $page_slug ): bool {
	return wpps_opb_user_can_manage_page( $page_slug );
}

/**
 * Render a field value for shortcodes, builders, and REST consumers.
 *
 * @param array<string, mixed> $args format: display|raw|html|url|text, default
 */
function wpps_opb_render_field_output( string $page_slug, string $field_id, array $args = [] ): string {
	$page_slug = sanitize_key( $page_slug );
	$field_id  = sanitize_key( $field_id );
	if ( $page_slug === '' || $field_id === '' ) {
		return '';
	}

	$format  = sanitize_key( (string) ( $args['format'] ?? 'display' ) );
	$default = $args['default'] ?? '';

	if ( $format === 'raw' ) {
		$value = wpps_opb_get( $page_slug, $field_id, $default );
	} else {
		$value = wpps_opb_get_display( $page_slug, $field_id, $default );
	}

	if ( is_array( $value ) ) {
		$value = implode( ', ', array_map( 'strval', $value ) );
	}

	$field = wpps_opb_get_field_definition( $page_slug, $field_id );
	$type  = is_array( $field ) ? sanitize_key( (string) ( $field['type'] ?? '' ) ) : '';

	if ( $format === 'display' ) {
		if ( in_array( $type, [ 'wysiwyg', 'message' ], true ) ) {
			$format = 'html';
		} elseif ( in_array( $type, [ 'image', 'file', 'gallery', 'url' ], true ) ) {
			$format = 'url';
		} elseif ( $type === 'link' ) {
			$link = is_array( $value ) ? $value : [];
			$href = (string) ( $link['url'] ?? '' );
			$text = (string) ( $link['title'] ?? $href );
			if ( $href === '' ) {
				return '';
			}
			$target = (string) ( $link['target'] ?? '' ) === '_blank' ? ' target="_blank" rel="noopener noreferrer"' : '';

			return '<a href="' . esc_url( $href ) . '"' . $target . '>' . esc_html( $text !== '' ? $text : $href ) . '</a>';
		} else {
			$format = 'text';
		}
	}

	switch ( $format ) {
		case 'html':
			return wp_kses_post( (string) $value );
		case 'url':
			return esc_url( (string) $value );
		case 'raw':
		case 'text':
		default:
			return esc_html( (string) $value );
	}
}

function wpps_opb_replace_content_tags( string $content ): string {
	if ( strpos( $content, '{wp_powersuite_opb:' ) === false ) {
		return $content;
	}

	return (string) preg_replace_callback(
		'/\{wp_powersuite_opb:([^:}]+):([^}]+)\}/',
		static function ( array $matches ): string {
			$page_slug = sanitize_key( $matches[1] );
			if ( ! wpps_opb_page_exists( $page_slug ) ) {
				return '';
			}

			return wpps_opb_render_field_output(
				$page_slug,
				sanitize_key( $matches[2] )
			);
		},
		$content
	);
}
