<?php

namespace App\Services\Addons;

use App\Models\Event;
use App\Models\EventPackageAddon;
use App\Models\Tenant;
use App\Services\Paddle\PaddleClient;
use App\Services\Paddle\PaddleCustomerService;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
use Throwable;

class EventAddonCheckoutService
{
    public function __construct(
        private readonly EventAddonCatalog $catalog,
        private readonly PaddleClient $paddle,
        private readonly PaddleCustomerService $customers,
    ) {}

    /**
     * @param  array{addon_key: string, quantity?: int, success_url?: string|null, cancel_url?: string|null}  $payload
     * @return array{checkout_url: string|null, id: string|null, expires_at: string|null}
     */
    public function createCheckout(Tenant $tenant, Event $event, array $payload): array
    {
        $addonKey = $payload['addon_key'] ?? null;
        $quantity = max(1, (int) ($payload['quantity'] ?? 1));
        $acceptedWaiver = (bool) ($payload['accepted_waiver'] ?? false);
        $acceptedTerms = (bool) ($payload['accepted_terms'] ?? false);

        try {
            $customerId = $this->customers->ensureCustomerId($tenant);
        } catch (Throwable $exception) {
            throw ValidationException::withMessages([
                'customer' => __('Konnte Paddle-Kundenkonto nicht anlegen: :message', ['message' => $exception->getMessage()]),
            ]);
        }

        if (! $addonKey || ! $this->catalog->find($addonKey)) {
            throw ValidationException::withMessages([
                'addon_key' => __('Unbekanntes Add-on.'),
            ]);
        }

        $priceId = $this->catalog->resolvePriceId($addonKey);

        if (! $priceId) {
            throw ValidationException::withMessages([
                'addon_key' => __('Für dieses Add-on ist kein Paddle-Preis hinterlegt.'),
            ]);
        }

        $event->loadMissing('eventPackage');

        if (! $event->eventPackage) {
            throw ValidationException::withMessages([
                'event' => __('Kein Paket für dieses Event hinterlegt.'),
            ]);
        }

        $addonIntent = (string) Str::uuid();

        $increments = $this->catalog->resolveIncrements($addonKey);

        $metadata = array_filter([
            'tenant_id' => (string) $tenant->id,
            'event_id' => (string) $event->id,
            'event_package_id' => (string) $event->eventPackage->id,
            'addon_key' => $addonKey,
            'addon_intent' => $addonIntent,
            'quantity' => $quantity,
            'legal_version' => $this->resolveLegalVersion(),
            'accepted_terms' => $acceptedTerms ? '1' : '0',
            'accepted_waiver' => $acceptedWaiver ? '1' : '0',
            'success_url' => $payload['success_url'] ?? null,
            'cancel_url' => $payload['cancel_url'] ?? null,
        ], static fn ($value) => $value !== null && $value !== '');

        $requestPayload = array_filter([
            'customer_id' => $customerId,
            'items' => [
                [
                    'price_id' => $priceId,
                    'quantity' => $quantity,
                ],
            ],
            'custom_data' => $metadata,
        ], static fn ($value) => $value !== null && $value !== '');

        $response = $this->paddle->post('/transactions', $requestPayload);

        $checkoutUrl = Arr::get($response, 'data.checkout.url')
            ?? Arr::get($response, 'checkout.url')
            ?? Arr::get($response, 'data.url')
            ?? Arr::get($response, 'url');
        $checkoutId = Arr::get($response, 'data.checkout_id')
            ?? Arr::get($response, 'data.checkout.id')
            ?? Arr::get($response, 'checkout_id')
            ?? Arr::get($response, 'checkout.id');
        $transactionId = Arr::get($response, 'data.id') ?? Arr::get($response, 'id');

        if (! $checkoutUrl) {
            Log::warning('Paddle addon checkout response missing url', ['response' => $response]);
        }

        EventPackageAddon::create([
            'event_package_id' => $event->eventPackage->id,
            'event_id' => $event->id,
            'tenant_id' => $tenant->id,
            'addon_key' => $addonKey,
            'quantity' => $quantity,
            'price_id' => $priceId,
            'checkout_id' => $checkoutId,
            'transaction_id' => $transactionId,
            'status' => 'pending',
            'metadata' => array_merge($metadata, [
                'increments' => $increments,
                'provider_payload' => $response,
                'consents' => [
                    'legal_version' => $metadata['legal_version'],
                    'accepted_terms_at' => $acceptedTerms ? now()->toIso8601String() : null,
                    'digital_content_waiver_at' => $acceptedWaiver ? now()->toIso8601String() : null,
                ],
            ]),
            'extra_photos' => ($increments['extra_photos'] ?? 0) * $quantity,
            'extra_guests' => ($increments['extra_guests'] ?? 0) * $quantity,
            'extra_gallery_days' => ($increments['extra_gallery_days'] ?? 0) * $quantity,
        ]);

        return [
            'checkout_url' => $checkoutUrl,
            'expires_at' => Arr::get($response, 'data.checkout.expires_at')
                ?? Arr::get($response, 'data.expires_at')
                ?? Arr::get($response, 'expires_at'),
            'id' => $transactionId ?? $checkoutId,
        ];
    }

    protected function resolveLegalVersion(): string
    {
        return config('app.legal_version', now()->toDateString());
    }
}
