<?php
declare(strict_types=1);

namespace PpPhp\Core\Platform\Event\Verification;

final class EventVerificationService
{
    public const VERSION = 'R0100.5A';
    public const VERIFICATION_VERSION = '1.0.0';
    public const AUDITOR_VERSION = 'tokenized-property-scan-v1';
    public const REPORT_FILE = 'storage/reports/r0100/r0100-event-core-verification-report.json';

    public function verify(string $basePath): EventCoreStatus
    {
        return (new EventCoreVerifier())->verify($this->normalizeBasePath($basePath));
    }

    public function verifyAndWriteReport(string $basePath): EventCoreStatus
    {
        $basePath = $this->normalizeBasePath($basePath);
        $status = $this->verify($basePath);

        $this->writeReport($basePath, $status, false);

        return $status;
    }

    public function lock(string $basePath): EventCoreStatus
    {
        $basePath = $this->normalizeBasePath($basePath);
        $status = $this->verify($basePath);

        $this->writeReport($basePath, $status, true);
        $this->writeLock($basePath, $status);

        return $status;
    }

    public function reportPayload(EventCoreStatus $status, bool $locked = false): array
    {
        return [
            'version' => self::VERSION,
            'verificationVersion' => self::VERIFICATION_VERSION,
            'auditorVersion' => self::AUDITOR_VERSION,
            'generatedAt' => date('c'),
            'locked' => $locked,
            'score' => $status->summary()['score'] ?? 0,
            'verification' => $status->toArray(),
        ];
    }

    public function writeReport(string $basePath, EventCoreStatus $status, bool $locked = false): string
    {
        $file = $this->normalizeBasePath($basePath) . '/' . self::REPORT_FILE;
        $dir = dirname($file);

        if (!is_dir($dir)) {
            mkdir($dir, 0775, true);
        }

        file_put_contents($file, json_encode($this->reportPayload($status, $locked), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));

        return $file;
    }

    public function writeLock(string $basePath, EventCoreStatus $status): string
    {
        $file = $this->normalizeBasePath($basePath) . '/' . EventCoreLock::LOCK_FILE;
        $dir = dirname($file);

        if (!is_dir($dir)) {
            mkdir($dir, 0775, true);
        }

        file_put_contents($file, json_encode(EventCoreLock::payload($status), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));

        return $file;
    }

    public function normalizeBasePath(string $basePath): string
    {
        $basePath = rtrim($basePath, DIRECTORY_SEPARATOR);
        $real = realpath($basePath);

        return $real !== false ? $real : $basePath;
    }
}
