<?php

namespace Limb_Chatbot\Includes\Services\Export\Formatters;

use Dompdf\Dompdf;
use Dompdf\Options;
use Limb_Chatbot\Includes\Services\Export\Abstract_Chat_Export_Formatter;

/**
 * Class Pdf_Chat_Export_Formatter
 *
 * Formats chat export data as a branded PDF document using Dompdf (HTML → PDF).
 *
 * Layout:
 * - Agent header table (Agent ID, Agent Name, Start Date, End Date)
 * - "Conversations" section title
 * - Per conversation:
 *   - Info row (Conversation ID, Date Created, Last Message At)
 *   - Messages table (Role, Message)
 *
 * @package Limb_Chatbot\Includes\Services\Export\Formatters
 * @since 1.0.0
 */
class Pdf_Chat_Export_Formatter extends Abstract_Chat_Export_Formatter {

	/**
	 * Format the export data as PDF.
	 *
	 * @param array $export_data Structured export data.
	 *
	 * @return string Raw PDF binary content.
	 */
	public function format( array $export_data ): string {
		$this->ensure_dompdf_loaded();

		$html = $this->build_html( $export_data );

		$options = new Options();
		$options->set( 'isRemoteEnabled', false );
		$options->set( 'isHtml5ParserEnabled', true );
		$options->set( 'defaultFont', 'DejaVu Sans' );

		$dompdf = new Dompdf( $options );
		$dompdf->loadHtml( $html, 'UTF-8' );
		$dompdf->setPaper( 'A4', 'portrait' );
		$dompdf->render();

		return $dompdf->output();
	}

	/**
	 * {@inheritdoc}
	 */
	public function get_content_type(): string {
		return 'application/pdf';
	}

	/**
	 * {@inheritdoc}
	 */
	public function get_file_extension(): string {
		return 'pdf';
	}

	/**
	 * {@inheritdoc}
	 */
	public function get_type(): string {
		return 'pdf';
	}

	// ──────────────────────────────────────────────────────────────────────
	// Dompdf lazy loader
	// ──────────────────────────────────────────────────────────────────────

	/**
	 * Ensure Dompdf library is loaded.
	 *
	 * Lazy-loads the autoloader only when needed, following the same pattern
	 * used by the pdfparser content extractor.
	 *
	 * @return void
	 */
	private function ensure_dompdf_loaded(): void {
		if ( class_exists( 'Dompdf\Dompdf', false ) ) {
			return;
		}

		$plugin_dir = defined( 'LIMB_CHATBOT_FILE' )
			? plugin_dir_path( LIMB_CHATBOT_FILE )
			: dirname( dirname( dirname( dirname( __DIR__ ) ) ) ) . '/';

		$autoloader_path = $plugin_dir . 'includes/lib/dompdf/autoload.php';
		if ( file_exists( $autoloader_path ) ) {
			require_once $autoloader_path;
		}
	}

	// ──────────────────────────────────────────────────────────────────────
	// HTML builder
	// ──────────────────────────────────────────────────────────────────────

	/**
	 * Build the full HTML document for PDF rendering.
	 *
	 * @param array $export_data Structured export data.
	 *
	 * @return string Complete HTML document.
	 */
	private function build_html( array $export_data ): string {
		$chatbot_name       = $export_data['chatbot_name'] ?? '';
		$conversations_html = '';
		if ( ! empty( $export_data['conversations'] ) ) {
			foreach ( $export_data['conversations'] as $conversation ) {
				$conversations_html .= $this->build_conversation_html( $conversation, $chatbot_name );
			}
		}

		return '<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><style>' . $this->get_styles() . '</style></head>
<body>

<h2 class="section-title">' . esc_html__( 'Conversations', 'limb-chatbot' ) . '</h2>

' . $conversations_html . '

<div class="footer">' . esc_html__( 'Powered by Limb AI Chatbot', 'limb-chatbot' ) . '</div>

</body>
</html>';
	}

	/**
	 * Build HTML for a single conversation block.
	 *
	 * @param array $conversation Conversation data.
	 *
	 * @return string HTML fragment.
	 */
	private function build_conversation_html( array $conversation, string $chatbot_name = '' ): string {
		$chat_uuid       = esc_html( $conversation['chat_uuid'] ?? '' );
		$created_at      = esc_html( $conversation['created_at'] ?? '' );
		$last_message_at = esc_html( $conversation['last_message_at'] ?? '' );

		$messages_html = '';
		if ( ! empty( $conversation['messages'] ) ) {
			foreach ( $conversation['messages'] as $message ) {
				$record = $this->extract_message_record( $message );

				$content_html = $this->markdown_to_html( $record['content'] );

				// Append non-text content parts (WooCommerce widgets, etc.).
				$raw_parts = $message->get_content();
				if ( is_array( $raw_parts ) ) {
					$content_html .= $this->build_content_parts_html( $raw_parts );
				}

				// Append source references if present.
				if ( ! empty( $record['sources'] ) ) {
					$content_html .= '<div class="msg-sources">';
					foreach ( $record['sources'] as $source ) {
						$source_name = esc_html( $source['source'] );
						$similarity  = $source['similarity'] !== null ? esc_html( $source['similarity'] ) : 'N/A';
						$source_url  = esc_url( $source['source_url'] );
						$content_html .= '<div class="msg-source-item">';
						$content_html .= '↳ ' . $source_name . ' (similarity: ' . $similarity . ')';
						if ( ! empty( $source_url ) ) {
							$content_html .= ' <span class="source-url">' . esc_html( $source_url ) . '</span>';
						}
						$content_html .= '</div>';
					}
					$content_html .= '</div>';
				}

				$display_role   = ( 'assistant' === $record['role'] && '' !== $chatbot_name )
					? $chatbot_name
					: $record['role'];
				$messages_html .= '<tr>'
					. '<td class="msg-role">' . esc_html( $display_role ) . '</td>'
					. '<td class="msg-content">' . $content_html . '</td>'
					. '</tr>';
			}
		}

		return '
<div class="conversation">
	<table class="conv-info">
		<thead>
			<tr>
				<th>' . esc_html__( 'Conversation ID', 'limb-chatbot' ) . '</th>
				<th>' . esc_html__( 'Date Created', 'limb-chatbot' ) . '</th>
				<th>' . esc_html__( 'Last Message At', 'limb-chatbot' ) . '</th>
			</tr>
		</thead>
		<tbody>
			<tr>
				<td>' . $chat_uuid . '</td>
				<td>' . $created_at . '</td>
				<td>' . $last_message_at . '</td>
			</tr>
		</tbody>
	</table>

	<table class="messages">
		<thead>
			<tr>
				<th>' . esc_html__( 'Role', 'limb-chatbot' ) . '</th>
				<th>' . esc_html__( 'Message', 'limb-chatbot' ) . '</th>
			</tr>
		</thead>
		<tbody>
			' . $messages_html . '
		</tbody>
	</table>
</div>';
	}

	/**
	 * Render HTML summaries for all non-text content parts in a message.
	 *
	 * @param array $parts Raw content parts array from Message::get_content().
	 *
	 * @return string HTML fragment.
	 */
	private function build_content_parts_html( array $parts ): string {
		$html = '';

		foreach ( $parts as $part ) {
			$type = $part['type'] ?? '';

			switch ( $type ) {
				case 'text':
					// Already rendered via markdown_to_html; skip.
					break;

				case 'wc_product':
					$p     = $part['wc_product'] ?? [];
					$name  = esc_html( $p['name'] ?? '' );
					$price = esc_html( $p['price'] ?? '' );
					$curr  = esc_html( $p['prices']['currency_suffix'] ?? ( $p['prices']['currency_symbol'] ?? '' ) );
					$url   = esc_url( $p['permalink'] ?? '' );
					$html .= '<div class="wc-meta wc-product">'
						. '<span class="wc-meta-label">[Product]</span> '
						. $name
						. ( $price ? ' — ' . $price . ' ' . $curr : '' )
						. ( $url ? ' <span class="source-url">' . esc_html( $url ) . '</span>' : '' )
						. '</div>';
					break;

				case 'wc_products':
					$items = $part['wc_products'] ?? [];
					if ( ! empty( $items ) ) {
						$html .= '<div class="wc-meta wc-products"><span class="wc-meta-label">[Products]</span><ul>';
						foreach ( $items as $p ) {
							$name  = esc_html( $p['name'] ?? '' );
							$price = esc_html( $p['price'] ?? '' );
							$curr  = esc_html( $p['prices']['currency_suffix'] ?? ( $p['prices']['currency_symbol'] ?? '' ) );
							$url   = esc_url( $p['permalink'] ?? '' );
							$html .= '<li>' . $name
								. ( $price ? ' — ' . $price . ' ' . $curr : '' )
								. ( $url ? ' <span class="source-url">' . esc_html( $url ) . '</span>' : '' )
								. '</li>';
						}
						$html .= '</ul></div>';
					}
					break;

				case 'wc_cart':
					$cart  = $part['wc_cart'] ?? [];
					$items = $cart['items'] ?? [];
					if ( ! empty( $items ) ) {
						$html .= '<div class="wc-meta wc-cart"><span class="wc-meta-label">[Cart]</span><ul>';
						foreach ( $items as $item ) {
							$item_name = esc_html( $item['name'] ?? '' );
							$qty       = esc_html( $item['quantity'] ?? '' );
							$subtotal  = esc_html( $item['totals']['line_total'] ?? '' );
							$curr      = esc_html( $item['totals']['currency_suffix'] ?? '' );
							$html     .= '<li>' . $item_name . ' × ' . $qty
								. ( $subtotal ? ' = ' . $subtotal . ' ' . $curr : '' )
								. '</li>';
						}
						$total     = esc_html( $cart['totals']['total_price'] ?? '' );
						$total_cur = esc_html( $cart['totals']['currency_suffix'] ?? '' );
						if ( $total ) {
							$html .= '</ul><div class="wc-cart-total">Total: ' . $total . ' ' . $total_cur . '</div></div>';
						} else {
							$html .= '</ul></div>';
						}
					}
					break;

				case 'wc_choices':
					$options = $part['wc_choices']['options'] ?? [];
					if ( ! empty( $options ) ) {
						$labels = array_map(
							fn( $o ) => esc_html( $o['label'] ?? $o['value'] ?? '' ),
							$options
						);
						$html .= '<div class="wc-meta wc-choices"><span class="wc-meta-label">[Choices]</span> '
							. implode( ' / ', $labels )
							. '</div>';
					}
					break;

				case 'wc_add_to_cart':
					$atc     = $part['wc_add_to_cart'] ?? [];
					$prod_id = esc_html( $atc['product_id'] ?? '' );
					$intent  = esc_html( $atc['intent'] ?? '' );
					$html   .= '<div class="wc-meta wc-add-to-cart"><span class="wc-meta-label">[Add to Cart]</span>'
						. ( $prod_id ? ' Product ID: ' . $prod_id : '' )
						. ( $intent ? ' — ' . $intent : '' )
						. '</div>';
					break;

				case 'wc_product_confirmation':
					$prod_id = esc_html( $part['wc_product_confirmation']['product_id'] ?? '' );
					$html   .= '<div class="wc-meta wc-confirmation"><span class="wc-meta-label">[Product Confirmation]</span>'
						. ( $prod_id ? ' Product ID: ' . $prod_id : '' )
						. '</div>';
					break;

				default:
					// Unknown type — show a generic label.
					if ( '' !== $type ) {
						$html .= '<div class="wc-meta"><span class="wc-meta-label">[' . esc_html( $type ) . ']</span></div>';
					}
					break;
			}
		}

		return $html;
	}

	/**
	 * CSS styles for the PDF document.
	 *
	 * @return string CSS content.
	 */
	private function get_styles(): string {
		return '
			@page {
				margin: 30px 28px;
			}
			body {
				font-family: "DejaVu Sans", Helvetica, Arial, sans-serif;
				font-size: 10px;
				color: #333;
				margin: 0;
				padding: 0;
			}

			/* Section title */
			.section-title {
				font-size: 12px;
				font-weight: normal;
				color: #000;
				margin: 20px 0 12px 0;
			}

			/* Conversation block */
			.conversation {
				margin-bottom: 20px;
				page-break-inside: avoid;
			}

			/* Conversation info table */
			.conv-info {
				width: 100%;
				border-collapse: collapse;
				margin-bottom: 8px;
			}
			.conv-info th {
				font-weight: bold;
				text-align: left;
				padding: 4px 0;
				font-size: 10px;
				color: #141414;
				border: none;
			}
			.conv-info td {
				padding: 4px 0;
				font-size: 10px;
				color: #505050;
				border: none;
			}

			/* Messages table */
			.messages {
				width: 100%;
				border-collapse: collapse;
			}
			.messages th {
				font-weight: bold;
				text-align: left;
				padding: 4px 0;
				font-size: 10px;
				color: #141414;
				border: none;
			}
			.messages td {
				padding: 4px 6px;
				font-size: 10px;
				color: #505050;
				vertical-align: top;
				border: none;
			}
			.messages tbody tr:nth-child(even) {
				background-color: #f5f5fa;
			}
			.msg-role {
				width: 15%;
				white-space: nowrap;
			}
			.msg-content {
				width: 85%;
				word-wrap: break-word;
			}
			.msg-content p {
				margin: 0 0 4px 0;
			}
			.msg-content ul {
				margin: 2px 0;
				padding-left: 14px;
			}
			.msg-content li {
				margin-bottom: 2px;
			}
			.msg-content hr {
				border: none;
				border-top: 1px solid #ccc;
				margin: 4px 0;
			}
			.msg-content strong {
				font-weight: bold;
				color: #333;
			}
			.msg-content a {
				color: #3366cc;
				text-decoration: none;
			}

			/* WooCommerce meta blocks */
			.wc-meta {
				margin-top: 4px;
				padding: 3px 5px;
				background-color: #f0f4ff;
				border-left: 2px solid #aac;
				font-size: 8px;
				color: #444;
			}
			.wc-meta ul {
				margin: 2px 0 0 0;
				padding-left: 12px;
			}
			.wc-meta li {
				margin-bottom: 1px;
			}
			.wc-meta-label {
				font-weight: bold;
				color: #336;
			}
			.wc-cart-total {
				margin-top: 2px;
				font-weight: bold;
			}

			/* Source references */
			.msg-sources {
				margin-top: 4px;
				padding-top: 3px;
				border-top: 1px solid #e0e0e0;
			}
			.msg-source-item {
				font-size: 8px;
				color: #777;
				padding: 1px 0;
			}
			.source-url {
				color: #3366cc;
			}

			/* Footer */
			.footer {
				position: fixed;
				bottom: 0;
				left: 0;
				width: 100%;
				text-align: left;
				font-size: 7px;
				color: #999;
			}
		';
	}
}

