<?php
declare(strict_types=1);

namespace Autogedal\EanTools\Model;

use Autogedal\EanTools\Model\ResourceModel\Ean as EanResource;
use Autogedal\EanTools\Model\Tool\EanAudit;
use Magento\Framework\FlagManager;
use Magento\Framework\Lock\LockManagerInterface;

class StatsSnapshot
{
    private const FLAG_CODE = 'autogedal_ean_tools_stats';
    private const REFRESH_FLAG_CODE = 'autogedal_ean_tools_stats_refresh_requested';
    private const LOCK_NAME = 'autogedal_ean_tools_stats_refresh';

    public function __construct(
        private readonly FlagManager $flagManager,
        private readonly EanResource $eanResource,
        private readonly EanAudit $audit,
        private readonly LockManagerInterface $lockManager
    ) {
    }

    public function get(): ?array
    {
        $data = $this->flagManager->getFlagData(self::FLAG_CODE);

        return is_array($data) && isset($data['generated_at']) ? $data : null;
    }

    public function getOrCreate(): array
    {
        $data = $this->get();
        if ($data !== null) {
            return $data;
        }

        $this->requestRefresh();

        return [];
    }

    public function requestRefresh(): void
    {
        if ($this->flagManager->getFlagData(self::REFRESH_FLAG_CODE)) {
            return;
        }

        $this->flagManager->saveFlag(self::REFRESH_FLAG_CODE, gmdate('Y-m-d H:i:s'));
    }

    public function refreshIfRequested(): void
    {
        if (!$this->flagManager->getFlagData(self::REFRESH_FLAG_CODE)
            || !$this->lockManager->lock(self::LOCK_NAME, 0)
        ) {
            return;
        }

        try {
            if (!$this->flagManager->getFlagData(self::REFRESH_FLAG_CODE)) {
                return;
            }

            $this->refresh();
            $this->flagManager->deleteFlag(self::REFRESH_FLAG_CODE);
        } finally {
            $this->lockManager->unlock(self::LOCK_NAME);
        }
    }

    public function refresh(): array
    {
        $startedAt = microtime(true);

        $audit = $this->audit->scan();
        $used = $this->eanResource->countUsedEans();
        $duplicates = $this->eanResource->countDuplicateEanValues();
        $missingEnabled = $this->eanResource->countProductsWithoutEan(['status' => 'enabled']);

        $data = [
            'generated_at' => gmdate('Y-m-d H:i:s'),
            'duration' => round(microtime(true) - $startedAt, 1),
            'used' => $used,
            'duplicates' => $duplicates,
            'missing_enabled' => $missingEnabled,
            'invalid_total' => $audit['total'],
            'invalid_issues' => $audit['issues'],
            'scanned' => $audit['scanned'],
        ];

        $this->flagManager->saveFlag(self::FLAG_CODE, $data);

        return $data;
    }
}
