<?php

// SPDX-FileCopyrightText: 2026 Ovation S.r.l. <dev@novamira.ai>
// SPDX-License-Identifier: AGPL-3.0-or-later

declare(strict_types=1);

/**
 * Self-hosted plugin update checker.
 *
 * Checks https://license.dynamic.ooo/api/novamira/info for new versions
 * and injects update data into the WordPress update system.
 */

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

add_filter('site_transient_update_plugins', callback: 'novamira_check_for_updates');
add_filter('plugins_api', callback: 'novamira_plugins_api', priority: 10, accepted_args: 3);

/**
 * Inject update data into the plugins update transient.
 *
 * @param mixed $transient The update_plugins transient value.
 * @return mixed
 */
function novamira_check_for_updates($transient)
{
    if (!is_object($transient)) {
        return $transient;
    }

    /** @var object{response: array<string, object>, no_update: array<string, object>, checked?: array<string, string>} $transient */

    $remote = novamira_fetch_update_info();
    $plugin_file = plugin_basename(dirname(__DIR__) . '/novamira.php');

    if ($remote === null || !version_compare(NOVAMIRA_VERSION, $remote['version'], operator: '<')) {
        // No remote info or up-to-date. Report as no_update so WordPress.org cannot override.
        $transient->no_update[$plugin_file] = (object) [
            'slug' => 'novamira',
            'plugin' => $plugin_file,
            'new_version' => NOVAMIRA_VERSION,
            'url' => '',
            'package' => '',
        ];

        return $transient;
    }

    $update_data = [
        'slug' => 'novamira',
        'plugin' => $plugin_file,
        'new_version' => $remote['version'],
        'url' => $remote['homepage'],
        'package' => $remote['download_url'],
        'tested' => $remote['tested'],
        'requires_php' => $remote['requires_php'],
        'requires' => $remote['requires'],
        'icons' => $remote['icons'],
        'banners' => $remote['banners'],
    ];
    $transient->response[$plugin_file] = (object) $update_data;

    return $transient;
}

/**
 * Supply plugin info for the "View Details" popup.
 *
 * @param false|object|array $result
 * @param string             $action
 * @param object             $args
 * @return false|object|array
 */
function novamira_plugins_api($result, $action, $args)
{
    if ($action !== 'plugin_information' || ($args->slug ?? '') !== 'novamira') {
        return $result;
    }

    $remote = novamira_fetch_update_info();
    if ($remote === null) {
        return $result;
    }

    return (object) [
        'name' => $remote['name'],
        'slug' => 'novamira',
        'version' => $remote['version'],
        'author' => $remote['author'],
        'author_profile' => $remote['author_homepage'],
        'homepage' => $remote['homepage'],
        'requires' => $remote['requires'],
        'requires_php' => $remote['requires_php'],
        'tested' => $remote['tested'],
        'last_updated' => $remote['last_updated'],
        'sections' => $remote['sections'],
        'icons' => $remote['icons'],
        'banners' => $remote['banners'],
        'download_link' => $remote['download_url'],
    ];
}

/**
 * Fetch plugin info from the license server, with transient caching.
 *
 * @return array{name: string, version: string, author: string, author_homepage: string, homepage: string, requires: string, requires_php: string, tested: string, last_updated: string, sections: array<string, string>, icons: array<string, string>, banners: array<string, string>, download_url: string}|null
 */
function novamira_fetch_update_info()
{
    $cache_key = 'novamira_update_info';
    /** @var array{name: string, version: string, author: string, author_homepage: string, homepage: string, requires: string, requires_php: string, tested: string, last_updated: string, sections: array<string, string>, icons: array<string, string>, banners: array<string, string>, download_url: string}|string|false $cached */
    $cached = get_transient($cache_key);

    if ($cached === 'error') {
        return null;
    }
    if (is_array($cached)) {
        return $cached;
    }

    $raw = novamira_request_update_info();
    if ($raw === null) {
        set_transient($cache_key, value: 'error', expiration: HOUR_IN_SECONDS);
        return null;
    }

    $data = novamira_normalize_update_response($raw);
    set_transient($cache_key, value: $data, expiration: 12 * HOUR_IN_SECONDS);
    return $data;
}

/**
 * Make the HTTP request to the license server info endpoint.
 *
 * @return array<string, mixed>|null Raw decoded response, or null on failure.
 */
function novamira_request_update_info()
{
    $url =
        'https://license.dynamic.ooo/api/novamira/info?'
        . http_build_query([
            's' => wp_parse_url(home_url(), PHP_URL_HOST),
            'v' => NOVAMIRA_VERSION,
        ]);

    $response = wp_remote_get($url, ['timeout' => 10]);

    if (is_wp_error($response) || wp_remote_retrieve_response_code($response) !== 200) {
        return null;
    }

    /** @var array<string, mixed>|null $raw */
    $raw = json_decode(wp_remote_retrieve_body($response), associative: true);

    if (!is_array($raw) || !is_string($raw['version'] ?? null) || $raw['version'] === '') {
        return null;
    }

    return $raw;
}

/**
 * Normalize the raw API response into a typed array.
 *
 * @param array<string, mixed> $raw Raw decoded API response.
 * @return array{name: string, version: string, author: string, author_homepage: string, homepage: string, requires: string, requires_php: string, tested: string, last_updated: string, sections: array<string, string>, icons: array<string, string>, banners: array<string, string>, download_url: string}
 */
function novamira_normalize_update_response($raw)
{
    /** @var array<string, string> $sections */
    $sections = is_array($raw['sections'] ?? null) ? $raw['sections'] : [];
    /** @var array<string, string> $icons */
    $icons = is_array($raw['icons'] ?? null) ? $raw['icons'] : [];
    /** @var array<string, string> $banners */
    $banners = is_array($raw['banners'] ?? null) ? $raw['banners'] : [];

    return [
        'name' => (string) ($raw['name'] ?? 'Novamira'),
        'version' => (string) $raw['version'],
        'author' => (string) ($raw['author'] ?? ''),
        'author_homepage' => (string) ($raw['author_homepage'] ?? ''),
        'homepage' => (string) ($raw['homepage'] ?? ''),
        'requires' => (string) ($raw['requires'] ?? ''),
        'requires_php' => (string) ($raw['requires_php'] ?? ''),
        'tested' => (string) ($raw['tested'] ?? ''),
        'last_updated' => (string) ($raw['last_updated'] ?? ''),
        'sections' => $sections,
        'icons' => $icons,
        'banners' => $banners,
        'download_url' => (string) ($raw['download_url'] ?? ''),
    ];
}
