<?php
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

if ( ! function_exists( 'elementsell_get_update_server_public_base_url' ) ) {
    require_once __DIR__ . '/publish-endpoint-sync.php';
}

add_filter( 'pre_set_site_transient_update_plugins', 'elementsell_pre_set_update_plugins_transient' );
add_filter( 'plugins_api', 'elementsell_plugins_api_update_info', 10, 3 );
add_filter( 'all_plugins', 'elementsell_ensure_plugins_list_version' );
add_filter( 'plugin_row_meta', 'elementsell_plugin_row_meta_version', 10, 2 );
add_action( 'load-plugins.php', 'elementsell_updater_maybe_refresh_on_admin_load' );
add_action( 'load-update-core.php', 'elementsell_updater_maybe_refresh_on_admin_load' );
add_action( 'admin_notices', 'elementsell_updater_plugins_page_update_notice' );
add_action( 'plugins_loaded', 'elementsell_register_update_uri_host_filters', 0 );

elementsell_register_update_uri_host_filters();

/**
 * Update URI z hlavičky plugin.php (WP 5.8+).
 *
 * @return string
 */
function elementsell_get_update_uri_from_header() {
    static $update_uri = null;

    if ( is_string( $update_uri ) ) {
        return $update_uri;
    }

    $update_uri = '';

    if ( defined( 'PF_PLUGIN_FILE' ) && is_readable( PF_PLUGIN_FILE ) && function_exists( 'get_file_data' ) ) {
        $header = get_file_data(
            PF_PLUGIN_FILE,
            [
                'UpdateURI' => 'Update URI',
            ],
            'plugin'
        );
        $update_uri = isset( $header['UpdateURI'] ) ? trim( (string) $header['UpdateURI'] ) : '';
    }

    if ( $update_uri === '' ) {
        $update_uri = 'https://elementsell.cz/elementsell-update.json';
    }

    return $update_uri;
}

/**
 * Hostname z hlavičky Update URI (WP 5.8+).
 *
 * @return string
 */
function elementsell_get_update_uri_hostname() {
    $hostnames = elementsell_get_update_uri_hostnames();

    return ! empty( $hostnames ) ? (string) $hostnames[0] : 'elementsell.cz';
}

/**
 * Hostnames pro hook update_plugins_{hostname} — stejný tvar jako wp_parse_url() ve WP jádře.
 *
 * @return string[]
 */
function elementsell_get_update_uri_hostnames() {
    static $hostnames = null;

    if ( is_array( $hostnames ) ) {
        return $hostnames;
    }

    $update_uri = elementsell_get_update_uri_from_header();
    $primary    = 'elementsell.cz';

    if ( $update_uri !== '' && function_exists( 'wp_parse_url' ) ) {
        $parsed_host = (string) wp_parse_url( $update_uri, PHP_URL_HOST );

        if ( $parsed_host !== '' ) {
            $primary = $parsed_host;
        }
    }

    $expanded = [ $primary, strtolower( $primary ) ];
    $lower    = strtolower( $primary );

    if ( 0 === strpos( $lower, 'www.' ) ) {
        $expanded[] = substr( $lower, 4 );
    } else {
        $expanded[] = 'www.' . $lower;
    }

    $hostnames = array_values( array_unique( array_filter( $expanded ) ) );

    return $hostnames;
}

/**
 * Registruje update_plugins_{hostname} hook pro každý hostname z Update URI.
 *
 * @return void
 */
function elementsell_register_update_uri_host_filters() {
    static $registered_hooks = [];

    foreach ( elementsell_get_update_uri_hostnames() as $hostname ) {
        if ( $hostname === '' || isset( $registered_hooks[ $hostname ] ) ) {
            continue;
        }

        add_filter( 'update_plugins_' . $hostname, 'elementsell_filter_update_plugins_host', 10, 4 );
        $registered_hooks[ $hostname ] = true;
    }
}

/**
 * @return string
 */
function elementsell_get_plugin_basename() {
    if ( ! defined( 'PF_PLUGIN_FILE' ) ) {
        return '';
    }

    return plugin_basename( PF_PLUGIN_FILE );
}

/**
 * Očekávaný název složky pluginu v ZIP i wp-content/plugins/ (ElementSell).
 * Manifest slug zůstává lowercase elementsell — to je jen identifikátor updateru, ne název složky.
 *
 * @return string
 */
function elementsell_get_release_zip_folder_name() {
    return 'ElementSell';
}

/**
 * @param string $plugin_file
 * @return bool
 */
function elementsell_is_elementsell_plugin_file( $plugin_file ) {
    $plugin_file = (string) $plugin_file;

    if ( $plugin_file === '' ) {
        return false;
    }

    if ( defined( 'PF_PLUGIN_FILE' ) && $plugin_file === plugin_basename( PF_PLUGIN_FILE ) ) {
        return true;
    }

    $folder = preg_quote( elementsell_get_release_zip_folder_name(), '#' );

    return (bool) preg_match( '#(^|/)' . $folder . '/plugin\.php$#i', $plugin_file );
}

/**
 * Veřejná URL manifestu aktualizací a vypuštění verze na elementsell.cz.
 *
 * @return string
 */
function elementsell_get_update_json_url() {
    $update_uri = elementsell_get_update_uri_from_header();

    if ( $update_uri !== '' && preg_match( '/\.json(\?.*)?$/i', $update_uri ) ) {
        return (string) apply_filters( 'elementsell_update_json_url', $update_uri );
    }

    $base = rtrim( elementsell_get_update_server_public_base_url(), '/' );

    return (string) apply_filters(
        'elementsell_update_json_url',
        $base . '/' . elementsell_get_update_manifest_filename()
    );
}

/**
 * Opraví poškozenou hlavičku Version (např. Version: $13.2.14).
 *
 * @param string $content
 * @return string
 */
function elementsell_repair_plugin_version_header_content( $content ) {
    $content = (string) $content;

    if ( function_exists( 'elementsell_repair_plugin_version_headers_in_content' ) ) {
        return elementsell_repair_plugin_version_headers_in_content( $content );
    }

    $content = preg_replace(
        '/^(\s*(?:\*\s*)?Version:\s*)\$1(\d+\.\d+\.\d+)/mi',
        '${1}${2}',
        $content
    );

    return is_string( $content ) ? $content : '';
}

/**
 * @param string $plugin_path
 * @return string
 */
function elementsell_read_plugin_version_from_path( $plugin_path ) {
    if ( ! is_string( $plugin_path ) || $plugin_path === '' || ! is_readable( $plugin_path ) ) {
        return defined( 'PF_VERSION' ) ? (string) PF_VERSION : '';
    }

    if ( function_exists( 'get_file_data' ) ) {
        $data = get_file_data(
            $plugin_path,
            [
                'Version' => 'Version',
            ],
            'plugin'
        );

        if ( ! empty( $data['Version'] ) ) {
            return (string) $data['Version'];
        }
    }

    $content = elementsell_repair_plugin_version_header_content( (string) file_get_contents( $plugin_path ) );

    if ( preg_match( '/^\s*\*\s*Version:\s*([0-9]+\.[0-9]+\.[0-9]+)/m', $content, $matches ) ) {
        return (string) $matches[1];
    }

    if ( preg_match( '/Version:\s*(\d+\.\d+\.\d+)/i', $content, $matches ) ) {
        return (string) $matches[1];
    }

    return defined( 'PF_VERSION' ) ? (string) PF_VERSION : '';
}

/**
 * @return string
 */
function elementsell_get_installed_plugin_version() {
    $plugin_file = defined( 'PF_PLUGIN_FILE' ) ? PF_PLUGIN_FILE : '';

    if ( $plugin_file !== '' ) {
        $version = elementsell_read_plugin_version_from_path( $plugin_file );

        if ( $version !== '' ) {
            return $version;
        }
    }

    return defined( 'PF_VERSION' ) ? (string) PF_VERSION : '0.0.0';
}

/**
 * Verze ElementSell ze seznamu pluginů WordPress (all_plugins / get_plugins).
 *
 * @param string|null $plugin_file Volitelně plugin basename; jinak aktivní ElementSell.
 * @return string
 */
function elementsell_get_plugins_list_local_version( $plugin_file = null ) {
    if ( null === $plugin_file || $plugin_file === '' ) {
        $plugin_file = elementsell_get_plugin_basename();
    } else {
        $plugin_file = (string) $plugin_file;
    }

    if ( $plugin_file === '' ) {
        return elementsell_get_installed_plugin_version();
    }

    if ( ! function_exists( 'get_plugins' ) ) {
        require_once ABSPATH . 'wp-admin/includes/plugin.php';
    }

    if ( function_exists( 'get_plugins' ) ) {
        $plugins = get_plugins();

        if ( isset( $plugins[ $plugin_file ] ) && is_array( $plugins[ $plugin_file ] ) ) {
            $listed = isset( $plugins[ $plugin_file ]['Version'] ) ? trim( (string) $plugins[ $plugin_file ]['Version'] ) : '';

            if ( $listed !== '' ) {
                return $listed;
            }
        }
    }

    return elementsell_get_installed_plugin_version();
}

/**
 * @param string $local
 * @param string $remote
 * @return bool
 */
function elementsell_remote_version_is_newer_than_local( $local, $remote ) {
    $local  = trim( (string) $local );
    $remote = trim( (string) $remote );

    if ( $local === '' || $remote === '' ) {
        return false;
    }

    return version_compare( $local, $remote, '<' );
}

/**
 * @param array<string, mixed> $remote
 * @param string|null          $local_version Volitelně verze z WordPress seznamu pluginů.
 * @return array<string, mixed>|false
 */
function elementsell_build_plugin_update_offer( $remote, $local_version = null ) {
    if ( ! is_array( $remote ) || empty( $remote['version'] ) || empty( $remote['download_url'] ) ) {
        return false;
    }

    $local = null !== $local_version && $local_version !== ''
        ? trim( (string) $local_version )
        : elementsell_get_installed_plugin_version();

    $remote_version = trim( (string) $remote['version'] );

    if ( ! elementsell_remote_version_is_newer_than_local( $local, $remote_version ) ) {
        return false;
    }

    $update_uri = elementsell_get_update_uri_from_header();

    return [
        'id'           => $update_uri,
        'slug'         => 'elementsell',
        'version'      => $remote_version,
        'url'          => isset( $remote['homepage'] ) ? (string) $remote['homepage'] : 'https://elementsell.cz',
        'package'      => (string) $remote['download_url'],
        'tested'       => isset( $remote['tested'] ) ? (string) $remote['tested'] : '',
        'requires'     => isset( $remote['requires'] ) ? (string) $remote['requires'] : '',
        'requires_php' => isset( $remote['requires_php'] ) ? (string) $remote['requires_php'] : '',
    ];
}

/**
 * @param array<string, mixed> $offer
 * @param string               $plugin_file
 * @return array<string, mixed>
 */
function elementsell_finalize_plugin_update_offer( $offer, $plugin_file ) {
    return array_merge(
        $offer,
        [
            'plugin'      => $plugin_file,
            'new_version' => (string) $offer['version'],
        ]
    );
}

/**
 * Doplní verzi v seznamu Pluginy, pokud ji WordPress z hlavičky nepřečte.
 *
 * @param array<string, array<string, mixed>> $plugins
 * @return array<string, array<string, mixed>>
 */
function elementsell_ensure_plugins_list_version( $plugins ) {
    if ( ! is_array( $plugins ) ) {
        return $plugins;
    }

    foreach ( $plugins as $plugin_file => $plugin_data ) {
        if ( ! is_array( $plugin_data ) ) {
            continue;
        }

        if ( ! elementsell_is_elementsell_plugin_file( $plugin_file ) && 'ElementSell' !== ( $plugin_data['Name'] ?? '' ) ) {
            continue;
        }

        $version = elementsell_read_plugin_version_from_path( WP_PLUGIN_DIR . '/' . $plugin_file );

        if ( $version === '' ) {
            continue;
        }

        $listed = isset( $plugin_data['Version'] ) ? (string) $plugin_data['Version'] : '';

        if ( $listed === '' || version_compare( $listed, $version, '!=' ) ) {
            $plugins[ $plugin_file ]['Version'] = $version;
        }
    }

    return $plugins;
}

/**
 * Záložní řádek verze pod popisem pluginu (starší instalace / ruční upload).
 *
 * @param array<int, string> $plugin_meta
 * @param string             $plugin_file
 * @return array<int, string>
 */
function elementsell_plugin_row_meta_version( $plugin_meta, $plugin_file ) {
    if ( ! is_array( $plugin_meta ) ) {
        $plugin_meta = [];
    }

    if ( ! elementsell_is_elementsell_plugin_file( $plugin_file ) ) {
        return $plugin_meta;
    }

    foreach ( $plugin_meta as $meta ) {
        if ( is_string( $meta ) && ( false !== stripos( $meta, 'verze' ) || false !== stripos( $meta, 'version' ) ) ) {
            return $plugin_meta;
        }
    }

    $version = elementsell_read_plugin_version_from_path( WP_PLUGIN_DIR . '/' . $plugin_file );

    if ( $version === '' ) {
        return $plugin_meta;
    }

    $plugin_meta[] = sprintf(
        '<span class="elementsell-plugin-version">%s</span>',
        esc_html( sprintf( 'Verze %s', $version ) )
    );

    return $plugin_meta;
}

/**
 * Interval mezi automatickými kontrolami aktualizací (sekundy).
 *
 * @return int
 */
function elementsell_get_remote_update_check_interval() {
    return (int) apply_filters( 'elementsell_remote_update_check_interval', 30 * MINUTE_IN_SECONDS );
}

/**
 * TTL cache úspěšně staženého manifestu (sekundy).
 *
 * @return int
 */
function elementsell_get_remote_update_cache_ttl() {
    return (int) apply_filters( 'elementsell_remote_update_cache_ttl', 30 * MINUTE_IN_SECONDS );
}

/**
 * @return int Unix timestamp poslední kontroly manifestu, nebo 0.
 */
function elementsell_get_remote_update_last_checked_at() {
    $last_check = get_transient( 'elementsell_remote_update_last_check' );

    if ( ! is_array( $last_check ) || empty( $last_check['checked_at'] ) ) {
        return 0;
    }

    return (int) $last_check['checked_at'];
}

/**
 * Je cache manifestu starší než povolený interval?
 *
 * @return bool
 */
function elementsell_is_remote_update_info_stale() {
    $checked_at = elementsell_get_remote_update_last_checked_at();

    if ( $checked_at <= 0 ) {
        return true;
    }

    return ( time() - $checked_at ) >= elementsell_get_remote_update_check_interval();
}

/**
 * @param array<string, mixed>|null $data
 * @param string                    $error
 * @param int                       $http_code
 * @param string                    $manifest_url
 * @return void
 */
function elementsell_store_remote_update_check_result( $data, $error, $http_code, $manifest_url ) {
    set_transient(
        'elementsell_remote_update_last_check',
        [
            'checked_at'    => time(),
            'manifest_url'  => $manifest_url,
            'http_code'     => $http_code,
            'error'         => $error,
            'remote_version'=> is_array( $data ) && ! empty( $data['version'] ) ? (string) $data['version'] : '',
            'local_version' => elementsell_get_installed_plugin_version(),
        ],
        2 * DAY_IN_SECONDS
    );
}

/**
 * @param string $manifest_url
 * @param array<string, mixed> $request_args
 * @return array{data: array<string, mixed>|null, http_code: int, error: string}
 */
function elementsell_fetch_update_manifest_http( $manifest_url, $request_args = [] ) {
    $manifest_url = (string) $manifest_url;

    if ( $manifest_url === '' ) {
        return [
            'data'      => null,
            'http_code' => 0,
            'error'     => 'Prázdná URL manifestu.',
        ];
    }

    $defaults = [
        'timeout'    => 15,
        'sslverify'  => (bool) apply_filters( 'elementsell_updater_sslverify', true ),
        'headers'    => [
            'Accept' => 'application/json',
        ],
        'user-agent' => 'ElementSell-Updater/' . elementsell_get_installed_plugin_version(),
    ];

    $request_args = array_merge( $defaults, is_array( $request_args ) ? $request_args : [] );

    $last_error = '';
    $last_code  = 0;

    if ( function_exists( 'wp_remote_get' ) ) {
        $response = wp_remote_get( $manifest_url, $request_args );

        if ( ! is_wp_error( $response ) ) {
            $last_code = (int) wp_remote_retrieve_response_code( $response );

            if ( 200 === $last_code ) {
                $data = json_decode( (string) wp_remote_retrieve_body( $response ), true );

                if ( is_array( $data ) ) {
                    return [
                        'data'      => $data,
                        'http_code' => 200,
                        'error'     => '',
                    ];
                }

                $last_error = 'Manifest není platný JSON.';
            } else {
                $last_error = 'Server vrátil HTTP ' . $last_code;
            }
        } else {
            $last_error = $response->get_error_message();
        }
    }

    if ( function_exists( 'curl_init' ) ) {
        $curl = curl_init( $manifest_url );

        if ( false !== $curl ) {
            $verify_ssl = ! empty( $request_args['sslverify'] );

            curl_setopt_array(
                $curl,
                [
                    CURLOPT_RETURNTRANSFER => true,
                    CURLOPT_FOLLOWLOCATION => true,
                    CURLOPT_CONNECTTIMEOUT => 10,
                    CURLOPT_TIMEOUT        => (int) $request_args['timeout'],
                    CURLOPT_HTTPHEADER     => [
                        'Accept: application/json',
                        'User-Agent: ' . $request_args['user-agent'],
                    ],
                    CURLOPT_SSL_VERIFYPEER => $verify_ssl,
                    CURLOPT_SSL_VERIFYHOST => $verify_ssl ? 2 : 0,
                ]
            );

            $body       = curl_exec( $curl );
            $last_code  = (int) curl_getinfo( $curl, CURLINFO_HTTP_CODE );
            $curl_error = curl_error( $curl );
            curl_close( $curl );

            if ( false !== $body && 200 === $last_code ) {
                $data = json_decode( (string) $body, true );

                if ( is_array( $data ) ) {
                    return [
                        'data'      => $data,
                        'http_code' => 200,
                        'error'     => '',
                    ];
                }

                $last_error = 'Manifest není platný JSON (cURL).';
            } elseif ( $curl_error !== '' ) {
                $last_error = $curl_error;
            }
        }
    }

    if ( ini_get( 'allow_url_fopen' ) ) {
        $verify_ssl = ! empty( $request_args['sslverify'] );
        $context    = stream_context_create(
            [
                'http' => [
                    'timeout' => (int) $request_args['timeout'],
                    'header'  => "Accept: application/json\r\nUser-Agent: {$request_args['user-agent']}\r\n",
                ],
                'ssl'  => [
                    'verify_peer'      => $verify_ssl,
                    'verify_peer_name' => $verify_ssl,
                ],
            ]
        );

        $body = @file_get_contents( $manifest_url, false, $context );

        if ( is_string( $body ) && $body !== '' ) {
            $data = json_decode( $body, true );

            if ( is_array( $data ) ) {
                return [
                    'data'      => $data,
                    'http_code' => 200,
                    'error'     => '',
                ];
            }

            $last_error = 'Manifest není platný JSON (fopen).';
        }
    }

    return [
        'data'      => null,
        'http_code' => $last_code,
        'error'     => $last_error !== '' ? $last_error : 'Manifest se nepodařilo stáhnout.',
    ];
}

/**
 * @param bool $force
 * @return array<string, mixed>|null
 */
function elementsell_get_remote_update_info( $force = false ) {
    $cache_ttl = elementsell_get_remote_update_cache_ttl();
    $cached    = get_transient( 'elementsell_remote_update_info' );
    $cached    = is_array( $cached ) ? $cached : null;

    if ( ! $force && null !== $cached ) {
        $local_version  = elementsell_get_installed_plugin_version();
        $cached_version = ! empty( $cached['version'] ) ? trim( (string) $cached['version'] ) : '';

        // Dostupná aktualizace — vždy použij cache (manifest je novější než instalace).
        if ( $cached_version !== '' && elementsell_remote_version_is_newer_than_local( $local_version, $cached_version ) ) {
            return $cached;
        }

        // Lokální verze je stejná nebo vyšší než cache — může existovat novější release na serveru.
        if ( $cached_version !== '' && ! elementsell_remote_version_is_newer_than_local( $cached_version, $local_version ) ) {
            // Nevracej zastaralý manifest; vždy zkus čerstvý HTTP dotaz.
        } elseif ( ! elementsell_is_remote_update_info_stale() ) {
            return $cached;
        }
    }

    $manifest_url = elementsell_get_update_json_url();

    if ( ! $force && function_exists( 'elementsell_read_local_update_manifest' ) ) {
        $local = elementsell_read_local_update_manifest();

        if ( is_array( $local ) ) {
            elementsell_store_remote_update_check_result( $local, '', 200, $manifest_url );
            set_transient( 'elementsell_remote_update_info', $local, $cache_ttl );

            return $local;
        }
    }

    $fetch = elementsell_fetch_update_manifest_http( $manifest_url );
    $data  = is_array( $fetch['data'] ) ? $fetch['data'] : null;

    if ( ! is_array( $data ) || empty( $data['version'] ) || empty( $data['download_url'] ) ) {
        if (
            function_exists( 'elementsell_read_local_update_manifest' )
            && function_exists( 'elementsell_should_sync_publish_endpoint' )
            && elementsell_should_sync_publish_endpoint()
        ) {
            $local = elementsell_read_local_update_manifest();

            if ( is_array( $local ) ) {
                elementsell_store_remote_update_check_result( $local, '', 200, $manifest_url );
                set_transient( 'elementsell_remote_update_info', $local, $cache_ttl );

                return $local;
            }
        }

        if (
            null !== $cached
            && ! empty( $cached['version'] )
            && ! empty( $cached['download_url'] )
            && elementsell_remote_version_is_newer_than_local(
                elementsell_get_installed_plugin_version(),
                (string) $cached['version']
            )
        ) {
            elementsell_store_remote_update_check_result(
                $cached,
                (string) $fetch['error'],
                (int) $fetch['http_code'],
                $manifest_url
            );

            return $cached;
        }

        elementsell_store_remote_update_check_result(
            null,
            (string) $fetch['error'],
            (int) $fetch['http_code'],
            $manifest_url
        );

        return null;
    }

    elementsell_store_remote_update_check_result( $data, '', (int) $fetch['http_code'], $manifest_url );
    set_transient( 'elementsell_remote_update_info', $data, $cache_ttl );

    return $data;
}

/**
 * WP 5.8+ — Update URI hostname hook (primární cesta pro vlastní aktualizace).
 *
 * @param array<string, mixed>|false $update
 * @param array<string, mixed>       $plugin_data
 * @param string                     $plugin_file
 * @param array<int, string>         $locales
 * @return array<string, mixed>|false
 */
function elementsell_filter_update_plugins_host( $update, $plugin_data, $plugin_file, $locales ) {
    unset( $locales );

    if ( ! elementsell_is_elementsell_plugin_file( $plugin_file ) ) {
        return $update;
    }

    $local_version = is_array( $plugin_data ) && ! empty( $plugin_data['Version'] )
        ? trim( (string) $plugin_data['Version'] )
        : elementsell_get_plugins_list_local_version( $plugin_file );

    $remote = elementsell_get_remote_update_info( true );
    $offer  = elementsell_build_plugin_update_offer( is_array( $remote ) ? $remote : [], $local_version );

    if ( false !== $offer ) {
        return elementsell_finalize_plugin_update_offer( $offer, $plugin_file );
    }

    if ( is_array( $remote ) && ! empty( $remote['version'] ) ) {
        return false;
    }

    return $update;
}

/**
 * @param object|false $transient
 * @return object
 */
function elementsell_pre_set_update_plugins_transient( $transient ) {
    if ( ! is_object( $transient ) ) {
        $transient = new stdClass();
    }

    $plugin_file = elementsell_get_plugin_basename();

    if ( $plugin_file === '' ) {
        return $transient;
    }

    if ( ! isset( $transient->response ) || ! is_array( $transient->response ) ) {
        $transient->response = [];
    }

    if ( ! isset( $transient->no_update ) || ! is_array( $transient->no_update ) ) {
        $transient->no_update = [];
    }

    $local_version = elementsell_get_plugins_list_local_version( $plugin_file );

    $remote = elementsell_get_remote_update_info( true );
    $offer  = elementsell_build_plugin_update_offer( is_array( $remote ) ? $remote : [], $local_version );

    if ( false === $offer ) {
        unset( $transient->response[ $plugin_file ] );

        if ( is_array( $remote ) && ! empty( $remote['version'] ) ) {
            $transient->no_update[ $plugin_file ] = (object) [
                'slug'        => 'elementsell',
                'plugin'      => $plugin_file,
                'new_version' => (string) $remote['version'],
                'url'         => isset( $remote['homepage'] ) ? (string) $remote['homepage'] : 'https://elementsell.cz',
            ];
        } else {
            unset( $transient->no_update[ $plugin_file ] );
        }

        return $transient;
    }

    unset( $transient->no_update[ $plugin_file ] );

    $transient->response[ $plugin_file ] = (object) elementsell_finalize_plugin_update_offer( $offer, $plugin_file );

    return $transient;
}

/**
 * Stejná logika jako „Zkontrolovat aktualizace nyní“ v diagnostice.
 *
 * @return void
 */
function elementsell_updater_force_refresh_updates() {
    elementsell_clear_update_info_cache();

    if ( ! function_exists( 'wp_update_plugins' ) ) {
        require_once ABSPATH . 'wp-admin/includes/update.php';
    }

    if ( function_exists( 'wp_update_plugins' ) ) {
        wp_update_plugins();
    }
}

/**
 * Při návštěvě Pluginy / Aktualizace vymaže cache a spustí wp_update_plugins().
 * Opakuje se nejvýše jednou za minutu (kromě ?force-check).
 *
 * @return void
 */
function elementsell_updater_maybe_refresh_on_admin_load() {
    if ( ! is_admin() || wp_doing_ajax() || wp_doing_cron() ) {
        return;
    }

    if ( ! current_user_can( 'update_plugins' ) ) {
        return;
    }

    if ( ! empty( $_GET['force-check'] ) ) {
        elementsell_updater_force_refresh_updates();

        return;
    }

    if ( get_transient( 'elementsell_updater_refresh_lock' ) ) {
        return;
    }

    set_transient( 'elementsell_updater_refresh_lock', 1, MINUTE_IN_SECONDS );

    elementsell_updater_force_refresh_updates();
}

/**
 * Admin notice na stránce Pluginy, pokud je k dispozici aktualizace ElementSell.
 *
 * @return void
 */
function elementsell_updater_plugins_page_update_notice() {
    if ( ! function_exists( 'get_current_screen' ) ) {
        return;
    }

    $screen = get_current_screen();

    if ( ! $screen || 'plugins' !== $screen->id || ! current_user_can( 'update_plugins' ) ) {
        return;
    }

    $plugin_file = elementsell_get_plugin_basename();

    if ( $plugin_file === '' ) {
        return;
    }

    $updates = get_site_transient( 'update_plugins' );

    if ( ! is_object( $updates ) || empty( $updates->response[ $plugin_file ] ) ) {
        return;
    }

    $update      = $updates->response[ $plugin_file ];
    $new_version = isset( $update->new_version ) ? trim( (string) $update->new_version ) : '';

    if ( $new_version === '' ) {
        return;
    }

    $update_url = wp_nonce_url(
        self_admin_url( 'update.php?action=upgrade-plugin&plugin=' . rawurlencode( $plugin_file ) ),
        'upgrade-plugin_' . $plugin_file
    );

    echo '<div class="notice notice-warning"><p>';
    printf(
        /* translators: 1: version number, 2: update link */
        esc_html__( 'Je k dispozici nová verze ElementSell %1$s. %2$s', 'platebni-formular' ),
        esc_html( $new_version ),
        '<a href="' . esc_url( $update_url ) . '">' . esc_html__( 'Aktualizovat nyní', 'platebni-formular' ) . '</a>'
    );
    echo '</p></div>';
}

/**
 * @param false|object|array $result
 * @param string           $action
 * @param object           $args
 * @return false|object
 */
function elementsell_plugins_api_update_info( $result, $action, $args ) {
    if ( $action !== 'plugin_information' || ! isset( $args->slug ) ) {
        return $result;
    }

    $plugin_slug = dirname( elementsell_get_plugin_basename() );
    $remote_slug = 'elementsell';

    if ( ! in_array( (string) $args->slug, [ $plugin_slug, $remote_slug ], true ) ) {
        return $result;
    }

    $remote = elementsell_get_remote_update_info();

    if ( ! $remote ) {
        return $result;
    }

    return (object) [
        'name'           => isset( $remote['name'] ) ? (string) $remote['name'] : 'ElementSell',
        'slug'           => $remote_slug,
        'version'        => (string) $remote['version'],
        'author'         => isset( $remote['author'] ) ? (string) $remote['author'] : 'ElementSell',
        'author_profile' => isset( $remote['author_profile'] ) ? (string) $remote['author_profile'] : 'https://elementsell.cz',
        'homepage'       => isset( $remote['homepage'] ) ? (string) $remote['homepage'] : 'https://elementsell.cz',
        'requires'       => isset( $remote['requires'] ) ? (string) $remote['requires'] : '5.8',
        'tested'         => isset( $remote['tested'] ) ? (string) $remote['tested'] : '',
        'requires_php'   => isset( $remote['requires_php'] ) ? (string) $remote['requires_php'] : '7.4',
        'download_link'  => (string) $remote['download_url'],
        'sections'       => isset( $remote['sections'] ) && is_array( $remote['sections'] ) ? $remote['sections'] : [],
    ];
}

/**
 * Diagnostika updateru pro admin.
 *
 * @param bool $force_remote
 * @return array<string, mixed>
 */
function elementsell_get_plugin_update_diagnostics( $force_remote = true ) {
    $plugin_file  = elementsell_get_plugin_basename();
    $plugin_slug  = $plugin_file !== '' ? dirname( $plugin_file ) : '';
    $manifest_url = elementsell_get_update_json_url();
    $local        = elementsell_get_installed_plugin_version();
    $listed_local = elementsell_get_plugins_list_local_version( $plugin_file );
    $pf_constant  = defined( 'PF_VERSION' ) ? (string) PF_VERSION : '';
    $remote       = elementsell_get_remote_update_info( $force_remote );
    $remote_ver   = is_array( $remote ) && ! empty( $remote['version'] ) ? (string) $remote['version'] : '';
    $last_check   = get_transient( 'elementsell_remote_update_last_check' );
    $offer        = elementsell_build_plugin_update_offer( is_array( $remote ) ? $remote : [], $listed_local );
    $offer_disk   = elementsell_build_plugin_update_offer( is_array( $remote ) ? $remote : [], $local );

    $hooks = [
        'pre_set_site_transient_update_plugins' => has_filter( 'pre_set_site_transient_update_plugins', 'elementsell_pre_set_update_plugins_transient' ),
    ];

    foreach ( elementsell_get_update_uri_hostnames() as $hostname ) {
        $hooks[ 'update_plugins_' . $hostname ] = has_filter( 'update_plugins_' . $hostname, 'elementsell_filter_update_plugins_host' );
    }

    $site_transient = get_site_transient( 'update_plugins' );
    $in_response    = false;

    if ( is_object( $site_transient ) && isset( $site_transient->response ) && is_array( $site_transient->response ) && $plugin_file !== '' ) {
        $in_response = isset( $site_transient->response[ $plugin_file ] );
    }

    return [
        'local_version'        => $local,
        'listed_local_version' => $listed_local,
        'pf_version_constant'  => $pf_constant,
        'pf_version_matches'   => $pf_constant === '' || $pf_constant === $local,
        'remote_version'       => $remote_ver,
        'remote_is_newer'      => $remote_ver !== '' && elementsell_remote_version_is_newer_than_local( $listed_local, $remote_ver ),
        'manifest_url'         => $manifest_url,
        'plugin_basename'      => $plugin_file,
        'plugin_slug'          => $plugin_slug,
        'expected_folder'      => elementsell_get_release_zip_folder_name(),
        'folder_ok'            => strtolower( (string) $plugin_slug ) === strtolower( elementsell_get_release_zip_folder_name() ),
        'http_status'          => is_array( $last_check ) && isset( $last_check['http_code'] ) ? (int) $last_check['http_code'] : 0,
        'last_error'           => is_array( $last_check ) && ! empty( $last_check['error'] ) ? (string) $last_check['error'] : '',
        'checked_at'           => is_array( $last_check ) && ! empty( $last_check['checked_at'] ) ? (int) $last_check['checked_at'] : 0,
        'would_offer_update'   => false !== $offer,
        'would_offer_from_disk'=> false !== $offer_disk,
        'in_update_transient'  => $in_response,
        'hooks_registered'     => $hooks,
        'last_check'           => is_array( $last_check ) ? $last_check : [],
        'download_url'         => is_array( $remote ) && ! empty( $remote['download_url'] ) ? (string) $remote['download_url'] : '',
        'update_uri'           => elementsell_get_update_uri_from_header(),
        'update_uri_hostname'  => elementsell_get_update_uri_hostname(),
        'update_uri_hostnames' => elementsell_get_update_uri_hostnames(),
    ];
}

/**
 * @return void
 */
function elementsell_clear_update_info_cache() {
    delete_transient( 'elementsell_remote_update_info' );
    delete_transient( 'elementsell_remote_update_last_check' );
    delete_site_transient( 'update_plugins' );
}
