<?php
/**
 * Business info enrichment utilities.
 *
 * Provides deterministic fallback behavior when business description or phone
 * are missing or contain placeholder values. Shared by widget classes and
 * the REST API to avoid duplication.
 *
 * @package    SiteStaffr
 * @subpackage SiteStaffr/includes
 * @since      0.14.271
 */

/**
 * Static utility class for business info enrichment.
 *
 * @since 0.14.271
 */
class SiteStaffr_Business_Enrichment {

	/**
	 * Normalize a business field into a trimmed string.
	 *
	 * @since 0.14.271
	 *
	 * @param mixed $value Field value.
	 * @return string
	 */
	public static function normalize_field( $value ) {
		if ( ! is_string( $value ) ) {
			return '';
		}

		return trim( $value );
	}

	/**
	 * Detect placeholder/test phone values that should be treated as missing.
	 *
	 * @since 0.14.271
	 *
	 * @param string $phone Business phone value.
	 * @return bool
	 */
	public static function is_placeholder_phone( $phone ) {
		$digits = preg_replace( '/\D+/', '', (string) $phone );
		if ( empty( $digits ) ) {
			return false;
		}

		return in_array(
			$digits,
			array(
				'5551234567',
				'1234567890',
				'0000000000',
			),
			true
		);
	}

	/**
	 * Enrich business info with deterministic fallback behavior.
	 *
	 * When description or phone are missing (or placeholders), sets fallback
	 * text and appends runtime instructions to custom_instructions so the AI
	 * model uses deterministic responses instead of guessing.
	 *
	 * @since 0.14.271
	 *
	 * @param array $business_info Business info payload with keys:
	 *   business_description, business_phone, custom_instructions.
	 * @return array Enriched payload with additional keys:
	 *   business_description_available, business_phone_available,
	 *   missing_description_response, missing_business_phone_response.
	 */
	public static function enrich_business_info( $business_info ) {
		if ( ! is_array( $business_info ) ) {
			return array();
		}

		$description = isset( $business_info['business_description'] ) ? self::normalize_field( $business_info['business_description'] ) : '';
		$description_missing = ( '' === $description );
		$phone_raw = isset( $business_info['business_phone'] ) ? self::normalize_field( $business_info['business_phone'] ) : '';
		$custom_instructions = isset( $business_info['custom_instructions'] ) ? self::normalize_field( $business_info['custom_instructions'] ) : '';
		$phone_missing = ( '' === $phone_raw ) || self::is_placeholder_phone( $phone_raw );
		$phone_value = $phone_missing ? __( 'Not publicly listed', 'sitestaffr' ) : $phone_raw;

		$missing_description_response = __( "I don't have specific details about our services right now, but I'd be happy to have someone from our team follow up with more information. Would you like that?", 'sitestaffr' );
		$missing_phone_response = __( "I don't have a public business phone number available right now, but I can have someone from our team follow up with you directly.", 'sitestaffr' );

		$runtime_instructions = array();
		if ( $description_missing ) {
			$description = sprintf(
				/* translators: %s is a deterministic fallback AI response */
				__( 'BUSINESS_DESCRIPTION_MISSING. Do not infer or invent services. If asked what services are offered, reply exactly: %s', 'sitestaffr' ),
				$missing_description_response
			);
			$runtime_instructions[] = sprintf(
				/* translators: %s is a deterministic fallback AI response */
				__( 'If asked what the business does and no business description is configured, reply exactly: %s', 'sitestaffr' ),
				$missing_description_response
			);
		}
		if ( $phone_missing ) {
			$runtime_instructions[] = sprintf(
				/* translators: %s is a deterministic fallback AI response */
				__( 'If asked for the business phone number and none is configured, reply exactly: %s', 'sitestaffr' ),
				$missing_phone_response
			);
		}

		$business_info['business_description'] = $description;
		$business_info['business_phone'] = $phone_value;
		$business_info['business_description_available'] = ! $description_missing;
		$business_info['business_phone_available'] = ! $phone_missing;
		$business_info['missing_description_response'] = $missing_description_response;
		$business_info['missing_business_phone_response'] = $missing_phone_response;

		if ( ! empty( $runtime_instructions ) ) {
			$business_info['custom_instructions'] = trim( $custom_instructions . "\n\n" . implode( "\n", $runtime_instructions ) );
		} else {
			$business_info['custom_instructions'] = $custom_instructions;
		}

		return $business_info;
	}

	/**
	 * Attach hot knowledge chunks to business info payload.
	 *
	 * Queries top chunks by hit_count for pre-loading into the prompt.
	 * Channel determines how many chunks to include (voice=3, text=5).
	 *
	 * @since 2.0.0
	 * @param array  $business_info Business info payload.
	 * @param string $channel       'voice' or 'text'.
	 * @return array Business info with hot_chunks added.
	 */
	public static function attach_hot_chunks( $business_info, $channel = 'voice' ) {
		if ( ! class_exists( 'SiteStaffr_Knowledge_Manager' ) ) {
			require_once SITESTAFFR_PLUGIN_DIR . 'includes/class-sitestaffr-knowledge-manager.php';
		}
		$limit = ( 'text' === $channel ) ? 5 : 3;
		$hot = SiteStaffr_Knowledge_Manager::get_hot_chunks( $limit );
		if ( ! empty( $hot ) ) {
			$business_info['hot_chunks'] = array_map( function ( $chunk ) {
				return array(
					'id'         => (int) $chunk['id'],
					'post_title' => $chunk['post_title'],
					'chunk_text' => $chunk['chunk_text'],
				);
			}, $hot );
		}
		return $business_info;
	}

	/**
	 * Get enabled user-written custom instructions as a single string.
	 *
	 * @since 1.20.0
	 * @return string Newline-separated enabled instructions, or empty string.
	 */
	public static function get_user_custom_instructions() {
		$settings = get_option( 'sitestaffr_settings', array() );
		$list = isset( $settings['custom_instructions_list'] ) ? $settings['custom_instructions_list'] : array();

		if ( empty( $list ) ) {
			return '';
		}

		$enabled = array();
		foreach ( $list as $item ) {
			if ( ! empty( $item['enabled'] ) && ! empty( $item['text'] ) ) {
				$enabled[] = $item['text'];
			}
		}

		return implode( "\n", $enabled );
	}
}
