<?php

namespace App\Support;

use App\Models\Event;
use App\Models\Package;
use Illuminate\Support\Arr;

class WatermarkConfigResolver
{
    public static function determineBrandingAllowed(Event $event): bool
    {
        $event->loadMissing('eventPackage.package', 'eventPackages.package');

        $package = $event->eventPackage?->package;

        if (! $package && $event->relationLoaded('eventPackages')) {
            $package = $event->eventPackages->first()?->package;
        }

        // If no package is attached, default to allowing branding to avoid silently stripping event/tenant branding.
        if (! $package) {
            return true;
        }

        return $package->branding_allowed !== false;
    }

    public static function determinePolicy(Event $event): string
    {
        $event->loadMissing('eventPackage.package');

        return self::determineRemovalAllowed($event) ? 'none' : 'basic';
    }

    public static function determineRemovalAllowed(Event $event): bool
    {
        $event->loadMissing('eventPackage.package', 'eventPackages.package');

        $package = $event->eventPackage?->package;

        if (! $package && $event->relationLoaded('eventPackages')) {
            $package = $event->eventPackages->first()?->package;
        }

        return self::packageHasFeature($package, 'no_watermark')
            || self::packageHasFeature($package, 'watermark_removal');
    }

    /**
     * @return array{type:string, policy:string, asset?:string, position?:string, opacity?:float, scale?:float, padding?:int, offset_x?:int, offset_y?:int}
     */
    public static function resolve(Event $event): array
    {
        $policy = self::determinePolicy($event);

        $baseSetting = null;

        if (class_exists(\App\Models\WatermarkSetting::class) && \Illuminate\Support\Facades\Schema::hasTable('watermark_settings')) {
            try {
                $baseSetting = \App\Models\WatermarkSetting::query()->first();
            } catch (\Throwable) {
                $baseSetting = null;
            }
        }
        $base = [
            'asset' => $baseSetting?->asset ?? config('watermark.base.asset', 'branding/fotospiel-watermark.png'),
            'position' => $baseSetting?->position ?? config('watermark.base.position', 'bottom-right'),
            'opacity' => $baseSetting?->opacity ?? config('watermark.base.opacity', 0.25),
            'scale' => $baseSetting?->scale ?? config('watermark.base.scale', 0.2),
            'padding' => $baseSetting?->padding ?? config('watermark.base.padding', 16),
            'offset_x' => $baseSetting?->offset_x ?? config('watermark.base.offset_x', 0),
            'offset_y' => $baseSetting?->offset_y ?? config('watermark.base.offset_y', 0),
        ];

        $event->loadMissing('eventPackage.package', 'eventPackages.package', 'tenant');
        $package = $event->eventPackage?->package;

        if (! $package && $event->relationLoaded('eventPackages')) {
            $package = $event->eventPackages->first()?->package;
        }
        $brandingAllowed = self::determineBrandingAllowed($event);
        $watermarkAllowed = $package?->watermark_allowed !== false;
        $removalAllowed = self::determineRemovalAllowed($event);
        $eventWatermark = Arr::get($event->settings, 'watermark', []);
        $tenantWatermark = Arr::get($event->tenant?->settings, 'watermark', []);
        $serveOriginals = (bool) Arr::get($event->settings, 'watermark_serve_originals', false);

        $mode = $brandingAllowed
            ? ($eventWatermark['mode'] ?? $tenantWatermark['mode'] ?? 'base')
            : 'base';

        if ($mode === 'custom' && (! $brandingAllowed || ! $watermarkAllowed)) {
            $mode = 'base';
        }

        if ($mode === 'off' && ! $removalAllowed) {
            $mode = 'base';
        }

        if ($mode === 'off') {
            return [
                'type' => 'none',
                'policy' => $policy,
            ];
        }

        $source = $mode === 'custom' && $brandingAllowed ? ($eventWatermark ?: $tenantWatermark) : [];

        $asset = $source['asset'] ?? $base['asset'] ?? null;
        $position = $source['position'] ?? $base['position'] ?? 'bottom-right';
        $opacity = (float) ($source['opacity'] ?? $base['opacity'] ?? 0.25);
        $scale = (float) ($source['scale'] ?? $base['scale'] ?? 0.2);
        $padding = (int) ($source['padding'] ?? $base['padding'] ?? 16);
        $offsetX = (int) ($source['offset_x'] ?? $base['offset_x'] ?? 0);
        $offsetY = (int) ($source['offset_y'] ?? $base['offset_y'] ?? 0);

        $clamp = static fn (float $value, float $min, float $max) => max($min, min($max, $value));

        return [
            'type' => $mode === 'custom' && $brandingAllowed ? 'custom' : 'base',
            'policy' => $policy,
            'asset' => $asset,
            'position' => $position,
            'opacity' => $clamp($opacity, 0.0, 1.0),
            'scale' => $clamp($scale, 0.05, 1.0),
            'padding' => max(0, $padding),
            'offset_x' => max(-500, min(500, $offsetX)),
            'offset_y' => max(-500, min(500, $offsetY)),
            'serve_originals' => $serveOriginals,
        ];
    }

    private static function packageHasFeature(?Package $package, string $feature): bool
    {
        if (! $package) {
            return false;
        }

        $features = $package->features ?? [];

        if (is_string($features)) {
            $decoded = json_decode($features, true);
            if (json_last_error() === JSON_ERROR_NONE) {
                $features = $decoded;
            }
        }

        if (! is_array($features)) {
            return false;
        }

        if (array_is_list($features)) {
            return in_array($feature, $features, true);
        }

        return isset($features[$feature]) && (bool) $features[$feature];
    }
}
