<?php

namespace App\Http\Controllers\Concerns;

use App\Models\Agency\Marketplace;
use Illuminate\Database\Eloquent\Model;

/**
 * Tarih modelleri için pazaryeri × sınıf fiyat satırlarını (tour_date_marketplace_prices)
 * senkronize eden ortak yardımcılar. Kültür / yurtdışı / günübirlik tarih controller'ları kullanır.
 *
 * Girdi yapısı: marketplace_prices[marketplaceId][classKey][field] => value
 *   classKey = 'none'  → sınıf kullanılmıyor (tour_class_id = null)
 *   classKey = <id>    → o fiyat sınıfı
 * (Eski düz yapı marketplace_prices[mpId][field] otomatik 'none' sınıfına sarılır.)
 */
trait SyncsMarketplacePrices
{
    /** Pazaryeri fiyat tablosuna yazılabilen fiyat alanları. */
    protected array $mpPriceFields = [
        'adult_price', 'child_price', 'child_price_1', 'child_price_2',
        'infant_price', 'single_supplement', 'extra_bed_price',
    ];

    /** Düz [field=>scalar] yapıyı ['none'=>[...]] sınıf haritasına normalize eder. */
    private function normalizeClassMap(array $classMap): array
    {
        foreach ($classMap as $v) {
            if (!is_array($v)) {
                return ['none' => $classMap];
            }
            break;
        }
        return $classMap;
    }

    /**
     * Bir tarih modeli için pazaryeri × sınıf fiyat satırlarını senkronize eder.
     * Boş (tüm alanları null) satırlar silinir; gönderilmeyen sınıflar (mod değişimi) temizlenir.
     */
    protected function syncMarketplacePrices(Model $date, array $input, int $agencyId): void
    {
        if (empty($input)) {
            return;
        }

        $marketplaces = Marketplace::where('agency_id', $agencyId)
            ->whereIn('id', array_keys($input))
            ->with('defaultCurrency')
            ->get()
            ->keyBy('id');

        foreach ($input as $mpId => $classMap) {
            $mp = $marketplaces->get((int) $mpId);
            if (!$mp || !is_array($classMap)) {
                continue;
            }

            $classMap = $this->normalizeClassMap($classMap);
            $currency = $mp->defaultCurrency->code ?? 'TRY';
            $rate = $mp->defaultCurrency->exchange_rate ?? 1.0;
            $submittedKeys = [];

            foreach ($classMap as $classKey => $fields) {
                if (!is_array($fields)) {
                    continue;
                }
                $classId = ($classKey === 'none' || $classKey === '') ? null : (int) $classKey;

                $payload = [];
                $hasValue = false;
                foreach ($this->mpPriceFields as $f) {
                    $raw = $fields[$f] ?? null;
                    $val = ($raw === '' || $raw === null) ? null : (float) $raw;
                    if ($val !== null) {
                        $hasValue = true;
                    }
                    $payload[$f] = $val;
                }

                if (!$hasValue) {
                    continue; // boş satır → yaz(ma); aşağıdaki temizlikte silinir
                }

                $submittedKeys[] = ($classId === null) ? 'none' : (string) $classId;
                $payload['currency'] = $currency;
                $payload['exchange_rate'] = $rate;

                $date->marketplacePrices()->updateOrCreate(
                    ['marketplace_id' => $mpId, 'tour_class_id' => $classId],
                    $payload
                );
            }

            // Bu pazaryerinde artık gönderilmeyen sınıf satırlarını temizle
            foreach ($date->marketplacePrices()->where('marketplace_id', $mpId)->get() as $row) {
                $k = $row->tour_class_id === null ? 'none' : (string) $row->tour_class_id;
                if (!in_array($k, $submittedKeys, true)) {
                    $row->delete();
                }
            }
        }
    }

    /**
     * Ana pazaryerini döndürür: ürünün tanımlı ana pazarı ($preferredId) öncelikli;
     * yoksa base currency olan; o da yoksa ilk.
     * @return Marketplace|null
     */
    protected function primaryMarketplace(array $input, int $agencyId, ?int $preferredId = null): ?Marketplace
    {
        if (empty($input)) {
            return null;
        }

        $marketplaces = Marketplace::where('agency_id', $agencyId)
            ->whereIn('id', array_keys($input))
            ->with('defaultCurrency')
            ->get();

        if ($marketplaces->isEmpty()) {
            return null;
        }

        return ($preferredId ? $marketplaces->firstWhere('id', $preferredId) : null)
            ?? $marketplaces->first(fn ($m) => $m->defaultCurrency && $m->defaultCurrency->is_base)
            ?? $marketplaces->first();
    }

    /**
     * Tarih satırının "temsili" temel fiyat alanlarını ana pazaryerinin taban sınıfından doldurur
     * (mevcut satış/liste ekranları tekil currency + adult_price bekliyor).
     *
     * @param array $map [tarih_kolonu => pazaryeri_alanı]
     */
    protected function applyPrimaryToDate(Model $date, array $input, int $agencyId, array $map, ?int $preferredId = null): void
    {
        $primary = $this->primaryMarketplace($input, $agencyId, $preferredId);
        if (!$primary) {
            return;
        }

        $classMap = $this->normalizeClassMap((array) ($input[$primary->id] ?? []));
        // Taban sınıf: 'none' varsa o; yoksa ilk sınıf (matris sıralaması taban ilk gelir)
        $prices = $classMap['none'] ?? (count($classMap) ? reset($classMap) : []);
        $prices = is_array($prices) ? $prices : [];

        $update = [];
        foreach ($map as $dateCol => $mpField) {
            $raw = $prices[$mpField] ?? null;
            $update[$dateCol] = ($raw === '' || $raw === null) ? null : (float) $raw;
        }

        $fillable = $date->getFillable();
        $cur = $primary->defaultCurrency->code ?? null;
        $rate = $primary->defaultCurrency->exchange_rate ?? null;
        if ($cur !== null && in_array('currency', $fillable, true)) {
            $update['currency'] = $cur;
        }
        if ($rate !== null && in_array('exchange_rate', $fillable, true)) {
            $update['exchange_rate'] = $rate;
        }

        $date->update($update);
    }
}
