<?php

namespace VendorTasksDokanClickUp\Rest;

use WP_Error;
use WP_REST_Request;
use WP_REST_Response;
use WP_REST_Server;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Settings REST Controller
 *
 * GET  /vendor-tasks-dokan-clickup/v1/settings  — Returns settings with api_token masked.
 * POST /vendor-tasks-dokan-clickup/v1/settings  — Sanitizes and saves settings.
 *
 * @since 1.3.0
 * @package VendorTasksDokanClickUp
 * @subpackage Rest
 */
class SettingsController {

	/**
	 * API namespace
	 */
	public const NAMESPACE = 'vendor-tasks-dokan-clickup/v1';

	/**
	 * Route base
	 */
	public const ROUTE = '/settings';

	/**
	 * Class constructor
	 *
	 * Automatically registers hooks following Dokan pattern.
	 *
	 * @since 1.3.0
	 */
	public function __construct() {
		add_action( 'rest_api_init', array( $this, 'register_routes' ) );
	}

	/**
	 * Register REST API routes
	 *
	 * @since 1.3.0
	 *
	 * @return void
	 */
	public function register_routes(): void {
		register_rest_route(
			self::NAMESPACE,
			self::ROUTE,
			array(
				array(
					'methods'             => WP_REST_Server::READABLE,
					'callback'            => array( $this, 'get_settings' ),
					'permission_callback' => array( $this, 'check_admin_permission' ),
				),
				array(
					'methods'             => WP_REST_Server::CREATABLE,
					'callback'            => array( $this, 'update_settings' ),
					'permission_callback' => array( $this, 'check_admin_permission' ),
				),
			)
		);
	}

	/**
	 * GET /settings — Returns all settings.
	 *
	 * The api_token is stripped from the response; api_token_exists boolean
	 * indicates whether a token is configured.
	 *
	 * @since 1.3.0
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response
	 */
	public function get_settings( WP_REST_Request $request ): WP_REST_Response {
		$settings = get_option( 'vendor_tasks_dokan_clickup_settings', array() );

		$api_token_exists   = ! empty( $settings['api_token'] );
		$license_key_exists = ! empty( $settings['license_key'] );
		unset( $settings['api_token'] );
		unset( $settings['license_key'] );
		$settings['api_token_exists']   = $api_token_exists;
		$settings['license_key_exists'] = $license_key_exists;

		return new WP_REST_Response( $settings, 200 );
	}

	/**
	 * POST /settings — Sanitizes and saves settings.
	 *
	 * Accepts api_token = '__KEEP_EXISTING__' to preserve the stored token
	 * without re-sending it through the wire.
	 *
	 * @since 1.3.0
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error
	 */
	public function update_settings( WP_REST_Request $request ) {
		$body      = $request->get_json_params();
		$sanitized = $this->sanitize_settings( $body );

		update_option( 'vendor_tasks_dokan_clickup_settings', $sanitized );
		wp_cache_delete( 'overview_stats', 'vendor_tasks_dokan_clickup' );
		vendor_tasks_dokan_clickup()->plan_manager()->invalidate_cache();

		$safe_settings = $sanitized;
		unset( $safe_settings['api_token'] );
		unset( $safe_settings['license_key'] );
		do_action( 'vendor_tasks_dokan_clickup_settings_saved', $safe_settings );

		$token_exists       = ! empty( $sanitized['api_token'] );
		$license_key_exists = ! empty( $sanitized['license_key'] );
		unset( $sanitized['api_token'] );
		unset( $sanitized['license_key'] );
		$sanitized['api_token_exists']   = $token_exists;
		$sanitized['license_key_exists'] = $license_key_exists;

		return new WP_REST_Response( $sanitized, 200 );
	}

	/**
	 * Sanitize and validate settings input.
	 *
	 * @since 1.4.0
	 *
	 * @param array<string,mixed> $input Raw input array.
	 * @return array<string,mixed>
	 */
	public function sanitize_settings( array $input ): array {
		$sanitized       = array();
		$old_settings    = get_option( 'vendor_tasks_dokan_clickup_settings', array() );
		$old_token       = $old_settings['api_token'] ?? '';
		$old_license_key = $old_settings['license_key'] ?? '';

		if ( isset( $input['api_token'] ) ) {
			$new_token              = sanitize_text_field( $input['api_token'] );
			$sanitized['api_token'] = ( '__KEEP_EXISTING__' === $new_token || '' === $new_token )
				? $old_token
				: $new_token;
		}

		if ( isset( $input['license_key'] ) ) {
			$new_key                  = sanitize_text_field( $input['license_key'] );
			$sanitized['license_key'] = ( '__KEEP_EXISTING__' === $new_key || '' === $new_key )
				? $old_license_key
				: $new_key;
		}

		if ( isset( $input['workspace_id'] ) ) {
			$sanitized['workspace_id'] = sanitize_text_field( $input['workspace_id'] );
		}
		if ( isset( $input['list_id'] ) ) {
			$sanitized['list_id'] = sanitize_text_field( $input['list_id'] );
		}
		if ( isset( $input['task_priority'] ) ) {
			$sanitized['task_priority'] = max( 1, min( 4, absint( $input['task_priority'] ) ) );
		}
		if ( isset( $input['task_description_type'] ) ) {
			$sanitized['task_description_type'] = in_array( $input['task_description_type'], array( 'normal', 'markdown' ), true )
				? $input['task_description_type'] : 'normal';
		}
		if ( isset( $input['task_name_format'] ) ) {
			$sanitized['task_name_format'] = sanitize_text_field( $input['task_name_format'] );
		}
		if ( isset( $input['description_template'] ) ) {
			$sanitized['description_template'] = sanitize_textarea_field( $input['description_template'] );
		}
		if ( isset( $input['task_status'] ) ) {
			$sanitized['task_status'] = sanitize_text_field( $input['task_status'] );
		}
		if ( isset( $input['task_due_date_offset'] ) ) {
			$sanitized['task_due_date_offset'] = max( 0, min( 365, absint( $input['task_due_date_offset'] ) ) );
		}

		$sanitized['task_assignees'] = isset( $input['task_assignees'] ) && is_array( $input['task_assignees'] )
			? array_values( array_filter( array_map( 'absint', $input['task_assignees'] ) ) )
			: array();

		$sanitized['failure_notify_email']   = sanitize_email( $input['failure_notify_email'] ?? '' );
		$sanitized['enable_logging']         = isset( $input['enable_logging'] ) ? (bool) $input['enable_logging'] : false;
		$sanitized['sync_on_profile_update'] = isset( $input['sync_on_profile_update'] ) ? (bool) $input['sync_on_profile_update'] : false;

		if ( isset( $input['product_review_action'] ) ) {
			$sanitized['product_review_action'] = in_array( $input['product_review_action'], array( 'none', 'comment' ), true )
				? $input['product_review_action'] : 'none';
		}
		if ( isset( $input['withdraw_request_action'] ) ) {
			$sanitized['withdraw_request_action'] = in_array( $input['withdraw_request_action'], array( 'none', 'comment' ), true )
				? $input['withdraw_request_action'] : 'none';
		}

		$sanitized['reverse_withdrawal_alert']       = isset( $input['reverse_withdrawal_alert'] ) ? (bool) $input['reverse_withdrawal_alert'] : false;
		$sanitized['first_sale_comment']             = isset( $input['first_sale_comment'] ) ? (bool) $input['first_sale_comment'] : false;
		$sanitized['payment_method_check']           = isset( $input['payment_method_check'] ) ? (bool) $input['payment_method_check'] : false;
		$sanitized['first_product_published_status'] = sanitize_text_field( $input['first_product_published_status'] ?? '' );
		$sanitized['order_comment_enabled']          = isset( $input['order_comment_enabled'] ) ? (bool) $input['order_comment_enabled'] : false;
		$sanitized['commission_change_comment']      = isset( $input['commission_change_comment'] ) ? (bool) $input['commission_change_comment'] : false;
		$sanitized['trust_status_tag']               = isset( $input['trust_status_tag'] ) ? (bool) $input['trust_status_tag'] : false;
		$sanitized['trigger_vendor_approved']        = isset( $input['trigger_vendor_approved'] ) ? (bool) $input['trigger_vendor_approved'] : false;
		$sanitized['trigger_vendor_approved_status'] = sanitize_text_field( $input['trigger_vendor_approved_status'] ?? '' );
		$sanitized['trigger_vendor_disabled']        = isset( $input['trigger_vendor_disabled'] ) ? (bool) $input['trigger_vendor_disabled'] : false;
		$sanitized['trigger_vendor_disabled_status'] = sanitize_text_field( $input['trigger_vendor_disabled_status'] ?? '' );

		// Webhook
		$sanitized['enable_webhook'] = isset( $input['enable_webhook'] ) ? (bool) $input['enable_webhook'] : false;
		$sanitized['webhook_secret'] = sanitize_text_field( $input['webhook_secret'] ?? '' );

		$raw_mappings       = is_array( $input['webhook_status_mappings'] ?? null ) ? $input['webhook_status_mappings'] : array();
		$sanitized_mappings = array();
		$builtin_actions    = array( 'enable_vendor', 'disable_vendor', 'send_welcome_email' );
		foreach ( $raw_mappings as $mapping ) {
			if ( ! is_array( $mapping ) ) {
				continue;
			}
			$clickup_status = sanitize_text_field( $mapping['clickup_status'] ?? '' );
			$wp_action      = sanitize_key( $mapping['wp_action'] ?? '' );
			$select_val     = sanitize_key( $mapping['wp_action_select'] ?? '' );
			if ( in_array( $select_val, $builtin_actions, true ) ) {
				$wp_action = $select_val;
			}
			if ( empty( $clickup_status ) || empty( $wp_action ) ) {
				continue;
			}
			$sanitized_mappings[] = array(
				'clickup_status' => $clickup_status,
				'wp_action'      => $wp_action,
			);
		}
		$sanitized['webhook_status_mappings'] = $sanitized_mappings;

		// List routing
		$sanitized['enable_list_routing'] = isset( $input['enable_list_routing'] ) ? (bool) $input['enable_list_routing'] : false;
		$raw_rules                        = is_array( $input['routing_rules'] ?? null ) ? $input['routing_rules'] : array();
		$sanitized_rules                  = array();
		foreach ( $raw_rules as $rule ) {
			if ( ! is_array( $rule ) ) {
				continue;
			}
			$condition_type = sanitize_text_field( $rule['condition_type'] ?? '' );
			if ( ! in_array( $condition_type, array( 'user_role', 'user_meta' ), true ) ) {
				continue;
			}
			$list = sanitize_text_field( $rule['list_id'] ?? '' );
			if ( empty( $list ) ) {
				continue;
			}
			$sanitized_rules[] = array(
				'condition_type'  => $condition_type,
				'condition_key'   => sanitize_key( $rule['condition_key'] ?? '' ),
				'condition_value' => sanitize_text_field( $rule['condition_value'] ?? '' ),
				'list_id'         => $list,
			);
		}
		$sanitized['routing_rules'] = $sanitized_rules;

		// Slack
		$sanitized['slack_webhook_url']         = esc_url_raw( $input['slack_webhook_url'] ?? '' );
		$sanitized['slack_notify_task_created'] = isset( $input['slack_notify_task_created'] ) ? (bool) $input['slack_notify_task_created'] : false;
		$sanitized['slack_notify_task_failed']  = isset( $input['slack_notify_task_failed'] ) ? (bool) $input['slack_notify_task_failed'] : false;

		$sanitized['retry_failed_tasks'] = isset( $input['retry_failed_tasks'] ) ? (bool) $input['retry_failed_tasks'] : false;
		if ( isset( $input['max_retry_attempts'] ) ) {
			$sanitized['max_retry_attempts'] = max( 1, min( 10, absint( $input['max_retry_attempts'] ) ) );
		}

		// Per-event task templates
		$raw_templates      = is_array( $input['event_templates'] ?? null ) ? $input['event_templates'] : array();
		$clean_templates    = array();
		$allowed_desc_types = array( 'normal', 'markdown' );
		foreach ( $raw_templates as $event_key => $tpl ) {
			if ( ! is_string( $event_key ) || ! is_array( $tpl ) ) {
				continue;
			}
			$event_key = sanitize_key( $event_key );
			if ( empty( $event_key ) ) {
				continue;
			}
			$clean_tpl = array();
			if ( isset( $tpl['name_format'] ) ) {
				$clean_tpl['name_format'] = sanitize_text_field( $tpl['name_format'] );
			}
			if ( isset( $tpl['description_type'] ) ) {
				$clean_tpl['description_type'] = in_array( $tpl['description_type'], $allowed_desc_types, true )
					? $tpl['description_type'] : 'normal';
			}
			if ( isset( $tpl['description_template'] ) ) {
				$clean_tpl['description_template'] = sanitize_textarea_field( $tpl['description_template'] );
			}
			if ( isset( $tpl['priority'] ) ) {
				$clean_tpl['priority'] = max( 1, min( 4, absint( $tpl['priority'] ) ) );
			}
			if ( isset( $tpl['status'] ) ) {
				$clean_tpl['status'] = sanitize_text_field( $tpl['status'] );
			}
			if ( isset( $tpl['due_date_offset'] ) ) {
				$clean_tpl['due_date_offset'] = max( 0, min( 365, absint( $tpl['due_date_offset'] ) ) );
			}
			$clean_templates[ $event_key ] = $clean_tpl;
		}
		$sanitized['event_templates'] = $clean_templates;

		// Clear API cache if token changed.
		if ( isset( $sanitized['api_token'] ) && $old_token !== $sanitized['api_token'] ) {
			$client = vendor_tasks_dokan_clickup()->get_clickup_client();
			if ( $client ) {
				$client->clear_cache();
				vendor_tasks_dokan_clickup()->log( 'Cache cleared due to API token change', 'info' );
			}
		}

		return $sanitized;
	}

	/**
	 * Check admin permission
	 *
	 * @since 1.3.0
	 *
	 * @return bool
	 */
	public function check_admin_permission(): bool {
		return current_user_can( 'manage_options' );
	}
}
