<?php

namespace App\Classes\Modules\Affiliate\Services;

use App\Models\Affiliate;
use App\Models\Booking;
use App\Models\User;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class TracksAffiliateOrder
{
    /**
     * Track when a user with an affiliate code creates an order
     *
     * @param Booking $booking
     * @return Affiliate|null
     */
    public function execute(Booking $booking): ?Affiliate
    {
        try {
            return DB::transaction(function () use ($booking) {
                $user = $booking->company->employees()->first();

                if (!$user) {
                    return null;
                }

                // Get user's affiliate
                $userAffiliate = \App\Models\UserAffiliate::where('user_id', $user->id)
                    ->whereNotNull('registered_at')
                    ->first();

                if (!$userAffiliate) {
                    return null;
                }

                // Lock the affiliate record to prevent race conditions
                $affiliate = Affiliate::where('id', $userAffiliate->affiliate_id)
                    ->where('is_active', true)
                    ->lockForUpdate()
                    ->first();

                if (!$affiliate) {
                    return null;
                }

                // Check if this booking has already been counted
                // We'll use a KeyValuePair to track which bookings have been counted
                $kvpKey = 'affiliate_order_tracked_' . $affiliate->id;

                $existingKvp = $booking->attributesKVP()
                    ->where('key', $kvpKey)
                    ->exists();

                if ($existingKvp) {
                    return $affiliate; // Already counted
                }

                // Mark this booking as tracked
                $keyValuePairObject = new \App\Classes\Modules\KeyValuePairs\DataTransferObjects\KeyValuePairObject(
                    $kvpKey,
                    '1'
                );

                $createsKeyValuePair = app()->make(\App\Classes\Modules\KeyValuePairs\Services\CreatesKeyValuePair::class);
                $createsKeyValuePair->execute($booking, $keyValuePairObject);

                // Increment orders count atomically
                $affiliate->increment('orders_count');

                return $affiliate;
            });
        } catch (\Exception $e) {
            Log::error('Failed to track affiliate order', [
                'booking_id' => $booking->id,
                'error' => $e->getMessage()
            ]);
            return null;
        }
    }
}

