<?php
/**
 * Team Survey — Publisher.
 *
 * Copies a `ready` response's structured_payload onto the live team CPT
 * post meta the Person schema renderer reads. Single + bulk operation.
 *
 * The source-of-truth for which structured key writes to which post_meta key
 * lives in BW_Schema_Survey::field_map() — keep it greppable.
 *
 * @package BW_AI_Schema_Pro
 * @since 2.2.0
 */

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

class BW_Schema_Survey_Publisher {

	/**
	 * Publish a single response. Returns true on success, false otherwise.
	 * Callers must have already verified capability + nonce.
	 *
	 * @param int $response_id
	 * @return bool
	 */
	public static function publish( $response_id ) {
		$response = BW_Schema_Survey_Store::get( absint( $response_id ) );
		if ( ! $response ) {
			return false;
		}

		if ( BW_Schema_Survey_Store::STATUS_READY !== $response['status'] ) {
			return false;
		}

		$target = $response['target_post_id'];
		if ( ! $target ) {
			return false; // Holding-queue entries must be graduated first.
		}

		$post = get_post( $target );
		$tpt  = BW_Schema_Team_Member::get_team_post_type();
		if ( ! $post || $post->post_type !== $tpt ) {
			return false;
		}

		$structured = is_array( $response['structured_payload'] ) ? $response['structured_payload'] : array();
		$field_map  = BW_Schema_Survey::field_map();

		foreach ( $field_map as $schema_key => $meta_key ) {
			if ( ! array_key_exists( $schema_key, $structured ) ) {
				continue;
			}
			$value = $structured[ $schema_key ];

			// Empty arrays / empty strings clear the meta. Treat NULL/missing as "leave alone".
			if ( null === $value ) {
				continue;
			}

			if ( is_array( $value ) ) {
				// Re-key, drop empty entries, normalize.
				$value = array_values( array_filter( array_map( 'strval', $value ), 'strlen' ) );
				update_post_meta( $target, $meta_key, $value );
			} else {
				update_post_meta( $target, $meta_key, $value );
			}
		}

		BW_Schema_Survey_Store::update( $response_id, array(
			'status'       => BW_Schema_Survey_Store::STATUS_PUBLISHED,
			'published_at' => gmdate( 'Y-m-d H:i:s' ),
		) );

		// Bust any cached schema for this post.
		if ( class_exists( 'BW_Schema_Cache' ) && method_exists( 'BW_Schema_Cache', 'clear_all' ) ) {
			BW_Schema_Cache::clear_all();
		}

		do_action( 'bw_schema_survey_published', $response_id, $target );

		return true;
	}

	/**
	 * Publish a list of response IDs. Returns the count published.
	 */
	public static function publish_many( array $ids ) {
		$count = 0;
		foreach ( $ids as $id ) {
			if ( self::publish( $id ) ) {
				$count++;
			}
		}
		return $count;
	}

	/**
	 * Deterministic parse from raw_payload → structured_payload defaults.
	 * Used by the admin Stage 3 view on first visit (admin can override).
	 *
	 * @param array $raw   The decoded raw_payload.
	 * @return array
	 */
	public static function default_structured_from_raw( array $raw ) {
		$out       = array();
		$questions = BW_Schema_Survey::survey_questions();

		foreach ( $questions as $q ) {
			$key   = $q['key'];
			$value = isset( $raw[ $key ] ) ? $raw[ $key ] : '';
			$schema_field = isset( $q['schema_field'] ) ? $q['schema_field'] : '';
			$type         = isset( $q['structured_type'] ) ? $q['structured_type'] : 'string';

			if ( ! $schema_field ) {
				continue;
			}

			switch ( $type ) {
				case 'list':
					$out[ $schema_field ] = self::prose_to_list( $value );
					break;

				case 'url-list':
					if ( is_array( $value ) ) {
						$out[ $schema_field ] = array_values( array_filter( array_map( 'esc_url_raw', $value ) ) );
					} else {
						$lines                = preg_split( '/[\r\n,]+/', (string) $value );
						$out[ $schema_field ] = array_values( array_filter( array_map( function ( $u ) {
							return esc_url_raw( trim( $u ) );
						}, $lines ) ) );
					}
					break;

				case 'int':
					$out[ $schema_field ] = '' === $value || null === $value ? '' : intval( $value );
					break;

				case 'string':
				default:
					$out[ $schema_field ] = is_array( $value ) ? implode( ', ', $value ) : (string) $value;
			}
		}

		return $out;
	}

	/**
	 * Turn a prose / comma / newline-separated string into a deduped array.
	 */
	public static function prose_to_list( $value ) {
		if ( is_array( $value ) ) {
			$items = $value;
		} else {
			// Split on newlines first; if only one line, split on commas.
			$lines = preg_split( '/[\r\n]+/', (string) $value );
			if ( count( array_filter( array_map( 'trim', $lines ) ) ) > 1 ) {
				$items = $lines;
			} else {
				$items = preg_split( '/,/', (string) $value );
			}
		}

		$items = array_map( function ( $i ) {
			return trim( (string) $i );
		}, $items );

		$items = array_filter( $items, 'strlen' );

		// Stable dedupe (case-insensitive).
		$seen = array();
		$out  = array();
		foreach ( $items as $i ) {
			$k = mb_strtolower( $i );
			if ( isset( $seen[ $k ] ) ) {
				continue;
			}
			$seen[ $k ] = true;
			$out[]      = $i;
		}

		return array_values( $out );
	}
}
