<?php

namespace App\Services\Addons;

use App\Models\EventPackage;
use App\Models\EventPackageAddon;
use App\Notifications\Addons\AddonPurchaseReceipt;
use App\Notifications\Ops\AddonPurchased;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Notification;

class EventAddonWebhookService
{
    public function __construct(private readonly EventAddonCatalog $catalog) {}

    public function handle(array $payload): bool
    {
        $eventType = $payload['event_type'] ?? null;
        $data = $payload['data'] ?? [];

        if ($eventType !== 'transaction.completed') {
            return false;
        }

        $metadata = $this->extractMetadata($data);
        $intentId = $metadata['addon_intent'] ?? null;
        $addonKey = $metadata['addon_key'] ?? null;

        if (! $intentId || ! $addonKey) {
            return false;
        }

        $transactionId = $data['id'] ?? $data['transaction_id'] ?? null;
        $checkoutId = $data['checkout_id'] ?? null;

        $addon = EventPackageAddon::query()
            ->where('addon_key', $addonKey)
            ->where(function ($query) use ($intentId, $checkoutId, $transactionId) {
                $query->where('metadata->addon_intent', $intentId)
                    ->orWhere('checkout_id', $checkoutId)
                    ->orWhere('transaction_id', $transactionId);
            })
            ->latest('id')
            ->first();

        if (! $addon) {
            Log::info('[AddonWebhook] Add-on intent not found', [
                'intent' => $intentId,
                'addon_key' => $addonKey,
                'transaction_id' => $transactionId,
            ]);

            return false;
        }

        if ($addon->status === 'completed') {
            return true; // idempotent
        }

        $increments = $this->resolveAddonIncrements($addon, $addonKey);

        DB::transaction(function () use ($addon, $transactionId, $checkoutId, $data, $increments) {
            $addon->forceFill([
                'transaction_id' => $transactionId,
                'checkout_id' => $addon->checkout_id ?: $checkoutId,
                'status' => 'completed',
                'amount' => Arr::get($data, 'totals.grand_total') ?? Arr::get($data, 'amount'),
                'currency' => Arr::get($data, 'currency_code') ?? Arr::get($data, 'currency'),
                'metadata' => array_merge($addon->metadata ?? [], ['webhook_payload' => $data]),
                'receipt_payload' => Arr::get($data, 'receipt_url') ? ['receipt_url' => Arr::get($data, 'receipt_url')] : null,
                'purchased_at' => now(),
            ])->save();

            /** @var EventPackage $eventPackage */
            $eventPackage = EventPackage::query()
                ->lockForUpdate()
                ->find($addon->event_package_id);

            if (! $eventPackage) {
                return;
            }

            $eventPackage->forceFill([
                'extra_photos' => ($eventPackage->extra_photos ?? 0) + (int) ($increments['extra_photos'] ?? 0) * $addon->quantity,
                'extra_guests' => ($eventPackage->extra_guests ?? 0) + (int) ($increments['extra_guests'] ?? 0) * $addon->quantity,
                'extra_gallery_days' => ($eventPackage->extra_gallery_days ?? 0) + (int) ($increments['extra_gallery_days'] ?? 0) * $addon->quantity,
            ]);

            if (($increments['extra_gallery_days'] ?? 0) > 0) {
                $base = $eventPackage->gallery_expires_at ?? now();
                $eventPackage->gallery_expires_at = $base->copy()->addDays((int) ($increments['extra_gallery_days'] ?? 0) * $addon->quantity);
            }

            $eventPackage->save();

            $tenant = $addon->tenant;
            if ($tenant) {
                Notification::route('mail', [$tenant->contact_email ?? $tenant->user?->email])
                    ->notify(new AddonPurchaseReceipt($addon));

                $opsEmail = config('mail.ops_address');
                if ($opsEmail) {
                    Notification::route('mail', $opsEmail)->notify(new AddonPurchased($addon));
                }
            }
        });

        return true;
    }

    /**
     * @param  array<string, mixed>  $data
     * @return array<string, mixed>
     */
    private function extractMetadata(array $data): array
    {
        $metadata = [];

        if (isset($data['metadata']) && is_array($data['metadata'])) {
            $metadata = $data['metadata'];
        }

        if (isset($data['custom_data']) && is_array($data['custom_data'])) {
            $metadata = array_merge($metadata, $data['custom_data']);
        }

        return $metadata;
    }

    /**
     * @return array<string, int>
     */
    private function resolveAddonIncrements(EventPackageAddon $addon, string $addonKey): array
    {
        $stored = Arr::get($addon->metadata ?? [], 'increments', []);

        if (is_array($stored) && $stored !== []) {
            $filtered = collect($stored)
                ->map(fn ($value) => is_numeric($value) ? (int) $value : 0)
                ->filter(fn ($value) => $value > 0)
                ->all();

            if ($filtered !== []) {
                return $filtered;
            }
        }

        return $this->catalog->resolveIncrements($addonKey);
    }
}
