<?php

namespace VendorTasksDokanClickUp\VendorIntegration;

use VendorTasksDokanClickUp\API\ClickUpClient;
use VendorTasksDokanClickUp\Queue\ActivityLog;
use VendorTasksDokanClickUp\Queue\PendingQueue;
use VendorTasksDokanClickUp\Settings\PluginSettings;
use VendorTasksDokanClickUp\VendorIntegration\VendorTaskState;

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

/**
 * Vendor Registration Hooks
 *
 * Handles vendor registration detection and ClickUp task creation
 *
 * @since 1.0.0
 * @package VendorTasksDokanClickUp
 * @subpackage VendorIntegration
 */
class Registration {

	/**
	 * Class constructor
	 *
	 * @since 1.0.0
	 */
	public function __construct() {
		// WordPress user registration hook
		add_action( 'user_register', array( $this, 'on_user_register' ), 10, 2 );

		// Dokan vendor registration hooks (frontend/REST)
		add_action( 'dokan_new_seller_created', array( $this, 'on_dokan_vendor_created' ), 10, 2 );

		// Fires when admin creates a vendor via Dokan admin panel / Vendor Manager API
		add_action( 'dokan_new_vendor', array( $this, 'on_dokan_new_vendor' ), 10, 1 );

		// Fires when a vendor store is created via Dokan REST API (POST /dokan/v1/stores)
		add_action( 'dokan_rest_stores_create_store', array( $this, 'on_rest_store_created' ), 10, 1 );

		// WooCommerce customer creation (backup)
		add_action( 'woocommerce_created_customer', array( $this, 'on_wc_customer_created' ), 10, 3 );

		// Bulk sync trigger hook for Pro plugin's BulkSyncRunner
		add_action( 'vendor_tasks_dokan_clickup_sync_vendor', array( $this, 'create_clickup_task_for_vendor' ) );
	}

	/**
	 * Handle WordPress user registration
	 *
	 * @since 1.0.0
	 *
	 * @param int   $user_id User ID.
	 * @param array $userdata User data array.
	 * @return void
	 */
	public function on_user_register( int $user_id, array $userdata = array() ): void {
		// Check if user has vendor role
		if ( ! $this->is_vendor( $user_id ) ) {
			return;
		}

		$this->create_clickup_task_for_vendor( $user_id );
	}

	/**
	 * Handle Dokan vendor registration (frontend / WooCommerce REST API)
	 *
	 * @since 1.0.0
	 *
	 * @param int   $vendor_id Vendor user ID.
	 * @param array $dokan_settings Dokan settings array.
	 * @return void
	 */
	public function on_dokan_vendor_created( int $vendor_id, array $dokan_settings = array() ): void {
		vendor_tasks_dokan_clickup()->log(
			sprintf( 'Dokan vendor created: User ID %d', $vendor_id ),
			'info'
		);

		$this->create_clickup_task_for_vendor( $vendor_id );
	}

	/**
	 * Handle vendor created via Dokan admin panel or Vendor Manager API.
	 *
	 * `dokan_new_seller_created` only fires on frontend/REST registration.
	 * Admin-panel vendor creation fires `dokan_new_vendor` instead.
	 *
	 * @since 1.5.0
	 *
	 * @param int $vendor_id Vendor user ID.
	 * @return void
	 */
	public function on_dokan_new_vendor( int $vendor_id ): void {
		vendor_tasks_dokan_clickup()->log(
			sprintf( 'Dokan vendor created via admin: User ID %d', $vendor_id ),
			'info'
		);

		$this->create_clickup_task_for_vendor( $vendor_id );
	}

	/**
	 * Handle vendor store created via Dokan REST API (POST /dokan/v1/stores).
	 *
	 * `dokan_new_seller_created` and `dokan_new_vendor` do not fire for this path.
	 * The $store parameter is a WeDevs\Dokan\Vendor\Vendor object.
	 *
	 * @since 1.5.0
	 *
	 * @param mixed $store Vendor object just created (WeDevs\Dokan\Vendor\Vendor at runtime).
	 * @return void
	 */
	public function on_rest_store_created( $store ): void {
		if ( ! is_object( $store ) || ! method_exists( $store, 'get_id' ) ) {
			return;
		}

		$vendor_id = (int) $store->get_id();
		if ( ! $vendor_id ) {
			return;
		}

		vendor_tasks_dokan_clickup()->log(
			sprintf( 'Dokan vendor created via REST API: User ID %d', $vendor_id ),
			'info'
		);

		$this->create_clickup_task_for_vendor( $vendor_id );
	}

	/**
	 * Handle WooCommerce customer creation
	 *
	 * @since 1.0.0
	 *
	 * @param int    $customer_id Customer user ID.
	 * @param array  $new_customer_data Customer data.
	 * @param string $password_generated Password generated flag.
	 * @return void
	 */
	public function on_wc_customer_created( int $customer_id, array $new_customer_data = array(), string $password_generated = '' ): void {
		// Check if user has vendor role
		if ( ! $this->is_vendor( $customer_id ) ) {
			return;
		}

		$this->create_clickup_task_for_vendor( $customer_id );
	}

	/**
	 * Check if user is a vendor
	 *
	 * @since 1.0.0
	 *
	 * @param int $user_id User ID.
	 * @return bool True if user is vendor, false otherwise.
	 */
	private function is_vendor( int $user_id ): bool {
		$user = get_userdata( $user_id );

		if ( ! $user ) {
			return false;
		}

		// Check for Dokan vendor role
		if ( in_array( 'seller', $user->roles, true ) ) {
			return true;
		}

		// Check for WooCommerce vendor role (compatibility)
		if ( in_array( 'vendor', $user->roles, true ) ) {
			return true;
		}

		return false;
	}

	/**
	 * Create ClickUp task for vendor
	 *
	 * Returns true on success, WP_Error on failure. Callers that previously
	 * checked the bool return value should use is_wp_error() to detect failures.
	 *
	 * @since 1.0.0
	 * @since 1.1.0 Made public.
	 * @since 1.2.0 Returns WP_Error on failure so callers can surface the message.
	 *
	 * @param int $vendor_id Vendor user ID.
	 * @return true|\WP_Error True on success, WP_Error on failure.
	 */
	public function create_clickup_task_for_vendor( int $vendor_id ) {
		// Check if already processed to avoid duplicates
		$task_state = new VendorTaskState();

		if ( $task_state->has_task( $vendor_id ) ) {
			// Verify the stored task still exists — if deleted on ClickUp, clear and re-create (F-10)
			$stored_task_id = $task_state->get_task_id( $vendor_id );
			if ( ! empty( $stored_task_id ) ) {
				$client = vendor_tasks_dokan_clickup()->get_clickup_client();
				if ( ! $client ) {
					return true; // Cannot verify — assume task exists and skip.
				}

				$check      = $client->get_task( $stored_task_id );
				$error_data = is_wp_error( $check ) ? (array) $check->get_error_data( 'clickup_api_error' ) : array();
				$status     = (int) ( $error_data['status'] ?? 0 );

				if ( is_wp_error( $check ) && 404 === $status ) {
					$task_state->clear_task( $vendor_id );
					vendor_tasks_dokan_clickup()->log(
						sprintf( 'Task %s not found on ClickUp for vendor ID %d — re-creating.', $stored_task_id, $vendor_id ),
						'warning'
					);
					// Fall through to create a new task
				} else {
					vendor_tasks_dokan_clickup()->log(
						sprintf( 'ClickUp task already created for vendor ID %d', $vendor_id ),
						'info'
					);
					return true;
				}
			} else {
				vendor_tasks_dokan_clickup()->log(
					sprintf( 'ClickUp task already created for vendor ID %d', $vendor_id ),
					'info'
				);
				return true;
			}
		}

		$clickup_client = vendor_tasks_dokan_clickup()->get_clickup_client() ?? new ClickUpClient();

		// Format vendor data for ClickUp task
		$task_data = $clickup_client->format_vendor_task_data( $vendor_id, 'vendor_registered' );

		if ( empty( $task_data ) ) {
			vendor_tasks_dokan_clickup()->log(
				sprintf( 'Failed to format task data for vendor ID %d', $vendor_id ),
				'error'
			);
			return new \WP_Error( 'task_format_failed', __( 'Failed to format task data. Ensure the vendor has a display name and the plugin settings are saved.', 'alamin-vendor-tasks-dokan-clickup' ) );
		}

		// Resolve target list — pro plugin may hook in to override via list routing rules.
		$list_id = (string) apply_filters( 'vendor_tasks_dokan_clickup_resolve_list_id', vendor_tasks_dokan_clickup()->get_setting( 'list_id' ), $vendor_id );

		// Create task in ClickUp
		$result = $clickup_client->create_task( $task_data, $list_id );

		if ( is_wp_error( $result ) ) {
			vendor_tasks_dokan_clickup()->log(
				sprintf(
					'Failed to create ClickUp task for vendor ID %d: %s',
					$vendor_id,
					$result->get_error_message()
				),
				'error'
			);

			// Log failure to activity ring-buffer.
			$fail_user   = get_userdata( $vendor_id );
			$fail_vendor = $fail_user instanceof \WP_User
				? $fail_user->display_name
				: (string) $vendor_id;
			( new ActivityLog() )->push(
				__( 'New Vendor Registration', 'alamin-vendor-tasks-dokan-clickup' ),
				$fail_vendor,
				'Failed',
				$vendor_id
			);

			$this->maybe_enqueue_for_retry( $vendor_id );
			return $result;
		}

		// Mark as processed.
		$task_state->record_task(
			$vendor_id,
			$result['id'] ?? '',
			$result['url'] ?? '',
			$result['date_created'] ?? ''
		);
		do_action( 'vendor_tasks_dokan_clickup_vendor_synced', $vendor_id, $result, 'task_created' );

		// Log to activity ring-buffer.
		$user_data      = get_userdata( $vendor_id );
		$vendor_display = $user_data instanceof \WP_User
			? $user_data->display_name
			: (string) $vendor_id;
		( new ActivityLog() )->push(
			__( 'New Vendor Registration', 'alamin-vendor-tasks-dokan-clickup' ),
			$vendor_display,
			'Created',
			$vendor_id
		);

		vendor_tasks_dokan_clickup()->log(
			sprintf(
				'ClickUp task created successfully for vendor ID %d (Task ID: %s)',
				$vendor_id,
				$result['id'] ?? 'unknown'
			),
			'info'
		);

		// Legacy single-event hook — new code should prefer vendor_tasks_dokan_clickup_vendor_synced.
		do_action( 'vendor_tasks_dokan_clickup_task_created', $vendor_id, $result );

		return true;
	}

	/**
	 * Enqueue vendor for retry if retry setting is enabled
	 *
	 * @since 1.1.0
	 *
	 * @param int $vendor_id Vendor user ID.
	 * @return void
	 */
	private function maybe_enqueue_for_retry( int $vendor_id ): void {
		if ( ! ( new PluginSettings() )->is_retry_failed_tasks() ) {
			return;
		}

		( new PendingQueue() )->enqueue( $vendor_id );

		vendor_tasks_dokan_clickup()->log(
			sprintf( 'Vendor ID %d queued for retry.', $vendor_id ),
			'warning'
		);
	}
}
