<?php

namespace VendorTasksDokanClickUp\Rest;

use VendorTasksDokanClickUp\Settings\PluginSettings;
use VendorTasksDokanClickUp\VendorIntegration\VendorTaskState;
use VendorTasksDokanClickUp\Queue\PendingQueue;
use VendorTasksDokanClickUp\Queue\ActivityLog;
use WP_REST_Response;
use WP_REST_Server;

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

/**
 * Overview REST Controller
 *
 * GET /vendor-tasks-dokan-clickup/v1/overview
 * Returns data for the Overview dashboard: counts, health, recent activity, setup checklist.
 *
 * @since 1.5.0
 * @package VendorTasksDokanClickUp
 * @subpackage Rest
 */
class OverviewController {

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

	/**
	 * REST route.
	 */
	public const ROUTE = '/overview';

	/**
	 * Cache group.
	 */
	private const CACHE_GROUP = 'vendor_tasks_dokan_clickup';

	/**
	 * Cache key for overview stats.
	 */
	private const CACHE_KEY = 'overview_stats';

	/**
	 * Cache TTL in seconds (5 minutes).
	 */
	private const CACHE_TTL = 300;

	/**
	 * Constructor.
	 *
	 * Registers the REST route on `rest_api_init`.
	 *
	 * @since 1.5.0
	 */
	public function __construct() {
		add_action( 'rest_api_init', array( $this, 'register_routes' ) );
	}

	/**
	 * Register REST API routes.
	 *
	 * @since 1.5.0
	 *
	 * @return void
	 */
	public function register_routes(): void {
		register_rest_route(
			self::NAMESPACE,
			self::ROUTE,
			array(
				'methods'             => WP_REST_Server::READABLE,
				'callback'            => array( $this, 'get_overview' ),
				'permission_callback' => function () {
					return current_user_can( 'manage_options' );
				},
			)
		);
	}

	/**
	 * Handle GET /overview.
	 *
	 * @since 1.5.0
	 *
	 * @return WP_REST_Response
	 */
	public function get_overview(): WP_REST_Response {
		$cached = wp_cache_get( self::CACHE_KEY, self::CACHE_GROUP );
		if ( false !== $cached && is_array( $cached ) ) {
			return new WP_REST_Response( $cached, 200 );
		}

		$ps        = new PluginSettings();
		$connected = ! empty( $ps->get_api_token() );
		$list_id   = $ps->get_list_id();

		// Counts.
		$tasks_created  = $this->count_tasks_created();
		$vendors_synced = $tasks_created; // Same metric.
		$failed_syncs   = count( ( new PendingQueue() )->get_all() );

		// Active triggers.
		$active_triggers = $this->count_active_triggers( $ps );

		// Recent activity.
		$recent = $this->format_recent( ( new ActivityLog() )->get_all() );

		// List name (from cache if available).
		$list_name = $this->get_list_name( $list_id, $ps );

		// Setup checklist booleans.
		$list_chosen = ! empty( $list_id );

		$data = array(
			'connected'      => $connected,
			'listName'       => $list_name,
			'listChosen'     => $list_chosen,
			'lastSync'       => null,
			'tasksCreated'   => $tasks_created,
			'vendorsSynced'  => $vendors_synced,
			'failedSyncs'    => $failed_syncs,
			'activeTriggers' => $active_triggers,
			'recent'         => $recent,
			'setup'          => array(
				'connected'        => $connected,
				'listChosen'       => $list_chosen,
				'hasActiveTrigger' => $active_triggers > 0,
				'firstTaskReady'   => $connected && $list_chosen,
			),
		);

		wp_cache_set( self::CACHE_KEY, $data, self::CACHE_GROUP, self::CACHE_TTL );

		return new WP_REST_Response( $data, 200 );
	}

	/**
	 * Count users who have a ClickUp task ID stored.
	 *
	 * @since 1.5.0
	 *
	 * @return int
	 */
	private function count_tasks_created(): int {
		global $wpdb;
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery
		$count = $wpdb->get_var(
			$wpdb->prepare(
				"SELECT COUNT(DISTINCT user_id) FROM {$wpdb->usermeta} WHERE meta_key = %s",
				VendorTaskState::META_TASK_ID
			)
		);
		return (int) $count;
	}

	/**
	 * Count how many trigger settings are enabled.
	 *
	 * @since 1.5.0
	 *
	 * @param PluginSettings $ps Plugin settings instance.
	 * @return int
	 */
	private function count_active_triggers( PluginSettings $ps ): int {
		$count = 0;

		// Boolean triggers.
		$booleans = array(
			$ps->is_trigger_vendor_approved(),
			$ps->is_trigger_vendor_disabled(),
			$ps->is_sync_on_profile_update(),
			$ps->is_payment_method_check(),
			$ps->is_trust_status_tag(),
			$ps->is_order_comment_enabled(),
			$ps->is_first_sale_comment(),
			$ps->is_reverse_withdrawal_alert(),
			$ps->is_commission_change_comment(),
		);

		foreach ( $booleans as $enabled ) {
			if ( $enabled ) {
				++$count;
			}
		}

		// Select-type triggers (non-"none" value counts).
		if ( $ps->get_product_review_action() !== 'none' ) {
			++$count;
		}
		if ( $ps->get_withdraw_request_action() !== 'none' ) {
			++$count;
		}

		return $count;
	}

	/**
	 * Format recent activity entries for the frontend.
	 *
	 * @since 1.5.0
	 *
	 * @param array<int, array<string, mixed>> $entries Raw ActivityLog entries.
	 * @return array<int, array{event: string, vendor: string, status: string, ts: int, timeAgo: string}>
	 */
	private function format_recent( array $entries ): array {
		$result = array();
		$now    = time();

		foreach ( $entries as $entry ) {
			$ts       = (int) ( $entry['ts'] ?? 0 );
			$diff     = $now - $ts;
			$time_ago = $this->human_time_ago( $diff );

			$result[] = array(
				'event'   => (string) ( $entry['event'] ?? '' ),
				'vendor'  => (string) ( $entry['vendor'] ?? '' ),
				'status'  => (string) ( $entry['status'] ?? '' ),
				'ts'      => $ts,
				'timeAgo' => $time_ago,
			);
		}

		return $result;
	}

	/**
	 * Convert a seconds-ago integer into a human-readable string.
	 *
	 * @since 1.5.0
	 *
	 * @param int $diff Seconds elapsed.
	 * @return string
	 */
	private function human_time_ago( int $diff ): string {
		if ( $diff < 60 ) {
			return __( 'just now', 'alamin-vendor-tasks-dokan-clickup' );
		}
		if ( $diff < 3600 ) {
			$mins = (int) floor( $diff / 60 );
			/* translators: %d: minutes elapsed */
			return sprintf( __( '%dm ago', 'alamin-vendor-tasks-dokan-clickup' ), $mins );
		}
		if ( $diff < 86400 ) {
			$hours = (int) floor( $diff / 3600 );
			/* translators: %d: hours elapsed */
			return sprintf( __( '%dh ago', 'alamin-vendor-tasks-dokan-clickup' ), $hours );
		}
		$days = (int) floor( $diff / 86400 );
		/* translators: %d: days elapsed */
		return sprintf( __( '%dd ago', 'alamin-vendor-tasks-dokan-clickup' ), $days );
	}

	/**
	 * Get list name from ClickUp client (via cache).
	 *
	 * @since 1.5.0
	 *
	 * @param string         $list_id ClickUp list ID.
	 * @param PluginSettings $ps      Plugin settings.
	 * @return string
	 */
	private function get_list_name( string $list_id, PluginSettings $ps ): string {
		if ( empty( $list_id ) ) {
			return '';
		}

		$cache_key = 'list_name_' . md5( $list_id );
		$cached    = wp_cache_get( $cache_key, self::CACHE_GROUP );
		if ( false !== $cached ) {
			return (string) $cached;
		}

		$client = vendor_tasks_dokan_clickup()->get_clickup_client();
		if ( ! $client ) {
			return '';
		}

		// Try to find the list name in the lists cache.
		$ws_id = $ps->get_workspace_id();
		if ( empty( $ws_id ) ) {
			return $list_id; // Fallback to ID.
		}

		$lists     = $client->get_lists_for_workspace( $ws_id );
		$list_name = '';
		if ( is_array( $lists ) ) {
			foreach ( $lists as $list ) {
				if ( isset( $list['id'] ) && (string) $list['id'] === $list_id ) {
					$list_name = (string) ( $list['name'] ?? '' );
					break;
				}
			}
		}

		wp_cache_set( $cache_key, $list_name ?: $list_id, self::CACHE_GROUP, self::CACHE_TTL );
		return $list_name ?: $list_id;
	}
}
