<?php
/**
 * Brevo connection REST controller.
 *
 * @package RewindBrevoFormBridge
 */

namespace RewindBrevoFormBridge\Rest\Controllers;

use RewindBrevoFormBridge\Api\Attributes;
use RewindBrevoFormBridge\Api\Cache;
use RewindBrevoFormBridge\Api\Client;
use RewindBrevoFormBridge\Admin\Settings;
use RewindBrevoFormBridge\Api\Lists;
use RewindBrevoFormBridge\Rest\BaseController;
use RewindBrevoFormBridge\Support\Errors;

defined( 'ABSPATH' ) || exit;

/**
 * Everything the Connections screen needs.
 *
 * Only two routes here ever reach Brevo: /brevo/test and /brevo/refresh,
 * both of which exist solely to serve an explicit button press. The plain
 * reads (/brevo/lists, /brevo/attributes) answer from the transient cache
 * and return cached:false when it is cold, so rendering the UI never
 * triggers an API call.
 *
 * @since 0.4.0
 */
class BrevoController extends BaseController {

	/**
	 * Brevo API client.
	 *
	 * @var Client
	 */
	private Client $client;

	/**
	 * Transient cache.
	 *
	 * @var Cache
	 */
	private Cache $cache;

	/**
	 * Lists resource.
	 *
	 * @var Lists
	 */
	private Lists $lists;

	/**
	 * Attributes resource.
	 *
	 * @var Attributes
	 */
	private Attributes $attributes;

	/**
	 * Settings storage service.
	 *
	 * @var Settings
	 */
	private Settings $settings;

	/**
	 * Constructor.
	 *
	 * @since 0.4.0
	 * @param Client     $client     Brevo API client.
	 * @param Cache      $cache      Transient cache.
	 * @param Lists      $lists      Lists resource.
	 * @param Attributes $attributes Attributes resource.
	 * @param Settings   $settings   Settings storage service.
	 */
	public function __construct( Client $client, Cache $cache, Lists $lists, Attributes $attributes, Settings $settings ) {
		parent::__construct( 'brevo' );

		$this->client     = $client;
		$this->cache      = $cache;
		$this->lists      = $lists;
		$this->attributes = $attributes;
		$this->settings   = $settings;
	}

	/**
	 * Register routes.
	 *
	 * @since 0.4.0
	 * @return void
	 */
	public function register_routes(): void {
		register_rest_route(
			self::NAMESPACE_V1,
			'/' . $this->rest_base . '/test',
			array(
				'methods'             => \WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'test' ),
				'permission_callback' => array( $this, 'can_manage' ),
			)
		);

		register_rest_route(
			self::NAMESPACE_V1,
			'/' . $this->rest_base . '/refresh',
			array(
				'methods'             => \WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'refresh' ),
				'permission_callback' => array( $this, 'can_manage' ),
			)
		);

		register_rest_route(
			self::NAMESPACE_V1,
			'/' . $this->rest_base . '/lists',
			array(
				'methods'             => \WP_REST_Server::READABLE,
				'callback'            => array( $this, 'get_lists' ),
				'permission_callback' => array( $this, 'can_manage' ),
			)
		);

		register_rest_route(
			self::NAMESPACE_V1,
			'/' . $this->rest_base . '/attributes',
			array(
				array(
					'methods'             => \WP_REST_Server::READABLE,
					'callback'            => array( $this, 'get_attributes' ),
					'permission_callback' => array( $this, 'can_manage' ),
				),
				array(
					'methods'             => \WP_REST_Server::CREATABLE,
					'callback'            => array( $this, 'create_attribute' ),
					'permission_callback' => array( $this, 'can_manage' ),
					'args'                => array(
						'label' => array(
							'type'              => 'string',
							'required'          => true,
							'sanitize_callback' => array( $this, 'sanitize_text' ),
						),
						'type'  => array(
							'type'     => 'string',
							'required' => true,
							'enum'     => array( 'text', 'date', 'float', 'boolean' ),
						),
					),
				),
			)
		);
	}

	/**
	 * Explicit "Test connection": GET /account.
	 *
	 * @since 0.4.0
	 * @return \WP_REST_Response|\WP_Error
	 */
	public function test() {
		if ( '' === $this->client_key() ) {
			return $this->error(
				'rbfb_no_key',
				__( 'Add your Brevo API key before testing the connection.', 'rewind-form-bridge-for-brevo' )
			);
		}

		$response = $this->client->get( '/account' );

		if ( ! $response->is_success() ) {
			return $this->error( 'rbfb_api_error', Errors::translate( $response ), self::HTTP_BAD_REQUEST );
		}

		$body    = $response->body();
		$company = isset( $body['companyName'] ) && is_string( $body['companyName'] ) ? $body['companyName'] : '';
		$email   = isset( $body['email'] ) && is_string( $body['email'] ) ? $body['email'] : '';

		$plans = array();
		if ( isset( $body['plan'] ) && is_array( $body['plan'] ) ) {
			foreach ( $body['plan'] as $plan ) {
				if ( isset( $plan['type'] ) && is_string( $plan['type'] ) ) {
					$plans[] = $plan['type'];
				}
			}
		}

		$verified_at = current_time( 'mysql', true );
		update_option( 'rbfb_last_verified', $verified_at, false );

		return $this->respond(
			array(
				'connected'   => true,
				'company'     => '' !== $company ? $company : __( '(no company name set)', 'rewind-form-bridge-for-brevo' ),
				'email'       => $email,
				'plan'        => count( $plans ) > 0 ? implode( ', ', array_unique( $plans ) ) : '',
				'verified_at' => $verified_at,
			)
		);
	}

	/**
	 * Explicit "Refresh from Brevo": flush the cache and refetch.
	 *
	 * @since 0.4.0
	 * @return \WP_REST_Response|\WP_Error
	 */
	public function refresh() {
		if ( '' === $this->client_key() ) {
			return $this->error(
				'rbfb_no_key',
				__( 'Add your Brevo API key before refreshing.', 'rewind-form-bridge-for-brevo' )
			);
		}

		$this->cache->flush();

		$lists = $this->lists->all( true );

		if ( is_wp_error( $lists ) ) {
			return $this->from_wp_error( $lists );
		}

		$attributes = $this->attributes->all( true );

		if ( is_wp_error( $attributes ) ) {
			return $this->from_wp_error( $attributes );
		}

		$cached_at = current_time( 'mysql', true );
		update_option( 'rbfb_cache_stamp', $cached_at, false );

		return $this->respond(
			array(
				'lists'      => $lists,
				'attributes' => $attributes,
				'cached_at'  => $cached_at,
			)
		);
	}

	/**
	 * Cached lists. Never calls the API.
	 *
	 * @since 0.4.0
	 * @return \WP_REST_Response
	 */
	public function get_lists(): \WP_REST_Response {
		$cached = $this->lists->cached();

		return $this->respond(
			array(
				'items'     => null === $cached ? array() : $cached,
				'cached'    => null !== $cached,
				'cached_at' => (string) get_option( 'rbfb_cache_stamp', '' ),
			)
		);
	}

	/**
	 * Cached attributes. Never calls the API.
	 *
	 * @since 0.4.0
	 * @return \WP_REST_Response
	 */
	public function get_attributes(): \WP_REST_Response {
		$cached = $this->attributes->cached();

		return $this->respond(
			array(
				'items'     => null === $cached ? array() : $cached,
				'cached'    => null !== $cached,
				'cached_at' => (string) get_option( 'rbfb_cache_stamp', '' ),
			)
		);
	}

	/**
	 * Create an attribute in Brevo — an explicit click justifies the call.
	 *
	 * @since 0.4.0
	 * @param \WP_REST_Request $request Request.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public function create_attribute( \WP_REST_Request $request ) {
		$label = (string) $request->get_param( 'label' );
		$type  = (string) $request->get_param( 'type' );

		$result = $this->attributes->create( $label, 'normal', $type );

		if ( is_wp_error( $result ) ) {
			return $this->from_wp_error( $result );
		}

		$all = $this->attributes->all( true );

		return $this->respond(
			array(
				'name'       => Attributes::slugify( $label ),
				'attributes' => is_wp_error( $all ) ? array() : $all,
			),
			self::HTTP_CREATED
		);
	}

	/**
	 * The effective API key, read only to test whether one is configured.
	 *
	 * @since 0.4.0
	 * @return string
	 */
	private function client_key(): string {
		return $this->settings->api_key();
	}
}
