<?php
/**
 * WooCommerce Analytics leaderboards (same REST source as WC Admin Overview).
 */

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

const ZERTI_WC_HOME_LEADERBOARDS_CACHE_KEY = 'zerti_home_leaderboards_v1';
const ZERTI_WC_HOME_LEADERBOARDS_BUILD_LOCK_KEY = 'zerti_home_leaderboards_build_v1';

/**
 * Whether WooCommerce Analytics REST is available.
 */
function zerti_wc_analytics_leaderboards_available(): bool
{
    return class_exists('WooCommerce')
        && function_exists('rest_do_request')
        && class_exists(\Automattic\WooCommerce\Admin\API\Init::class);
}

/**
 * @return array{after:string,before:string}
 */
function zerti_wc_home_month_to_date_gmt_range(): array
{
    $tz = function_exists('zerti_get_timezone') ? zerti_get_timezone() : wp_timezone();
    $now = new DateTimeImmutable('now', $tz);
    $start = $now->modify('first day of this month')->setTime(0, 0, 0);
    $end = $now->setTime(23, 59, 59);

    return [
        'after' => $start->setTimezone(new DateTimeZone('UTC'))->format('Y-m-d H:i:s'),
        'before' => $end->setTimezone(new DateTimeZone('UTC'))->format('Y-m-d H:i:s'),
    ];
}

/**
 * @param array<string, mixed> $params
 * @return array<string, mixed>|WP_Error
 */
function zerti_wc_analytics_rest_get(string $path, array $params = [])
{
    if (!zerti_wc_analytics_leaderboards_available()) {
        return new WP_Error('zerti_wc_analytics_unavailable', __('WooCommerce Analytics is not available.', 'zerti'));
    }

    $request = new WP_REST_Request('GET', $path);
    foreach ($params as $key => $value) {
        $request->set_param($key, $value);
    }

    $response = rest_do_request($request);
    if (is_wp_error($response)) {
        return $response;
    }
    if ($response->get_status() !== 200) {
        return new WP_Error('zerti_wc_analytics_http', __('Analytics request failed.', 'zerti'), ['status' => $response->get_status()]);
    }

    return $response->get_data();
}

/**
 * @param list<string> $ids
 * @return list<array<string, mixed>>
 */
function zerti_wc_analytics_fetch_leaderboards(string $after, string $before, array $ids, int $per_page = 5): array
{
    $ids = array_values(array_filter(array_map('sanitize_key', $ids)));
    if ($ids === []) {
        return [];
    }
    $want = array_flip($ids);

    $data = zerti_wc_analytics_rest_get('/wc-analytics/leaderboards', [
        'after' => $after,
        'before' => $before,
        'per_page' => max(1, min(20, $per_page)),
    ]);
    if (is_wp_error($data) || !is_array($data)) {
        return [];
    }

    $by_id = [];
    foreach ($data as $board) {
        if (!is_array($board)) {
            continue;
        }
        $id = sanitize_key((string) ($board['id'] ?? ''));
        if ($id !== '' && isset($want[$id])) {
            $by_id[$id] = zerti_wc_analytics_normalize_leaderboard_for_client($board);
        }
    }

    $out = [];
    foreach ($ids as $id) {
        if (isset($by_id[$id])) {
            $out[] = $by_id[$id];
        }
    }

    return $out;
}

/**
 * Localized leaderboard card copy for the home dashboard.
 *
 * @return array{label:string,headers:list<string>}
 */
function zerti_wc_analytics_leaderboard_meta(string $id): array
{
    if ($id === 'categories') {
        return [
            'label' => __('Top categories - Items sold', 'zerti'),
            'headers' => [
                __('Category', 'zerti'),
                __('Items sold', 'zerti'),
                __('Net sales', 'zerti'),
            ],
        ];
    }
    if ($id === 'products') {
        return [
            'label' => __('Top products - Items sold', 'zerti'),
            'headers' => [
                __('Product', 'zerti'),
                __('Items sold', 'zerti'),
                __('Net sales', 'zerti'),
            ],
        ];
    }

    return [
        'label' => '',
        'headers' => [],
    ];
}

/**
 * @param array<string, mixed> $board
 * @return array<string, mixed>
 */
function zerti_wc_analytics_normalize_leaderboard_for_client(array $board): array
{
    $id = sanitize_key((string) ($board['id'] ?? ''));
    $meta = zerti_wc_analytics_leaderboard_meta($id);
    $headers = $meta['headers'];
    if ($headers === []) {
        $header_map = [
            'Category' => __('Category', 'zerti'),
            'Product' => __('Product', 'zerti'),
            'Items sold' => __('Items sold', 'zerti'),
            'Net sales' => __('Net sales', 'zerti'),
        ];
        foreach ((array) ($board['headers'] ?? []) as $header) {
            $label = (string) ($header['label'] ?? '');
            $headers[] = $header_map[$label] ?? $label;
        }
    }

    $rows = [];
    foreach ((array) ($board['rows'] ?? []) as $row) {
        if (!is_array($row) || count($row) < 3) {
            continue;
        }
        $name_cell = $row[0];
        $qty_cell = $row[1];
        $sales_cell = $row[2];
        $name_plain = (string) ($name_cell['value'] ?? '');
        if ($name_plain === '') {
            $name_plain = wp_strip_all_tags((string) ($name_cell['display'] ?? ''));
        }
        $rows[] = [
            'name' => $name_plain,
            'items_sold' => function_exists('zerti_format_admin_number')
                ? zerti_format_admin_number($qty_cell['value'] ?? 0)
                : (string) ($qty_cell['value'] ?? 0),
            'net_sales' => function_exists('zerti_format_admin_price_html')
                ? zerti_format_admin_price_html($sales_cell['value'] ?? 0)
                : wc_price($sales_cell['value'] ?? 0),
        ];
    }

    return [
        'id' => $id,
        'label' => $meta['label'] !== '' ? $meta['label'] : (string) ($board['label'] ?? ''),
        'headers' => $headers,
        'rows' => $rows,
    ];
}

/**
 * @return list<array<string, mixed>>
 */
function zerti_wc_home_build_leaderboards(int $per_page = 5): array
{
    if (!zerti_wc_analytics_leaderboards_available()) {
        return [];
    }

    $range = zerti_wc_home_month_to_date_gmt_range();

    return zerti_wc_analytics_fetch_leaderboards(
        $range['after'],
        $range['before'],
        ['categories', 'products'],
        $per_page
    );
}

function zerti_wc_home_invalidate_leaderboards_cache(): void
{
    delete_transient(ZERTI_WC_HOME_LEADERBOARDS_CACHE_KEY);
    delete_transient(ZERTI_WC_HOME_LEADERBOARDS_BUILD_LOCK_KEY);
}

/**
 * Seconds to hold the leaderboards rebuild lock.
 */
function zerti_wc_home_leaderboards_build_lock_ttl(): int
{
    return max(15, (int) apply_filters('zerti_wc_home_leaderboards_build_lock_ttl', 30));
}

function zerti_wc_home_invalidate_leaderboards_cache_for_refresh(): void
{
    if (get_transient(ZERTI_WC_HOME_LEADERBOARDS_BUILD_LOCK_KEY) !== false) {
        return;
    }

    set_transient(ZERTI_WC_HOME_LEADERBOARDS_BUILD_LOCK_KEY, time(), zerti_wc_home_leaderboards_build_lock_ttl());
    delete_transient(ZERTI_WC_HOME_LEADERBOARDS_CACHE_KEY);
}

function zerti_wc_home_release_leaderboards_build_lock(): void
{
    delete_transient(ZERTI_WC_HOME_LEADERBOARDS_BUILD_LOCK_KEY);
}

/**
 * @return list<array<string, mixed>>|null
 */
function zerti_wc_home_wait_for_cached_leaderboards(int $max_seconds = 10): ?array
{
    $deadline = time() + max(1, $max_seconds);

    while (time() < $deadline) {
        $cached = get_transient(ZERTI_WC_HOME_LEADERBOARDS_CACHE_KEY);
        if (is_array($cached)) {
            return $cached;
        }

        if (get_transient(ZERTI_WC_HOME_LEADERBOARDS_BUILD_LOCK_KEY) === false) {
            return null;
        }

        usleep(100000);
    }

    $cached = get_transient(ZERTI_WC_HOME_LEADERBOARDS_CACHE_KEY);

    return is_array($cached) ? $cached : null;
}

/**
 * @return list<array<string, mixed>>
 */
function zerti_wc_home_get_leaderboards(int $per_page = 5, bool $refresh = false): array
{
    if ($refresh) {
        zerti_wc_home_invalidate_leaderboards_cache_for_refresh();
    }

    $ttl = (int) apply_filters('zerti_wc_home_leaderboards_cache_ttl', 2 * MINUTE_IN_SECONDS);
    if ($ttl > 0) {
        $cached = get_transient(ZERTI_WC_HOME_LEADERBOARDS_CACHE_KEY);
        if (is_array($cached)) {
            zerti_wc_home_release_leaderboards_build_lock();

            return $cached;
        }
    }

    if (get_transient(ZERTI_WC_HOME_LEADERBOARDS_BUILD_LOCK_KEY) !== false) {
        $waited = zerti_wc_home_wait_for_cached_leaderboards(10);
        if (is_array($waited)) {
            zerti_wc_home_release_leaderboards_build_lock();

            return $waited;
        }
    }

    if (get_transient(ZERTI_WC_HOME_LEADERBOARDS_BUILD_LOCK_KEY) === false) {
        set_transient(ZERTI_WC_HOME_LEADERBOARDS_BUILD_LOCK_KEY, time(), zerti_wc_home_leaderboards_build_lock_ttl());
    }

    try {
        $boards = zerti_wc_home_build_leaderboards($per_page);
        if ($ttl > 0 && $boards !== []) {
            set_transient(ZERTI_WC_HOME_LEADERBOARDS_CACHE_KEY, $boards, $ttl);
        }

        return $boards;
    } finally {
        zerti_wc_home_release_leaderboards_build_lock();
    }
}

/**
 * @return array{leaderboards:list<array<string, mixed>>}
 */
function zerti_wc_home_leaderboards_client_payload(int $per_page = 5, bool $refresh = false): array
{
    return [
        'leaderboards' => zerti_wc_home_get_leaderboards($per_page, $refresh),
    ];
}

add_action('woocommerce_order_status_changed', 'zerti_wc_home_invalidate_leaderboards_cache', 10, 0);
add_action('woocommerce_new_order', 'zerti_wc_home_invalidate_leaderboards_cache', 10, 0);
