<?php

declare(strict_types=1);

require_once __DIR__ . '/EntitlementSnapshot.php';

final class MyronCoreAttributionPolicy
{
    public const LINK_URL = 'https://myroncms.com';
    private const TEXT = 'Built with MyronCMS';

    public function __construct(private readonly bool $required)
    {
    }

    public static function fromRuntime(): self
    {
        if (!function_exists('myronEntitlementGate')) {
            return new self(false);
        }

        try {
            $decision = myronEntitlementGate()->evaluate('attribution.public_bar');
        } catch (Throwable) {
            return new self(false);
        }

        return new self(in_array((string) ($decision['outcome'] ?? ''), ['allowed', 'warn'], true));
    }

    public static function forSnapshot(MyronEntitlementSnapshot $snapshot): self
    {
        return new self(($snapshot->capabilities['attribution.public_bar'] ?? false) === true);
    }

    public function isRequired(): bool
    {
        return $this->required;
    }

    public function renderBar(): string
    {
        if (!$this->required) {
            return '';
        }

        $token = 'myron-core-attribution-' . substr(hash('sha256', myronAppUrl() . '|' . myronNow() . '|' . random_int(1, PHP_INT_MAX)), 0, 12);
        $style = implode('', [
            'display:flex!important;',
            'min-height:32px!important;',
            'align-items:center!important;',
            'justify-content:center!important;',
            'padding:6px 16px!important;',
            'box-sizing:border-box!important;',
            'font:500 12px/1.4 var(--myron-font-ui,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif)!important;',
            'letter-spacing:0!important;',
            'color:var(--myron-color-text,#151515)!important;',
            'background:color-mix(in srgb,var(--myron-color-surface,#ffffff) 92%,var(--myron-color-text,#151515) 8%)!important;',
            'border-top:1px solid color-mix(in srgb,var(--myron-color-text,#151515) 16%,transparent)!important;',
        ]);
        $linkStyle = implode('', [
            'color:inherit!important;',
            'text-decoration:underline!important;',
            'text-underline-offset:2px!important;',
        ]);

        return '<aside id="' . self::escape($token) . '" class="' . self::escape($token) . '" data-myron-core-attribution="' . self::escape($token) . '" aria-label="' . self::escape(self::TEXT) . '" style="' . self::escape($style) . '"><a href="' . self::escape(self::LINK_URL) . '" rel="noopener" style="' . self::escape($linkStyle) . '">' . self::escape(self::TEXT) . '</a></aside>';
    }

    public static function containsRemovalAttempt(string $payload): bool
    {
        $normalized = strtolower($payload);
        if (!str_contains($normalized, 'myron-core-attribution') && !str_contains($normalized, 'data-myron-core-attribution') && !str_contains($normalized, 'built with myroncms')) {
            return false;
        }

        return preg_match('/display\s*:\s*none|visibility\s*:\s*hidden|opacity\s*:\s*0|content\s*:\s*[\'"]{0,1}none/i', $payload) === 1
            || str_contains($normalized, 'remove attribution')
            || str_contains($normalized, 'hide attribution');
    }

    public static function assertNoRemovalAttempt(string $payload): void
    {
        if (self::containsRemovalAttempt($payload)) {
            throw new RuntimeException('Core attribution removal is not supported by this license.');
        }
    }

    public static function assertInstalledSourceIntact(string $projectRoot): void
    {
        $assembler = $projectRoot . '/app/modules/content/public/PublishedPageHtmlAssembler.php';
        $policy = $projectRoot . '/app/system/license/CoreAttributionPolicy.php';
        $assemblerSource = is_file($assembler) ? (string) file_get_contents($assembler) : '';
        $policySource = is_file($policy) ? (string) file_get_contents($policy) : '';
        if (
            !str_contains($assemblerSource, 'MyronCoreAttributionPolicy::fromRuntime()->renderBar()')
            || !str_contains($policySource, self::TEXT)
            || !str_contains($policySource, self::LINK_URL)
        ) {
            throw new RuntimeException('Required Core attribution source is missing or has been altered.');
        }
    }

    private static function escape(string $value): string
    {
        return htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
    }
}
