<?php

namespace App\Domains\Event\Actions\SetPaymentMethods;

use App\Models\AvailablePaymentMethod;
use App\Models\PaymentMethod;
use App\RelationModels\EventPaymentMethods;

class SetPaymentMethodsCommand
{
    public SetPaymentMethodsRequest $request;

    public function __construct(SetPaymentMethodsRequest $request)
    {
        $this->request = $request;
    }

    public function execute(): SetPaymentMethodsResponse
    {
        $response = new SetPaymentMethodsResponse();

        if (count($this->request->paymentMethods) === 0) {
            $response->success = false;
            $response->message = 'Mindestens eine Zahlungsmöglichkeit muss ausgewählt sein.';
            return $response;
        }

        $this->syncPaymentMethods();

        $this->request->event->save();
        $response->success = true;

        return $response;
    }

    /**
     * Differenzieller Sync der Zahlungsmethoden mit Snapshot-Copy-Semantik:
     * - entfernte Methoden werden gelöscht,
     * - neue Methoden erhalten einen Snapshot der Tenant-Config (oder eines expliziten Overrides),
     * - bestehende Methoden behalten ihre pro-Event-Config, sofern kein Override übergeben wird.
     */
    private function syncPaymentMethods(): void
    {
        $event = $this->request->event;
        $desiredSlugs = $this->request->paymentMethods;
        $overrides = $this->request->paymentMethodConfigurations;

        $existing = EventPaymentMethods::where('event_id', $event->id)->get()->keyBy('slug');

        // Nicht mehr gewünschte Methoden entfernen.
        foreach ($existing as $slug => $row) {
            if (!in_array($slug, $desiredSlugs, true)) {
                $row->delete();
            }
        }

        // Tenant-Instanzen (für Snapshot-Kopie neuer Methoden) laden.
        $tenantMethods = AvailablePaymentMethod::whereIn('slug', $desiredSlugs)->get()->keyBy('slug');

        foreach ($desiredSlugs as $slug) {
            $override = $overrides[$slug] ?? null;

            if (isset($existing[$slug])) {
                // Bestehende Zuweisung: Config nur bei explizitem Override anpassen, sonst unverändert lassen.
                if ($override !== null) {
                    $row = $existing[$slug];
                    $row->configuration = PaymentMethod::sanitizeConfiguration($slug, $override);
                    $row->save();
                }
                continue;
            }

            // Neue Zuweisung: expliziter Override oder Snapshot der Tenant-Config.
            $snapshot = $override ?? ($tenantMethods[$slug]->configuration ?? []);
            EventPaymentMethods::create([
                'event_id' => $event->id,
                'slug' => $slug,
                'configuration' => PaymentMethod::sanitizeConfiguration($slug, $snapshot ?? []),
            ]);
        }
    }
}
