<?php
/**
 * Base Shop Explorer Exception Class
 *
 * @package ShopExplorer\Exceptions
 * @since 1.0.0
 */

namespace SHOPEXPLORER\Exceptions;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * Base exception class for Shop Explorer
 *
 * @since 1.0.0
 */
class SHOPEX_ShopExplorerException extends \Exception {

	/**
	 * Error codes
	 */
	const ERROR_GENERAL = 1000;
	const ERROR_CONFIGURATION = 1001;
	const ERROR_AUTHENTICATION = 1002;
	const ERROR_AUTHORIZATION = 1003;
	const ERROR_DATABASE = 1004;
	const ERROR_SYNC = 1006;
	const ERROR_VALIDATION = 1007;
	const ERROR_API = 1008;
	const ERROR_NETWORK = 1009;

	/**
	 * Additional context data
	 *
	 * @var array
	 */
	protected $context = [];

	/**
	 * Error type
	 *
	 * @var string
	 */
	protected $error_type = 'general';

	/**
	 * Constructor
	 *
	 * @param string     $message Exception message
	 * @param int        $code Exception code
	 * @param \Throwable $previous Previous exception
	 * @param array      $context Additional context data
	 */
	public function __construct( $message = '', $code = 0, \Throwable $previous = null, array $context = [] ) {
		parent::__construct( $message, $code, $previous );
		$this->context = $context;
	}

	/**
	 * Get context data
	 *
	 * @return array
	 */
	public function get_context() {
		return $this->context;
	}

	/**
	 * Set context data
	 *
	 * @param array $context Context data
	 * @return self
	 */
	public function set_context( array $context ) {
		$this->context = $context;
		return $this;
	}

	/**
	 * Add context data
	 *
	 * @param string $key Context key
	 * @param mixed  $value Context value
	 * @return self
	 */
	public function add_context( $key, $value ) {
		$this->context[ $key ] = $value;
		return $this;
	}

	/**
	 * Get error type
	 *
	 * @return string
	 */
	public function get_error_type() {
		return $this->error_type;
	}

	/**
	 * Set error type
	 *
	 * @param string $type Error type
	 * @return self
	 */
	public function set_error_type( $type ) {
		$this->error_type = $type;
		return $this;
	}

	/**
	 * Convert exception to array
	 *
	 * @return array
	 */
	public function to_array() {
		return [
			'message' => $this->getMessage(),
			'code' => $this->getCode(),
			'type' => $this->get_error_type(),
			'file' => $this->getFile(),
			'line' => $this->getLine(),
			'context' => $this->get_context(),
			'trace' => $this->getTraceAsString(),
		];
	}

	/**
	 * Convert exception to JSON
	 *
	 * @return string
	 */
	public function to_json() {
		return wp_json_encode( $this->to_array() );
	}

	/**
	 * Log the exception
	 *
	 * @param string $level Log level (error, warning, info, debug)
	 */
	public function log( $level = 'error' ) {
		if ( class_exists( 'SHOPEXPLORER\\Utils\\Logger' ) ) {
			$logger = new \SHOPEXPLORER\Utils\Logger();
			$logger->log( $level, $this->getMessage(), $this->to_array() );
		}
	}

	/**
	 * Get user-friendly error message
	 *
	 * @return string
	 */
	public function get_user_message() {
		// Override in child classes for user-friendly messages
		return $this->getMessage();
	}
}
