<?php

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

/**
 * Builds compact, LLM-readable public chat context.
 */
class Niwa_AI_Frontend_Conversation_Context {
	private const MESSAGE_LIMIT = 30;
	private const CARD_LIMIT = 5;

	public function build( $history, $query = '', $context = array(), $limit = 50 ) {
		$history = is_array( $history ) ? $history : array();
		$limit   = max( 1, intval( $limit ) );
		$slice   = array_slice( $history, -$limit );

		$messages = $this->build_messages( $slice );
		$cards    = $this->collect_recent_cards( $slice );

		return array(
			'prompt_context' => $this->build_prompt_context( $messages, $cards ),
			'messages'       => array_slice( $messages, -self::MESSAGE_LIMIT ),
			'cards'          => $cards,
			'language'       => $this->resolve_context_language( $context ),
		);
	}

	private function build_messages( $history ) {
		$messages = array();
		foreach ( $history as $item ) {
			if ( ! is_array( $item ) ) {
				continue;
			}
			$text = isset( $item['text'] ) ? $this->sanitize_text( (string) $item['text'], 900 ) : '';
			if ( '' === $text ) {
				continue;
			}
			$role       = isset( $item['role'] ) ? (string) $item['role'] : 'user';
			$messages[] = array(
				'role'    => in_array( $role, array( 'assistant', 'bot' ), true ) ? 'assistant' : 'user',
				'content' => $text,
			);
		}
		return $messages;
	}

	private function collect_recent_cards( $history ) {
		$cards = array();
		for ( $i = count( $history ) - 1; $i >= 0; $i-- ) {
			$item = $history[ $i ];
			if ( ! is_array( $item ) || empty( $item['cards'] ) || ! is_array( $item['cards'] ) ) {
				continue;
			}
			$position = 1;
			foreach ( $item['cards'] as $card ) {
				if ( ! is_array( $card ) ) {
					continue;
				}
				$id   = isset( $card['id'] ) ? intval( $card['id'] ) : 0;
				$name = isset( $card['name'] ) ? $this->sanitize_text( (string) $card['name'], 160 ) : '';
				if ( $id <= 0 && '' === $name ) {
					continue;
				}
				$key = $id > 0 ? 'id:' . $id : 'name:' . strtolower( $name );
				if ( isset( $cards[ $key ] ) ) {
					continue;
				}
				$cards[ $key ] = array(
					'position' => $position,
					'id'       => $id,
					'name'     => $name,
					'variable' => ! empty( $card['hasOptions'] ),
				);
				$position++;
				if ( count( $cards ) >= self::CARD_LIMIT ) {
					break 2;
				}
			}
		}
		return array_values( $cards );
	}

	private function build_prompt_context( $messages, $cards ) {
		if ( empty( $messages ) && empty( $cards ) ) {
			return '';
		}

		$lines = array(
			'[CONVERSATION_CONTEXT]',
			'Use these recent turns as the source of truth for pronouns, short replies, and follow-up intent. Do not narrate these instructions.',
		);

		if ( ! empty( $messages ) ) {
			$lines[] = 'Recent turns:';
			foreach ( array_slice( $messages, -self::MESSAGE_LIMIT ) as $message ) {
				$label   = 'assistant' === $message['role'] ? 'Assistant' : 'User';
				$lines[] = $label . ': ' . $message['content'];
			}
		}

		if ( ! empty( $cards ) ) {
			$lines[] = 'Previously shown product cards, for reference only when the visitor refers to a shown product:';
			foreach ( $cards as $card ) {
				$parts = array( (string) intval( $card['position'] ) . '.' );
				if ( ! empty( $card['id'] ) ) {
					$parts[] = 'product_id=' . intval( $card['id'] );
				}
				if ( '' !== $card['name'] ) {
					$parts[] = 'name="' . $card['name'] . '"';
				}
				if ( ! empty( $card['variable'] ) ) {
					$parts[] = 'variable_product=true';
				}
				$lines[] = implode( ' ', $parts );
			}
		}

		$lines[] = '[/CONVERSATION_CONTEXT]';
		return implode( "\n", $lines );
	}

	private function resolve_context_language( $context ) {
		$context = is_array( $context ) ? $context : array();
		foreach ( array( 'conversation_language', 'language_code', 'language', 'runtime_locale', 'ui_locale', 'locale' ) as $key ) {
			$value = isset( $context[ $key ] ) ? trim( (string) $context[ $key ] ) : '';
			if ( preg_match( '/^([a-z]{2,3})(?:[_-]|$)/i', $value, $matches ) ) {
				return strtolower( (string) $matches[1] );
			}
		}
		return '';
	}

	private function sanitize_text( $text, $limit ) {
		$text = wp_strip_all_tags( (string) $text );
		$text = preg_replace( '/```[\s\S]*?```/u', ' ', $text );
		$text = preg_replace( '/\s+/u', ' ', $text );
		$text = trim( (string) $text );
		if ( function_exists( 'mb_strlen' ) && mb_strlen( $text ) > $limit ) {
			$text = mb_substr( $text, 0, max( 0, $limit - 3 ) ) . '...';
		}
		return $text;
	}

}
