<?php

namespace Limb_Chatbot\Includes\Services\Export\Formatters;

use Limb_Chatbot\Includes\Services\Export\Abstract_Chat_Export_Formatter;

/**
 * Class Csv_Chat_Export_Formatter
 *
 * Formats chat export data as a structured CSV that mirrors the reference layout:
 *
 * - Agent header row (Agent ID, Agent Name, Start Date, End Date)
 * - Per-conversation section separated by a visual divider:
 *   - Date Created / Last Message At
 *   - Conversation ID / Source
 *   - Messages table (Role, Message)
 *
 * @package Limb_Chatbot\Includes\Services\Export\Formatters
 * @since 1.0.0
 */
class Csv_Chat_Export_Formatter extends Abstract_Chat_Export_Formatter {

	/**
	 * Separator character repeated to form a visual divider.
	 *
	 * @var string
	 */
	const SEPARATOR_CHAR = '_';

	/**
	 * Number of columns in the widest row (used for separator sizing).
	 *
	 * @var int
	 */
	const COLUMN_COUNT = 5;

	/**
	 * Format the export data as CSV.
	 *
	 * @param array $export_data Structured export data.
	 *
	 * @return string CSV content.
	 */
	public function format( array $export_data ): string {
		$handle = fopen( 'php://temp', 'r+' );
		if ( false === $handle ) {
			return '';
		}

		// Write UTF-8 BOM for Excel compatibility.
		fwrite( $handle, "\xEF\xBB\xBF" );

		$chatbot_id   = $export_data['chatbot_id'] ?? '';
		$chatbot_name = $export_data['chatbot_name'] ?? '';
		$start_date   = $export_data['start_date'] ?? '';
		$end_date     = $export_data['end_date'] ?? '';

		// Agent header.
		fputcsv( $handle, [ '', 'Agent ID', 'Agent Name', 'Start Date', 'End Date' ] );
		fputcsv( $handle, [ '', $chatbot_id, $chatbot_name, $start_date, $end_date ] );

		if ( ! empty( $export_data['conversations'] ) ) {
			foreach ( $export_data['conversations'] as $conversation ) {
				$this->write_conversation( $handle, $conversation );
			}
		}

		rewind( $handle );
		$csv = stream_get_contents( $handle );
		fclose( $handle );

		return $csv;
	}

	/**
	 * Write a single conversation block to the CSV handle.
	 *
	 * @param resource $handle       The file handle.
	 * @param array    $conversation Conversation data.
	 *
	 * @return void
	 */
	private function write_conversation( $handle, array $conversation ): void {
		$chat_uuid      = $conversation['chat_uuid'] ?? '';
		$created_at     = $conversation['created_at'] ?? '';
		$last_message_at = $conversation['last_message_at'] ?? '';
		$source         = $conversation['source'] ?? '';

		// Visual separator.
		$this->write_separator( $handle );

		// Date info row.
		fputcsv( $handle, [ '', 'Date Created', 'Last Message At' ] );
		fputcsv( $handle, [ '', $created_at, $last_message_at ] );

		// Blank line.
		fputcsv( $handle, [ '' ] );

		// Conversation info row.
		fputcsv( $handle, [ 'Conversation:', 'Conversation ID', 'Source' ] );
		fputcsv( $handle, [ '', $chat_uuid, $source ] );

		// Blank line.
		fputcsv( $handle, [ '' ] );

		// Messages header.
		fputcsv( $handle, [ 'Messages:', 'Role', 'Message' ] );

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

				fputcsv( $handle, [
					'',
					$record['role'],
					$this->sanitize_export_value( $record['content'] ),
				] );

				// Append source references if present.
				if ( ! empty( $record['sources'] ) ) {
					foreach ( $record['sources'] as $source ) {
						$source_label = sprintf(
							'  → %s (similarity: %s) %s',
							$source['source'],
							$source['similarity'] ?? 'N/A',
							$source['source_url']
						);
						fputcsv( $handle, [ '', '', $source_label ] );
					}
				}
			}
		}
	}

	/**
	 * Write a visual separator row.
	 *
	 * @param resource $handle The file handle.
	 *
	 * @return void
	 */
	private function write_separator( $handle ): void {
		$separator = [];
		$widths    = [ 16, 38, 200, 19, 19 ];

		foreach ( $widths as $width ) {
			$separator[] = str_repeat( self::SEPARATOR_CHAR, $width );
		}

		fputcsv( $handle, $separator );
	}

	/**
	 * {@inheritdoc}
	 */
	public function get_content_type(): string {
		return 'text/csv; charset=UTF-8';
	}

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

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

