<?php

namespace WPSN\Modules\ImportExport;

defined('ABSPATH') || exit;

final class ImportAssistRepository
{
    public const OPTION_NAME = 'wpsn_import_assist_reports';
    private const MAX_ITEMS = 20;

    /**
     * @return array<int,array<string,mixed>>
     */
    public function all(int $limit = self::MAX_ITEMS): array
    {
        $rows = get_option(self::OPTION_NAME, []);
        if (!is_array($rows)) {
            return [];
        }

        $out = [];
        foreach ($rows as $row) {
            if (!is_array($row)) {
                continue;
            }
            $row['assist_id'] = $this->identify($row);
            $out[] = $row;
        }

        if ($limit > 0 && count($out) > $limit) {
            $out = array_slice($out, 0, $limit);
        }

        return $out;
    }

    /**
     * @return array<string,mixed>|null
     */
    public function find(string $assistId): ?array
    {
        $assistId = strtolower(trim($assistId));
        $assistId = preg_replace('/[^a-z0-9_-]/', '', $assistId) ?? '';
        if ($assistId === '') {
            return null;
        }

        foreach ($this->all(0) as $row) {
            if (!is_array($row)) {
                continue;
            }
            if ($this->identify($row) === $assistId) {
                return $row;
            }
        }

        return null;
    }

    /**
     * @param array<string,mixed> $entry
     */
    public function push(array $entry): void
    {
        $rows = $this->all();

        $entry['assist_id'] = $this->identify($entry + ['created_at' => gmdate('c')]);
        $entry['stored_at'] = gmdate('c');
        array_unshift($rows, $entry);

        if (count($rows) > self::MAX_ITEMS) {
            $rows = array_slice($rows, 0, self::MAX_ITEMS);
        }

        update_option(self::OPTION_NAME, array_values($rows), false);
    }

    public function clear(): void
    {
        delete_option(self::OPTION_NAME);
    }

    /**
     * @param array<string,mixed> $entry
     */
    public function identify(array $entry): string
    {
        if (!empty($entry['assist_id']) && is_scalar($entry['assist_id'])) {
            $id = strtolower(trim((string) $entry['assist_id']));
            $id = preg_replace('/[^a-z0-9_-]/', '', $id) ?? '';
            if ($id !== '') {
                return $id;
            }
        }

        $seed = [];
        foreach (['kind', 'source', 'title', 'created_at'] as $key) {
            if (!empty($entry[$key]) && is_scalar($entry[$key])) {
                $seed[] = (string) $entry[$key];
            }
        }

        $meta = isset($entry['meta']) && is_array($entry['meta']) ? $entry['meta'] : [];
        foreach (['report_id', 'job_id', 'undo_run_id', 'snapshot_id'] as $key) {
            if (!empty($meta[$key]) && is_scalar($meta[$key])) {
                $seed[] = (string) $meta[$key];
            }
        }

        if (empty($seed)) {
            $seed[] = wp_json_encode($entry, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) ?: gmdate('c');
        }

        return 'assist_' . substr(md5(implode('|', $seed)), 0, 16);
    }
}
