<?php

namespace Limb_Chatbot\Includes\Services\Knowledge\Knowledge_Mappers;

use Limb_Chatbot\Includes\Data_Objects\Dataset;
use Limb_Chatbot\Includes\Data_Objects\Dataset_Meta;
use Limb_Chatbot\Includes\Integrations\Integrations;
use Limb_Chatbot\Includes\Interfaces\Knowledge_Content_Interface;
use Limb_Chatbot\Includes\Interfaces\Knowledge_Mapper_Interface;

class CPT_Knowledge_Mapper implements Knowledge_Mapper_Interface {

	public function get_entry_input( $object ): string {
		if ( ! $object instanceof \WP_Post ) {
			return '';
		}

		return get_the_title( $object );
	}

	public function get_entry_output( $object ): string {
		if ( ! $object instanceof \WP_Post ) {
			return '';
		}

		$title   = get_the_title( $object );
		$excerpt = wp_strip_all_tags( get_the_excerpt( $object ), true );

		// Optionally include trimmed content (adjust length or remove if not desired)
		$content = wp_strip_all_tags( apply_filters( 'the_content', $object->post_content ), true );
		$content = mb_substr( $content, 0, 1000 ); // safe limit

		// Collect taxonomy terms (categories, tags, custom taxonomies)
		$tax_output          = [];
		$taxonomies = get_object_taxonomies( $object->post_type, 'objects' );

		// Try to get dataset from filter context first (set by generator)
		$dataset = apply_filters( 'lbaic_cpt_mapper_dataset_context', null );

		// Fallback to database lookup if not in context
		if ( ! $dataset instanceof Dataset ) {
			$datasets = Dataset::where( [
				'source'          => $object->ID,
				'source_type'     => 'cpt',
				'source_sub_type' => $object->post_type
			] );
			if ( ! $datasets->is_empty() ) {
				$dataset = $datasets->first();
			}
		}

		$selected_taxonomies = [];
		if ( $dataset instanceof Dataset ) {
			$taxonomies_meta = $dataset->get_meta( 'taxonomies' );
			$selected_taxonomies = $taxonomies_meta instanceof Dataset_Meta ? $taxonomies_meta->get_meta_value() : [];
		}

		foreach ( $taxonomies as $taxonomy ) {
			if ( ! empty( $selected_taxonomies ) && ! in_array( $taxonomy->name, $selected_taxonomies ) ) {
				continue;
			}

			$terms = get_the_terms( $object, $taxonomy->name );
			if ( ! empty( $terms ) && ! is_wp_error( $terms ) ) {
				$tax_output[] = sprintf(
					'%s: %s',
					$taxonomy->label,
					implode( ', ', wp_list_pluck( $terms, 'name' ) )
				);
			}
		}

		// Get custom fields content from integrations
		$custom_fields_content = $this->get_custom_fields_content( $object, $dataset );

		// Allow integrations to add additional custom fields content via filter
		$additional_custom_fields_content = apply_filters(
			'lbaic_dataset_entry_custom_fields_content',
			'',
			$object,
			$dataset
		);

		// Build the final string with proper separation
		$output_parts = array_filter( [
			$title,
			$excerpt,
			$content,
			! empty( $tax_output ) ? implode( "\n", $tax_output ) : '',
			$custom_fields_content,
			$additional_custom_fields_content,
		] );

		// Join with triple newlines for clear separation between sections
		$output = implode( "\n\n\n", $output_parts );

		return trim( $output );
	}

	/**
	 * Get custom fields content from integrations.
	 *
	 * Checks for integrations implementing Knowledge_Content_Interface and
	 * retrieves custom fields content based on dataset metadata configuration.
	 *
	 * @param  \WP_Post  $post  WordPress post object.
	 * @param  Dataset|null  $dataset  Dataset instance.
	 *
	 * @return string Custom fields content, or empty string if none found.
	 * @since 1.0.0
	 */
	private function get_custom_fields_content( \WP_Post $post, ?Dataset $dataset ): string {
		if ( ! $dataset instanceof Dataset ) {
			return '';
		}

		// Get custom field keys from dataset metadata
		$custom_field_keys = $this->get_custom_field_keys_from_dataset( $dataset );

		// If no custom fields configured, return empty
		if ( empty( $custom_field_keys ) ) {
			return '';
		}

		// Get integrations that can manage knowledge content
		$integrations = Integrations::get_knowledge_content_integrations();

		$content_parts = [];

		// Process each integration
		foreach ( $integrations as $integration ) {
			if ( $integration instanceof Knowledge_Content_Interface ) {
				$integration_content = $integration->get_post_custom_fields_content( $post, $custom_field_keys );
				if ( ! empty( $integration_content ) ) {
					$content_parts[] = $integration_content;
				}
			}
		}

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

	/**
	 * Get custom field keys from dataset metadata.
	 *
	 * Reads custom field keys from dataset metadata. These are saved during
	 * dataset creation from job config.
	 *
	 * @param  Dataset  $dataset  Dataset instance.
	 *
	 * @return array Array of custom field keys, or empty array if none configured.
	 * @since 1.0.0
	 */
	private function get_custom_field_keys_from_dataset( Dataset $dataset ): array {
		$custom_fields_meta = $dataset->get_meta_value( 'custom_fields' );

		if ( empty( $custom_fields_meta ) ) {
			return [];
		}

		// Handle JSON string or array
		if ( is_string( $custom_fields_meta ) ) {
			$custom_fields = json_decode( $custom_fields_meta, true );
			return is_array( $custom_fields ) ? $custom_fields : [];
		}

		return is_array( $custom_fields_meta ) ? $custom_fields_meta : [];
	}
}

