<?php

namespace Limb_Chatbot\Includes\Integrations\Slack\Handlers;

use Limb_Chatbot\Includes\Exceptions\Error_Codes;
use Limb_Chatbot\Includes\Exceptions\Exception;
use Limb_Chatbot\Includes\Interfaces\Response_Handler_Interface;
use Limb_Chatbot\Includes\Services\Response_Handler as Base_Response_Handler;

/**
 * Slack Response Handler
 *
 * Handles API responses from Slack endpoints.
 * Extends the base response handler and adds Slack-specific error handling.
 *
 * @package Limb_Chatbot\Includes\Integrations\Slack\Handlers
 * @since 1.0.0
 */
class Response_Handler extends Base_Response_Handler implements Response_Handler_Interface {

	const STATUS_CODE_QUOTA_EXCEED = 429;
	const STATUS_CODE_UNAUTHORIZED = 401;

	/**
	 * When true, response bodies will be decoded as associative arrays.
	 *
	 * @var bool
	 * @since 1.0.0
	 */
	protected bool $body_cast_array = true;

	/**
	 * Parse the HTTP response.
	 *
	 * Calls parent parse and then checks for errors in the response.
	 *
	 * @return void
	 * @throws Exception If a Slack error is found in the response.
	 * @since 1.0.0
	 */
	public function parse() {
		parent::parse();
		$this->check_for_errors();
	}

	/**
	 * Defines and decodes the response body.
	 *
	 * Retrieves and decodes JSON body from WordPress HTTP response.
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function define_body(): void {
		if ( get_class( $this->http_client ) === \WP_Http::class ) {
			$body       = wp_remote_retrieve_body( $this->response );
			$this->body = $this->is_application_json() ? json_decode( $body, $this->body_cast_array ) : $body;
		} else {
			$this->body = null;
		}
	}

	/**
	 * Checks for errors in the response body.
	 *
	 * Throws an Exception with error details if an error is detected.
	 *
	 * @return void
	 * @throws Exception When an error is found in the response.
	 * @since 1.0.0
	 */
	protected function check_for_errors(): void {
		$body = $this->get_body();

		// Slack API returns "ok": false when there's an error
		if ( is_array( $body ) && isset( $body['ok'] ) && $body['ok'] === false ) {
			$error_message = $body['error'] ?? __( 'Unknown Slack API error', 'limb-chatbot' );
			$error_details = $body;

			throw $this->create_slack_exception( $error_message, $error_details );
		}
	}

	/**
	 * Creates a Slack-specific exception with appropriate error codes.
	 *
	 * @param string $message Error message.
	 * @param array  $details Error details from Slack API.
	 *
	 * @return Exception The created exception.
	 * @since 1.0.0
	 */
	protected function create_slack_exception( string $message, array $details ): Exception {
		$http_status = $this->get_status_code();
		$error_code  = Error_Codes::TECHNICAL_ERROR;

		// Map Slack error types to our error codes
		// Check HTTP status codes
		switch ( $http_status ) {
			case self::STATUS_CODE_UNAUTHORIZED:
				$error_code = Error_Codes::AUTHENTICATION_UNAUTHORIZED;
				break;

			case self::STATUS_CODE_QUOTA_EXCEED:
				$error_code = Error_Codes::QUOTA_EXCEED;
				break;
		}

		$exception = new Exception(
			$error_code,
			$message,
			$details,
			$http_status
		);

		if ( $error_code === Error_Codes::QUOTA_EXCEED ) {
			$exception->set_related_to_quota( true );
		}

		return $exception;
	}
}

