<?php
/**
 * Error Handler Trait
 *
 * Provides standardized error logging and handling methods for classes
 * that need to log errors consistently without direct error_log() calls.
 *
 * @package Sequensy
 * @since 2.0.0
 */

declare(strict_types=1);

namespace Sequensy\Traits;

use Sequensy\Exceptions\SequensyException;
use Sequensy\Storage\ActivityLogger;
use Exception;
use WP_Error;

// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
	die;
}

/**
 * Trait ErrorHandler
 *
 * Provides consistent error logging methods that use the Activity Logger
 * or debug.log based on context. Classes using this trait should have
 * a $logger property or override get_error_handler_logger().
 */
trait ErrorHandler {

	/**
	 * Log an error message.
	 *
	 * Uses the activity logger if available and workflow context exists,
	 * otherwise falls back to debug_log for system-level errors.
	 *
	 * @param string   $message     Error message.
	 * @param array    $context     Additional context data.
	 * @param int|null $workflow_id Optional workflow ID for activity logging.
	 */
	protected function log_error( string $message, array $context = array(), ?int $workflow_id = null ): void {
		$logger = $this->get_error_handler_logger();

		if ( $logger && $workflow_id ) {
			$logger->error( $workflow_id, $message, $context );
		} else {
			$this->debug_log( 'error', $message, $context );
		}
	}

	/**
	 * Log a warning message.
	 *
	 * @param string   $message     Warning message.
	 * @param array    $context     Additional context data.
	 * @param int|null $workflow_id Optional workflow ID for activity logging.
	 */
	protected function log_warning( string $message, array $context = array(), ?int $workflow_id = null ): void {
		$logger = $this->get_error_handler_logger();

		if ( $logger && $workflow_id ) {
			$logger->warning( $workflow_id, $message, $context );
		} else {
			$this->debug_log( 'warning', $message, $context );
		}
	}

	/**
	 * Log an info message.
	 *
	 * @param string   $message     Info message.
	 * @param array    $context     Additional context data.
	 * @param int|null $workflow_id Optional workflow ID for activity logging.
	 */
	protected function log_info( string $message, array $context = array(), ?int $workflow_id = null ): void {
		$logger = $this->get_error_handler_logger();

		if ( $logger && $workflow_id ) {
			$logger->info( $workflow_id, $message, $context );
		} else {
			$this->debug_log( 'info', $message, $context );
		}
	}

	/**
	 * Log to WordPress debug.log if WP_DEBUG_LOG is enabled.
	 *
	 * This is for system-level logging when no workflow context is available.
	 *
	 * @param string $level   Log level (error, warning, info).
	 * @param string $message Log message.
	 * @param array  $context Additional context data.
	 */
	protected function debug_log( string $level, string $message, array $context = array() ): void {
		if ( ! defined( 'WP_DEBUG_LOG' ) || ! WP_DEBUG_LOG ) {
			return;
		}

		$log_message = sprintf(
			'[Sequensy Pro] [%s] %s',
			strtoupper( $level ),
			$message
		);

		if ( ! empty( $context ) ) {
			$log_message .= ' | Context: ' . wp_json_encode( $context );
		}

		error_log( $log_message );
	}

	/**
	 * Handle an error and return a standardized WP_Error.
	 *
	 * Converts various error types (Exception, WP_Error, string) to WP_Error.
	 *
	 * @param mixed  $error      The error to handle (Exception, WP_Error, or string).
	 * @param string $error_code Default error code if not determinable.
	 * @param array  $context    Additional context for logging.
	 * @return WP_Error Standardized error object.
	 */
	protected function handle_error(
		mixed $error,
		string $error_code = 'sequensy_error',
		array $context = array()
	): WP_Error {
		if ( $error instanceof SequensyException ) {
			return $error->to_wp_error();
		}

		if ( $error instanceof Exception ) {
			return new WP_Error(
				$error_code,
				$error->getMessage(),
				array_merge( $context, array( 'exception_class' => get_class( $error ) ) )
			);
		}

		if ( is_wp_error( $error ) ) {
			return $error;
		}

		// Assume string message.
		return new WP_Error( $error_code, (string) $error, $context );
	}

	/**
	 * Create a WP_Error for a specific error condition.
	 *
	 * @param string $code    Error code.
	 * @param string $message Error message.
	 * @param array  $data    Additional error data.
	 * @return WP_Error
	 */
	protected function create_error( string $code, string $message, array $data = array() ): WP_Error {
		return new WP_Error( $code, $message, $data );
	}

	/**
	 * Get the logger instance.
	 *
	 * Classes using this trait should either have a $logger property
	 * or override this method to provide access to the logger.
	 *
	 * @return ActivityLogger|null Logger instance or null.
	 */
	protected function get_error_handler_logger(): ?ActivityLogger {
		if ( property_exists( $this, 'logger' ) && $this->logger instanceof ActivityLogger ) {
			return $this->logger;
		}

		return null;
	}
}
