<?php

namespace App\Traits;

use App\Events\VehiclePriceChangedDuringStockSync;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Event;
use Mtc\ContentManager\Models\Media;
use Mtc\MercuryDataModels\Dealership;
use Mtc\MercuryDataModels\Vehicle;

trait StockSyncTraits
{
    use MapsTaxonomies;

    /**
     * Find all stock locations to fetch data from
     * These are stored against dealerships
     *
     * @return Collection
     */
    private function getAllStockLocations(string $provider_attribute): Collection
    {
        $this->dealerships = Dealership::all()
            ->each(function (Dealership $dealership) use ($provider_attribute) {
                $dealership->stock_location = $dealership->data[$provider_attribute] ?? null;
            });

        return $this->dealerships
            ->map(fn(Dealership $dealership) => $dealership->data[$provider_attribute] ?? null)
            ->filter();
    }

    /**
     * Get the dealership id from stock location
     *
     * @param $locationId
     * @return string|null
     */
    private function dealershipId($locationId): ?string
    {
        return $this->dealerships
            ->where('stock_location', $locationId)
            ->first()
            ?->id;
    }

    private function priceChangeEvents(Vehicle $vehicle, string $provider, mixed $originalPrice = null): void
    {
        if (!$vehicle->wasChanged('price')) {
            return;
        }

        // If original price provided, do numeric comparison to avoid false positives
        // from type differences (e.g., '10000' string vs 10000.00 decimal)
        if ($originalPrice !== null && (float) $originalPrice === (float) $vehicle->price) {
            return;
        }

        Event::dispatch(new VehiclePriceChangedDuringStockSync($vehicle, $provider));
    }

    private function removeOld(Collection $allRecords): void
    {
        Vehicle::query()
            ->where('stock_provider', self::NAME)
            ->whereNotIn('uuid', $allRecords)
            ->delete();
    }

    private function removeNotSynced(bool $check_pending = true): void
    {
        if ($this->enoughVehiclesSyncedRecently(config('automotive.sync_margin_for_removing'), $check_pending)) {
            Vehicle::query()
                ->where('stock_provider', $this->getProviderName())
                ->where('was_recently_synced', 0)
                ->when($check_pending, fn($query) => $query->whereNull('pending_stock_sync'))
                ->delete();
        }
    }

    private function markVehiclesToBeSynced(): void
    {
        Vehicle::query()
            ->where('stock_provider', $this->getProviderName())
            ->update([
                'was_recently_synced' => false,
            ]);
    }

    private function enoughVehiclesSyncedRecently(float $margin, bool $check_pending): bool
    {
        $synced = Vehicle::query()
            ->where('stock_provider', $this->getProviderName())
            ->when($check_pending, fn($query) => $query->whereNull('pending_stock_sync'))
            ->where('was_recently_synced', 1)
            ->count();

        $provider_total = Vehicle::query()
            ->where('stock_provider', $this->getProviderName())
            ->when($check_pending, fn($query) => $query->whereNull('pending_stock_sync'))
            ->count();

        return empty($provider_total) ?: ($synced / $provider_total) > $margin;
    }

    private function removeWithMedia(Vehicle $vehicle): void
    {
        $ids = $vehicle->mediaUses()->pluck('media_id');
        $vehicle->mediaUses()->delete();
        $vehicle->delete();
        Media::query()->whereIn('id', $ids)->whereDoesntHave('uses')->delete();
    }
}
