<?php
declare(strict_types=1);

namespace Autogedal\EanTools\ViewModel;

use Autogedal\EanTools\Model\Spreadsheet\Format;
use Autogedal\EanTools\Model\StatsSnapshot;
use DateTime;
use DateTimeZone;
use IntlDateFormatter;
use Magento\Backend\Model\UrlInterface;
use Magento\Framework\Data\Form\FormKey;
use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
use Magento\Framework\View\Element\Block\ArgumentInterface;
use Psr\Log\LoggerInterface;
use Throwable;

class Tools implements ArgumentInterface
{
    private ?array $snapshot = null;
    private ?string $snapshotError = null;
    private bool $snapshotLoaded = false;

    public function __construct(
        private readonly UrlInterface $urlBuilder,
        private readonly LoggerInterface $logger,
        private readonly StatsSnapshot $statsSnapshot,
        private readonly FormKey $formKey,
        private readonly TimezoneInterface $timezone,
        private readonly Format $format
    ) {
    }

    public function getUrl(string $path, array $params = []): string
    {
        return $this->urlBuilder->getUrl($path, $params);
    }

    public function getFormKey(): string
    {
        return $this->formKey->getFormKey();
    }

    public function getTools(): array
    {
        return [
            [
                'key' => 'validate',
                'title' => __('Validator'),
                'description' => __('Upload a file containing EAN codes (CSV or XLSX) to separate available codes, used codes, and codes with issues.'),
                'accent' => 'primary',
                'actions' => $this->openAction('autogedal_ean/validate/index'),
            ],
            [
                'key' => 'missing',
                'title' => __('Products without EANs'),
                'description' => __('List products that do not have an EAN code, filtered by status and product type.'),
                'accent' => 'primary',
                'actions' => $this->openAction('autogedal_ean/missing/index'),
            ],
            [
                'key' => 'invalid',
                'title' => __('Products with invalid EANs'),
                'description' => __('Export products that have a stored EAN code which does not pass validation.'),
                'accent' => 'warning',
                'actions' => $this->formatActions('autogedal_ean/invalid/export'),
            ],
            [
                'key' => 'used',
                'title' => __('Used EANs'),
                'description' => __('Export all EAN codes in the catalog together with the products using them.'),
                'accent' => 'primary',
                'actions' => $this->formatActions('autogedal_ean/used/export'),
            ],
            [
                'key' => 'duplicates',
                'title' => __('Duplicate EANs'),
                'description' => __('Export codes used by more than one product, grouped for manual correction.'),
                'accent' => 'warning',
                'actions' => $this->formatActions('autogedal_ean/duplicates/export'),
            ],
            [
                'key' => 'runs',
                'title' => __('Generated Files'),
                'description' => __('View files generated by previous runs, including their date and tool, and download them again without regenerating them.'),
                'accent' => 'neutral',
                'actions' => $this->openAction('autogedal_ean/runs/index'),
            ],
        ];
    }

    private function openAction(string $path): array
    {
        return [
            [
                'label' => (string)__('Open'),
                'url' => $this->getUrl($path),
                'primary' => true,
                'post' => false,
                'params' => [],
            ],
        ];
    }

    private function formatActions(string $path): array
    {
        $actions = [];

        foreach ($this->format->getOptions() as $value => $label) {
            $actions[] = [
                'label' => $label,
                'url' => $this->getUrl($path),
                'primary' => $value === Format::DEFAULT_FORMAT,
                'post' => true,
                'params' => ['format' => $value],
            ];
        }

        return $actions;
    }

    public function getOverview(): array
    {
        $snapshot = $this->getSnapshot();
        if ($snapshot === null) {
            return ['stats' => [], 'error' => $this->snapshotError];
        }

        return [
            'stats' => [
                [
                    'label' => __('Used EANs'),
                    'value' => (int)($snapshot['used'] ?? 0),
                    'tone' => 'neutral',
                ],
                [
                    'label' => __('Duplicate EANs'),
                    'value' => (int)($snapshot['duplicates'] ?? 0),
                    'tone' => 'warning',
                ],
                [
                    'label' => __('Enabled products without EANs'),
                    'value' => (int)($snapshot['missing_enabled'] ?? 0),
                    'tone' => 'warning',
                ],
                [
                    'label' => __('Products with invalid EANs'),
                    'value' => $this->getInvalidTotal(),
                    'tone' => 'error',
                ],
            ],
            'error' => null,
        ];
    }

    public function getInvalidTotal(): int
    {
        return (int)($this->getSnapshot()['invalid_total'] ?? 0);
    }

    public function getLastUpdated(): ?string
    {
        $generatedAt = $this->getSnapshot()['generated_at'] ?? null;
        if (!is_string($generatedAt) || $generatedAt === '') {
            return null;
        }

        try {
            return $this->timezone->formatDateTime(
                new DateTime($generatedAt, new DateTimeZone('UTC')),
                IntlDateFormatter::MEDIUM,
                IntlDateFormatter::SHORT
            );
        } catch (Throwable) {
            return null;
        }
    }

    public function getRefreshUrl(): string
    {
        return $this->getUrl('autogedal_ean/stats/refresh');
    }

    private function getSnapshot(): ?array
    {
        if (!$this->snapshotLoaded) {
            $this->snapshotLoaded = true;
            try {
                $this->snapshot = $this->statsSnapshot->getOrCreate();
            } catch (Throwable $exception) {
                $this->logger->error(
                    'Autogedal_EanTools overview: ' . $exception->getMessage(),
                    ['exception' => $exception]
                );
                $this->snapshotError = $exception->getMessage();
            }
        }

        return $this->snapshot;
    }
}
