<?php

namespace CleantalkSP\SpbctWP\VulnerabilityAlarm;

use CleantalkSP\SpbctWP\VulnerabilityAlarm\Dto\PluginReport;
use WP_Error;

class PscCertifiedPluginsCatalogScanner
{
    /**
     * @param array<int, mixed> $items
     * @return array<int, array<string, mixed>>
     */
    public static function filterPscCatalogItems($items)
    {
        $psc_items = [];

        foreach ($items as $item) {
            if (! is_array($item)) {
                continue;
            }

            if (($item['app_status'] ?? '') !== 'safe_psc' || empty($item['slug']) || empty($item['psc'])) {
                continue;
            }

            $psc_items[] = $item;
        }

        return $psc_items;
    }

    /**
     * @param array<int, array<string, mixed>> $items
     * @return array<string, array<string, mixed>>
     */
    public static function buildBadgesFromCatalogItems($items)
    {
        $badges = [];

        foreach ($items as $item) {
            $slug = sanitize_title((string) $item['slug']);
            $version = self::getCatalogItemVersion($item);
            $report = self::buildReportFromCatalogItem($item);

            if (empty($slug) || empty($report->psc)) {
                continue;
            }

            if (! empty($version) && ! VulnerabilityAlarmService::isModuleVersionMatchesReport($report, $version, true)) {
                continue;
            }

            $badges[$slug] = [
                'slug'            => $slug,
                'id'              => sanitize_text_field((string) ($item['id'] ?? '')),
                'psc'             => sanitize_text_field((string) $item['psc']),
                'report_object'   => $report,
                'current_version' => $version,
                'app_name'        => sanitize_text_field((string) ($item['app_name'] ?? $slug)),
                'publication_date' => sanitize_text_field((string) ($item['publication_date'] ?? '')),
            ];
        }

        return $badges;
    }

    /**
     * WP_Plugin_Install_List_Table expects plain arrays, including the nested `icons` data,
     * so the WordPress.org response is normalized before it reaches the cache or the renderer.
     *
     * @param array<string, mixed> $item
     * @return array<string, mixed>|null
     */
    public static function fetchPluginFromCatalogItem($item)
    {
        $slug = sanitize_title((string) $item['slug']);
        $plugin = plugins_api(
            'plugin_information',
            [
                'slug'   => $slug,
                'fields' => [
                    'short_description' => true,
                    'icons'             => true,
                    'banners'           => true,
                    'reviews'           => true,
                    'downloaded'        => true,
                    'active_installs'   => true,
                    'last_updated'      => true,
                    'added'             => true,
                    'homepage'          => true,
                    'rating'            => true,
                    'num_ratings'       => true,
                ],
            ]
        );

        if ($plugin instanceof WP_Error || ! is_object($plugin) || empty($plugin->slug)) {
            return self::buildPluginStubFromCatalogItem($item);
        }

        return self::toArray($plugin);
    }

    /**
     * @param object|array $plugin
     * @return array<string, mixed>
     */
    public static function toArray($plugin)
    {
        $normalized = json_decode((string) wp_json_encode($plugin), true);

        return is_array($normalized) ? $normalized : (array) $plugin;
    }

    /**
     * @param array<string, mixed> $item
     * @return array<string, mixed>|null
     */
    public static function buildPluginStubFromCatalogItem($item)
    {
        $slug = sanitize_title((string) ($item['slug'] ?? ''));

        if (empty($slug)) {
            return null;
        }

        $version = self::getCatalogItemVersion($item);
        $name = ! empty($item['app_name']) ? sanitize_text_field((string) $item['app_name']) : $slug;
        $timestamp = ! empty($item['publication_date'])
            ? strtotime((string) $item['publication_date'])
            : false;
        $last_updated = $timestamp ? gmdate('Y-m-d', $timestamp) : gmdate('Y-m-d');

        return [
            'slug'              => $slug,
            'name'              => $name,
            'version'           => $version,
            'author'            => '',
            'short_description' => $version
                ? sprintf(
                    /* translators: %s: Certified plugin version. */
                    __('CleanTalk certified release: %s.', 'security-malware-firewall'),
                    $version
                )
                : __('CleanTalk certified plugin release.', 'security-malware-firewall'),
            'icons'             => [
                'default' => 'https://s.w.org/plugins/geopattern-icon/' . rawurlencode($slug) . '.svg',
            ],
            'last_updated'      => $last_updated,
            'homepage'          => 'https://wordpress.org/plugins/' . $slug . '/',
            'download_link'     => 'https://downloads.wordpress.org/plugin/' . $slug . '.zip',
            'requires'          => false,
            'requires_php'      => false,
            'tested'            => get_bloginfo('version'),
            'rating'            => 0,
            'num_ratings'       => 0,
            'active_installs'   => 0,
            'downloaded'        => 0,
        ];
    }

    /**
     * @param array<string, mixed> $item
     * @return string
     */
    public static function getCatalogItemVersion($item)
    {
        if (! empty($item['rs_app_version_max'])) {
            return (string) $item['rs_app_version_max'];
        }

        if (! empty($item['rs_app_version_min'])) {
            return (string) $item['rs_app_version_min'];
        }

        return '';
    }

    /**
     * @param array<string, mixed> $item
     * @return PluginReport
     */
    public static function buildReportFromCatalogItem($item)
    {
        $report = new PluginReport();
        $report->slug = sanitize_title((string) ($item['slug'] ?? ''));
        $report->app_status = 'safe_psc';
        $report->psc = (string) ($item['psc'] ?? '');
        $report->id = isset($item['id']) ? (string) $item['id'] : '';
        $report->rs_app_version_min = isset($item['rs_app_version_min']) ? (string) $item['rs_app_version_min'] : '';
        $report->rs_app_version_max = isset($item['rs_app_version_max']) ? (string) $item['rs_app_version_max'] : '';

        return $report;
    }
}
