<?php

namespace Limb_Chatbot\Includes\Data_Objects;

use Limb_Chatbot\Includes\Services\Helper;

/**
 * Class Lead_Capture
 *
 * Represents a complete lead capture record with general metadata and collected data.
 * This is the central data object for managing lead information.
 *
 * @package Limb_Chatbot\Includes\Data_Objects
 * @since 1.0.13
 */
class Lead_Capture {

	/**
	 * Source type: Action
	 */
	const SOURCE_TYPE_ACTION = 'action';

	/**
	 * Source type: Widget
	 */
	const SOURCE_TYPE_WIDGET = 'widget';

	/**
	 * Unique lead capture ID (UUID or generated)
	 *
	 * @var string
	 */
	private string $id;

	/**
	 * When the lead was captured (MySQL datetime)
	 *
	 * @var string
	 */
	private string $captured_at;

	/**
	 * Source identifier (action ID or widget ID)
	 *
	 * @var int|string
	 */
	private $source_id;

	/**
	 * Source name (action title or widget title)
	 *
	 * @var string
	 */
	private string $source_name;

	/**
	 * Source type (action or widget)
	 *
	 * @var string
	 */
	private string $source_type;

	/**
	 * Collected lead data
	 * Each item: ['key' => 'field_key', 'label' => 'Field Label', 'value' => 'field_value']
	 *
	 * @var array
	 */
	private array $collected_data = [];

	/**
	 * Constructor
	 *
	 * @param  string  $source_type  Either SOURCE_TYPE_ACTION or SOURCE_TYPE_WIDGET
	 * @param  int|string  $source_id  Action ID or Widget ID
	 * @param  string  $source_name  Action title or Widget title
	 *
	 * @since 1.0.13
	 */
	public function __construct( string $source_type, $source_id, string $source_name ) {
		$this->id            = Helper::get_uuid();
		$this->source_type   = $source_type;
		$this->source_id     = $source_id;
		$this->source_name   = $source_name;
		$this->captured_at   = current_time( 'mysql', true );
	}

	/**
	 * Get lead capture ID
	 *
	 * @return string
	 * @since 1.0.13
	 */
	public function get_id(): string {
		return $this->id;
	}

	/**
	 * Get capture timestamp
	 *
	 * @return string
	 * @since 1.0.13
	 */
	public function get_captured_at(): string {
		return $this->captured_at;
	}

	/**
	 * Get source ID (action ID or widget ID)
	 *
	 * @return int|string
	 * @since 1.0.13
	 */
	public function get_source_id() {
		return $this->source_id;
	}

	/**
	 * Get source name (action title or widget title)
	 *
	 * @return string
	 * @since 1.0.13
	 */
	public function get_source_name(): string {
		return $this->source_name;
	}

	/**
	 * Get source type
	 *
	 * @return string
	 * @since 1.0.13
	 */
	public function get_source_type(): string {
		return $this->source_type;
	}

	/**
	 * Add a collected field to the lead capture
	 *
	 * @param  string  $key  Field key/name
	 * @param  string  $label  Field label (display name)
	 * @param  mixed  $value  Field value
	 *
	 * @return void
	 * @since 1.0.13
	 */
	public function add_field( string $key, string $label, $value ): void {
		$this->collected_data[] = [
			'key'   => $key,
			'label' => $label,
			'value' => $value,
		];
	}

	/**
	 * Get all collected fields
	 *
	 * @return array Array of fields with key, label, and value
	 * @since 1.0.13
	 */
	public function get_collected_data(): array {
		return $this->collected_data;
	}

	/**
	 * Set all collected fields at once
	 *
	 * @param  array  $data  Array of fields with key, label, and value
	 *
	 * @return void
	 * @since 1.0.13
	 */
	public function set_collected_data( array $data ): void {
		$this->collected_data = $data;
	}

	/**
	 * Get field by key
	 *
	 * @param  string  $key  Field key to search for
	 *
	 * @return array|null Field data or null if not found
	 * @since 1.0.13
	 */
	public function get_field( string $key ): ?array {
		foreach ( $this->collected_data as $field ) {
			if ( $field['key'] === $key ) {
				return $field;
			}
		}

		return null;
	}

	/**
	 * Get field value by key
	 *
	 * @param  string  $key  Field key to search for
	 *
	 * @return mixed|null Field value or null if not found
	 * @since 1.0.13
	 */
	public function get_field_value( string $key ) {
		$field = $this->get_field( $key );

		return $field ? $field['value'] : null;
	}

	/**
	 * Check if this is an action source
	 *
	 * @return bool
	 * @since 1.0.13
	 */
	public function is_action_source(): bool {
		return $this->source_type === self::SOURCE_TYPE_ACTION;
	}

	/**
	 * Check if this is a widget source
	 *
	 * @return bool
	 * @since 1.0.13
	 */
	public function is_widget_source(): bool {
		return $this->source_type === self::SOURCE_TYPE_WIDGET;
	}

	/**
	 * Convert to array for storage/transmission
	 *
	 * @return array
	 * @since 1.0.13
	 */
	public function to_array(): array {
		return [
			'id'               => $this->id,
			'captured_at'      => $this->captured_at,
			'source_id'        => $this->source_id,
			'source_name'      => $this->source_name,
			'source_type'      => $this->source_type,
			'collected_data'   => $this->collected_data,
		];
	}

	/**
	 * Create from array (for retrieval from storage)
	 *
	 * @param  array  $data  Array with lead capture data
	 *
	 * @return static
	 * @since 1.0.13
	 */
	public static function from_array( array $data ): self {
		$source_type = $data['source_type'] ?? self::SOURCE_TYPE_ACTION;
		$source_id   = $data['source_id'] ?? 0;
		$source_name = $data['source_name'] ?? '';

		$instance = new self( $source_type, $source_id, $source_name );

		// Set the ID if provided
		if ( ! empty( $data['id'] ) ) {
			$instance->id = $data['id'];
		}

		// Set the captured_at if provided
		if ( ! empty( $data['captured_at'] ) ) {
			$instance->captured_at = $data['captured_at'];
		}

		// Set collected data if provided
		if ( ! empty( $data['collected_data'] ) && is_array( $data['collected_data'] ) ) {
			$instance->set_collected_data( $data['collected_data'] );
		}

		return $instance;
	}

	/**
	 * Convert to JSON for serialization
	 *
	 * @return string
	 * @since 1.0.13
	 */
	public function to_json(): string {
		return wp_json_encode( $this->to_array() );
	}

	/**
	 * Get human-readable summary
	 *
	 * @return string
	 * @since 1.0.13
	 */
	public function get_summary(): string {
		$type = $this->source_type === self::SOURCE_TYPE_ACTION ? 'Action' : 'Widget';

		return sprintf(
			'Lead captured from %s "%s" (ID: %s) at %s. Fields collected: %d',
			$type,
			$this->source_name,
			$this->source_id,
			$this->captured_at,
			count( $this->collected_data )
		);
	}
}
