<?php

declare(strict_types=1);

namespace FleekDash\API;

class MenuDiagnosticService
{
    private const DATE_FORMAT_MYSQL = 'Y-m-d H:i:s';

    /** @return array<string, mixed> */
    public function buildDiagnostic(int $userId): array
    {
        $diagnostic = [
            'timestamp' => \current_time('mysql'),
            'user_id' => $userId,
            'is_rest' => \defined('REST_REQUEST') && REST_REQUEST,
            'did_action_admin_menu' => \did_action('admin_menu'),
            'did_action__admin_menu' => \did_action('_admin_menu'),
        ];

        $diagnostic['snapshot'] = $this->buildSnapshotDiagnostic($userId);
        $diagnostic['globals'] = $this->buildGlobalsDiagnostic();
        $diagnostic['invalidation'] = $this->buildInvalidationDiagnostic();
        $activePlugins = \get_option('active_plugins', []);
        $diagnostic['active_plugins_count'] = \is_array($activePlugins) ? \count($activePlugins) : 0;

        return $diagnostic;
    }

    /** @return array<string, mixed> */
    private function buildSnapshotDiagnostic(int $userId): array
    {
        if ($userId <= 0) {
            return ['exists' => false];
        }

        $snapshotData = \get_user_meta($userId, '_fleekdash_admin_menu_snapshot_v1', true);
        $snapshotUpdatedAt = (int) \get_user_meta($userId, '_fleekdash_admin_menu_snapshot_updated_at_v1', true);
        $isStale = $snapshotUpdatedAt === -1;

        if (empty($snapshotData) || !\is_array($snapshotData)) {
            return ['exists' => false];
        }

        $snapshotMenu = $snapshotData['menu'] ?? [];
        $snapshotSubmenu = $snapshotData['submenu'] ?? [];

        return [
            'exists' => true,
            'is_stale' => $isStale,
            'updated_at' => $this->formatSnapshotUpdatedAt($snapshotUpdatedAt, $isStale),
            'menu_count' => \count($snapshotMenu),
            'submenu_parents' => \count($snapshotSubmenu),
            'items' => $this->extractMenuItemNames($snapshotMenu),
        ];
    }

    /** @return array<string, mixed> */
    private function buildGlobalsDiagnostic(): array
    {
        global $menu, $submenu;
        $menuArray = (!empty($menu) && \is_array($menu)) ? $menu : [];
        $submenuArray = (!empty($submenu) && \is_array($submenu)) ? $submenu : [];

        return [
            'menu_count' => \count($menuArray),
            'submenu_parents' => \count($submenuArray),
            'items' => $this->extractMenuItemNames($menuArray),
        ];
    }

    /** @return array<string, mixed> */
    private function buildInvalidationDiagnostic(): array
    {
        $lastInvalidation = (int) \get_option('fleekdash_invalidate_frontend_cache', 0);
        $lastCheck = (int) \get_option('fleekdash_last_cache_check', 0);

        return [
            'should_invalidate' => $lastInvalidation > $lastCheck,
            'last_invalidation' => $lastInvalidation > 0 ? \date(self::DATE_FORMAT_MYSQL, $lastInvalidation) : 'never',
            'last_check' => $lastCheck > 0 ? \date(self::DATE_FORMAT_MYSQL, $lastCheck) : 'never',
        ];
    }

    /**
     * @param array<int|string, mixed> $menu
     * @return array<int, string>
     */
    private function extractMenuItemNames(array $menu): array
    {
        $names = [];
        foreach ($menu as $pos => $item) {
            if (\is_array($item) && !empty($item[0])) {
                $cleanName = \strip_tags($item[0]);
                $names[] = "[$pos] $cleanName (slug: " . ($item[2] ?? 'none') . ")";
            }
        }
        return $names;
    }

    private function formatSnapshotUpdatedAt(int $snapshotUpdatedAt, bool $isStale): string
    {
        if ($snapshotUpdatedAt > 0) {
            return \date(self::DATE_FORMAT_MYSQL, $snapshotUpdatedAt);
        }
        return $isStale ? 'stale' : 'never';
    }
}

