<?php

namespace App\Http\Controllers\Agency\Tour;

use App\Http\Controllers\Concerns\SyncsMarketplacePrices;
use App\Http\Controllers\Controller;
use App\Models\Tour\Tour;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;

class TourDateController extends Controller
{
    use AuthorizesRequests;
    use SyncsMarketplacePrices;

    /** Tarih tablosunda fiyat kolonu kalmadı — applyPrimaryToDate yalnızca ana pazarın
     *  currency/exchange_rate bilgisini tarihe senkronlar (fiyatlar sadece matriste). */
    private array $baseFieldMap = [];

    public function index(Tour $tour)
    {
        $this->authorize('update', $tour);

        $dates = $tour->tourDates()
            ->with(['assignedGuide', 'assignedVehicle'])
            ->orderBy('start_date')
            ->get();

        $activeCurrencies = auth()->user()->agency->getActiveCurrencies();

        return view('agency.products.kultur-turlari.dates', compact('tour', 'dates', 'activeCurrencies'));
    }

    public function store(Request $request, Tour $tour)
    {
        $this->authorize('update', $tour);

        $activeCurrencies = auth()->user()->agency->getActiveCurrencies();
        $allowedCurrencies = $activeCurrencies->pluck('code')->toArray();

        $validator = Validator::make($request->all(), [
            'start_date' => 'required|date|after:today',
            'end_date' => 'required|date|after_or_equal:start_date',
            'total_capacity' => 'required|integer|min:1',
            'adult_capacity' => 'nullable|integer|min:0',
            'child_capacity' => 'nullable|integer|min:0',
            'infant_capacity' => 'nullable|integer|min:0',
            'room_capacity' => 'nullable|integer|min:1',
            'adult_price' => 'nullable|numeric|min:0',
            'single_supplement' => 'nullable|numeric|min:0',
            'extra_bed_price' => 'nullable|numeric|min:0',
            'child_price_1' => 'nullable|numeric|min:0',
            'child_price_2' => 'nullable|numeric|min:0',
            'infant_price' => 'nullable|numeric|min:0',
            'child_min_age' => 'nullable|integer|min:0|max:17',
            'child_max_age' => 'nullable|integer|min:1|max:18',
            'infant_min_age' => 'nullable|integer|min:0|max:5',
            'infant_max_age' => 'nullable|integer|min:0|max:6',
            'currency' => 'nullable|in:' . implode(',', $allowedCurrencies),
            'marketplace_prices' => 'nullable|array',
            'early_booking_discount' => 'nullable|numeric|min:0|max:100',
            'early_booking_deadline' => 'nullable|date',
            'last_minute_discount' => 'nullable|numeric|min:0|max:100',
            'last_minute_booking_start' => 'nullable|date',
            'group_discount' => 'nullable|numeric|min:0|max:100',
            'min_group_size' => 'nullable|integer|min:0',
            'special_discount' => 'nullable|numeric|min:0|max:100',
            'discount_reason' => 'nullable|string|max:255',
            'auto_guarantee_on_min' => 'nullable|boolean',
            'season_type' => 'required|in:low,medium,high,peak',
            'status' => 'required|in:draft,published,booking_open,booking_closed,confirmed,in_progress,completed,cancelled',
            'min_participants' => 'nullable|integer|min:0',
            'use_custom_payment_plan' => 'nullable|boolean',
            'payment_schedule' => 'nullable|array',
            'early_booking_rule' => 'nullable|array',
            'last_minute_rule' => 'nullable|array',
            'booking_deadline_rule' => 'nullable|array',
            'special_notes' => 'nullable|string|max:1000',
        ], [
            'start_date.required' => 'Başlangıç tarihi zorunludur.',
            'start_date.date' => 'Geçerli bir başlangıç tarihi giriniz.',
            'start_date.after' => 'Başlangıç tarihi bugünden sonra olmalıdır.',
            'end_date.required' => 'Bitiş tarihi zorunludur.',
            'end_date.date' => 'Geçerli bir bitiş tarihi giriniz.',
            'end_date.after_or_equal' => 'Bitiş tarihi başlangıç tarihinden önce olamaz.',
            'total_capacity.required' => 'Toplam kapasite zorunludur.',
            'total_capacity.integer' => 'Toplam kapasite sayı olmalıdır.',
            'total_capacity.min' => 'Toplam kapasite en az 1 olmalıdır.',
            'adult_capacity.integer' => 'Yetişkin kapasitesi sayı olmalıdır.',
            'child_capacity.integer' => 'Çocuk kapasitesi sayı olmalıdır.',
            'infant_capacity.integer' => 'Bebek kapasitesi sayı olmalıdır.',
            'adult_price.numeric' => 'Yetişkin fiyatı sayı olmalıdır.',
            'adult_price.min' => 'Yetişkin fiyatı negatif olamaz.',
            'child_price.numeric' => 'Çocuk fiyatı sayı olmalıdır.',
            'child_price.min' => 'Çocuk fiyatı negatif olamaz.',
            'infant_price.numeric' => 'Bebek fiyatı sayı olmalıdır.',
            'infant_price.min' => 'Bebek fiyatı negatif olamaz.',
            'currency.required' => 'Para birimi zorunludur.',
            'currency.in' => 'Geçersiz para birimi seçimi.',
            'early_booking_discount.numeric' => 'Erken rezervasyon indirimi sayı olmalıdır.',
            'early_booking_discount.min' => 'Erken rezervasyon indirimi negatif olamaz.',
            'early_booking_discount.max' => 'Erken rezervasyon indirimi %100\'den fazla olamaz.',
            'last_minute_discount.numeric' => 'Son dakika indirimi sayı olmalıdır.',
            'last_minute_discount.min' => 'Son dakika indirimi negatif olamaz.',
            'last_minute_discount.max' => 'Son dakika indirimi %100\'den fazla olamaz.',
            'group_discount.numeric' => 'Grup indirimi sayı olmalıdır.',
            'group_discount.min' => 'Grup indirimi negatif olamaz.',
            'group_discount.max' => 'Grup indirimi %100\'den fazla olamaz.',
            'special_discount.numeric' => 'Özel indirim sayı olmalıdır.',
            'special_discount.min' => 'Özel indirim negatif olamaz.',
            'special_discount.max' => 'Özel indirim %100\'den fazla olamaz.',
            'season_type.required' => 'Sezon tipi zorunludur.',
            'season_type.in' => 'Geçersiz sezon tipi seçimi.',
            'status.required' => 'Durum zorunludur.',
            'status.in' => 'Geçersiz durum seçimi.',
            'min_participants.integer' => 'Minimum katılımcı sayısı tam sayı olmalıdır.',
            'min_participants.min' => 'Minimum katılımcı sayısı negatif olamaz.',
            'tour_pricing_id.exists' => 'Seçilen fiyatlandırma planı bulunamadı.',
            'special_notes.string' => 'Özel notlar metin olmalıdır.',
            'special_notes.max' => 'Özel notlar en fazla 1000 karakter olabilir.',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'errors' => $validator->errors(),
                'message' => 'Lütfen tüm alanları doğru şekilde doldurunuz.'
            ], 422);
        }

        $data = $request->all();
        $data['remaining_capacity'] = $request->total_capacity;

        // Checkboxlar
        $data['is_active'] = $request->has('is_active');
        $data['is_published'] = !in_array($request->status, ['draft']);
        $data['is_bookable'] = $request->has('is_bookable');
        $data['guarantee_departure'] = $request->has('guarantee_departure');
        $data['use_custom_payment_plan'] = $request->has('use_custom_payment_plan');
        $data['auto_guarantee_on_min'] = $request->has('auto_guarantee_on_min');
        $data['early_booking_rule'] = $this->sanitizeRule($request->input('early_booking_rule'));
        $data['last_minute_rule'] = $this->sanitizeRule($request->input('last_minute_rule'));
        $data['booking_deadline_rule'] = $this->sanitizeRule($request->input('booking_deadline_rule'));

        // Duration hesapla
        $startDate = \Carbon\Carbon::parse($request->start_date);
        $endDate = \Carbon\Carbon::parse($request->end_date);
        $data['duration_days'] = $startDate->diffInDays($endDate) + 1;
        $data['duration_nights'] = max(0, $data['duration_days'] - 1);

        // Code oluştur
        $data['code'] = $this->generateDateCode($tour);

        unset($data['marketplace_prices']); // tarih tablosunun kolonu değil

        $tourDate = $tour->tourDates()->create($data);

        // Pazaryeri fiyat matrisi + tarihin temsili temel fiyatları
        $agencyId = auth()->user()->currentAgencyId();
        $mpInput = $request->input('marketplace_prices', []);
        $this->syncMarketplacePrices($tourDate, $mpInput, $agencyId);
        $this->applyPrimaryToDate($tourDate, $mpInput, $agencyId, $this->baseFieldMap, $tour->product?->primary_marketplace_id);

        return response()->json([
            'success' => true,
            'tourDate' => $tourDate,
            'message' => 'Tur tarihi başarıyla eklendi.'
        ]);
    }

    /**
     * Esnek deadline kuralını temizler; geçersizse null döner.
     */
    private function sanitizeRule($rule): ?array
    {
        if (!is_array($rule) || empty($rule['mode'])) {
            return null;
        }

        if ($rule['mode'] === 'datetime') {
            return empty($rule['at']) ? null : ['mode' => 'datetime', 'at' => $rule['at']];
        }

        if ($rule['mode'] === 'relative') {
            $amount = (int) ($rule['amount'] ?? 0);
            if ($amount < 1) {
                return null;
            }
            return [
                'mode' => 'relative',
                'amount' => $amount,
                'unit' => in_array($rule['unit'] ?? '', ['hours', 'days']) ? $rule['unit'] : 'hours',
                'direction' => in_array($rule['direction'] ?? '', ['before', 'after']) ? $rule['direction'] : 'before',
                'anchor' => in_array($rule['anchor'] ?? '', ['departure', 'publish', 'booking_close']) ? $rule['anchor'] : 'departure',
            ];
        }

        return null;
    }

    /**
     * Tarih no: tur içinde 1'den başlayan düz sıra numarası.
     */
    private function generateDateCode(Tour $tour): string
    {
        return \App\Support\SequentialCode::next($tour->tourDates()->withTrashed());
    }

    /**
     * Bir kopya için "turun bitişinden kaç gün sonra" başlanacağını (periyot boşluğu) tespit eder.
     * Kaynaktan önceki tarih varsa: kaynağın başlangıcı − önceki turun bitişi.
     * Yoksa sonraki tarih varsa: sonraki turun başlangıcı − kaynağın bitişi. Hiç yoksa 7.
     */
    private function inferOffsetAfterEnd(Tour $tour, $source): int
    {
        if ($source->start_date) {
            $prev = $tour->tourDates()
                ->where('id', '!=', $source->id)
                ->whereNotNull('end_date')
                ->whereDate('start_date', '<', $source->start_date->toDateString())
                ->orderByDesc('start_date')
                ->first();
            if ($prev && $prev->end_date) {
                $gap = $prev->end_date->copy()->startOfDay()->diffInDays($source->start_date->copy()->startOfDay());
                if ($gap >= 0) return (int) $gap;
            }

            $next = $tour->tourDates()
                ->where('id', '!=', $source->id)
                ->whereNotNull('start_date')
                ->whereDate('start_date', '>', $source->start_date->toDateString())
                ->orderBy('start_date')
                ->first();
            if ($next && $next->start_date && $source->end_date) {
                $gap = $source->end_date->copy()->startOfDay()->diffInDays($next->start_date->copy()->startOfDay());
                if ($gap >= 0) return (int) $gap;
            }
        }

        return 7;
    }

    public function show(Request $request, Tour $tour, $dateId)
    {
        $this->authorize('update', $tour);

        $tourDate = $tour->tourDates()
            ->with(['assignedGuide', 'assignedVehicle'])
            ->find($dateId);

        if (!$tourDate) {
            return response()->json([
                'success' => false,
                'message' => 'Tarih bulunamadı.'
            ], 404);
        }

        $dateData = $tourDate->toArray();

        if ($tourDate->start_date) {
            $dateData['start_date'] = $tourDate->start_date->format('Y-m-d');
        }

        if ($tourDate->end_date) {
            $dateData['end_date'] = $tourDate->end_date->format('Y-m-d');
        }

        if ($tourDate->early_booking_deadline) {
            $dateData['early_booking_deadline'] = $tourDate->early_booking_deadline->format('Y-m-d');
        }

        if ($tourDate->last_minute_booking_start) {
            $dateData['last_minute_booking_start'] = $tourDate->last_minute_booking_start->format('Y-m-d');
        }

        return response()->json([
            'success' => true,
            'date' => $dateData
        ]);
    }

    public function update(Request $request, Tour $tour, $date)
    {
        $this->authorize('update', $tour);

        $tourDate = $tour->tourDates()->findOrFail($date);

        $activeCurrencies = auth()->user()->agency->getActiveCurrencies();
        $allowedCurrencies = $activeCurrencies->pluck('code')->toArray();

        $validator = Validator::make($request->all(), [
            'start_date' => 'required|date',
            'end_date' => 'required|date|after_or_equal:start_date',
            'total_capacity' => 'required|integer|min:1',
            'adult_capacity' => 'nullable|integer|min:0',
            'child_capacity' => 'nullable|integer|min:0',
            'infant_capacity' => 'nullable|integer|min:0',
            'room_capacity' => 'nullable|integer|min:1',
            'adult_price' => 'nullable|numeric|min:0',
            'single_supplement' => 'nullable|numeric|min:0',
            'extra_bed_price' => 'nullable|numeric|min:0',
            'child_price_1' => 'nullable|numeric|min:0',
            'child_price_2' => 'nullable|numeric|min:0',
            'infant_price' => 'nullable|numeric|min:0',
            'child_min_age' => 'nullable|integer|min:0|max:17',
            'child_max_age' => 'nullable|integer|min:1|max:18',
            'infant_min_age' => 'nullable|integer|min:0|max:5',
            'infant_max_age' => 'nullable|integer|min:0|max:6',
            'currency' => 'nullable|in:' . implode(',', $allowedCurrencies),
            'marketplace_prices' => 'nullable|array',
            'early_booking_discount' => 'nullable|numeric|min:0|max:100',
            'early_booking_deadline' => 'nullable|date',
            'last_minute_discount' => 'nullable|numeric|min:0|max:100',
            'last_minute_booking_start' => 'nullable|date',
            'group_discount' => 'nullable|numeric|min:0|max:100',
            'min_group_size' => 'nullable|integer|min:0',
            'special_discount' => 'nullable|numeric|min:0|max:100',
            'discount_reason' => 'nullable|string|max:255',
            'auto_guarantee_on_min' => 'nullable|boolean',
            'season_type' => 'required|in:low,medium,high,peak',
            'status' => 'required|in:draft,published,booking_open,booking_closed,confirmed,in_progress,completed,cancelled',
            'min_participants' => 'nullable|integer|min:0',
            'use_custom_payment_plan' => 'nullable|boolean',
            'payment_schedule' => 'nullable|array',
            'early_booking_rule' => 'nullable|array',
            'last_minute_rule' => 'nullable|array',
            'booking_deadline_rule' => 'nullable|array',
            'special_notes' => 'nullable|string|max:1000',
        ], [
            'start_date.required' => 'Başlangıç tarihi zorunludur.',
            'start_date.date' => 'Geçerli bir başlangıç tarihi giriniz.',
            'end_date.required' => 'Bitiş tarihi zorunludur.',
            'end_date.date' => 'Geçerli bir bitiş tarihi giriniz.',
            'end_date.after_or_equal' => 'Bitiş tarihi başlangıç tarihinden önce olamaz.',
            'total_capacity.required' => 'Toplam kapasite zorunludur.',
            'total_capacity.integer' => 'Toplam kapasite sayı olmalıdır.',
            'total_capacity.min' => 'Toplam kapasite en az 1 olmalıdır.',
            'currency.required' => 'Para birimi zorunludur.',
            'currency.in' => 'Geçersiz para birimi seçimi.',
            'season_type.required' => 'Sezon tipi zorunludur.',
            'season_type.in' => 'Geçersiz sezon tipi seçimi.',
            'status.required' => 'Durum zorunludur.',
            'status.in' => 'Geçersiz durum seçimi.',
            'special_notes.max' => 'Özel notlar en fazla 1000 karakter olabilir.',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'errors' => $validator->errors(),
                'message' => 'Lütfen tüm alanları doğru şekilde doldurunuz.'
            ], 422);
        }

        $data = $request->all();

        // Checkboxlar
        $data['is_active'] = $request->has('is_active');
        $data['is_published'] = !in_array($request->status, ['draft']);
        $data['is_bookable'] = $request->has('is_bookable');
        $data['guarantee_departure'] = $request->has('guarantee_departure');
        $data['use_custom_payment_plan'] = $request->has('use_custom_payment_plan');
        $data['auto_guarantee_on_min'] = $request->has('auto_guarantee_on_min');
        $data['early_booking_rule'] = $this->sanitizeRule($request->input('early_booking_rule'));
        $data['last_minute_rule'] = $this->sanitizeRule($request->input('last_minute_rule'));
        $data['booking_deadline_rule'] = $this->sanitizeRule($request->input('booking_deadline_rule'));

        // Duration hesapla
        $startDate = \Carbon\Carbon::parse($request->start_date);
        $endDate = \Carbon\Carbon::parse($request->end_date);
        $data['duration_days'] = $startDate->diffInDays($endDate) + 1;
        $data['duration_nights'] = max(0, $data['duration_days'] - 1);

        // Kapasite güncellendi mi kontrol et
        if ($request->total_capacity != $tourDate->total_capacity) {
            $data['remaining_capacity'] = $request->total_capacity - $tourDate->sold_count - $tourDate->reserved_count;
        }

        unset($data['marketplace_prices']); // tarih tablosunun kolonu değil

        $tourDate->update($data);

        // Pazaryeri fiyat matrisi + tarihin temsili temel fiyatları
        $agencyId = auth()->user()->currentAgencyId();
        $mpInput = $request->input('marketplace_prices', []);
        $this->syncMarketplacePrices($tourDate, $mpInput, $agencyId);
        $this->applyPrimaryToDate($tourDate, $mpInput, $agencyId, $this->baseFieldMap, $tour->product?->primary_marketplace_id);

        return response()->json([
            'success' => true,
            'message' => 'Tur tarihi başarıyla güncellendi.'
        ]);
    }

    public function destroy(Tour $tour, $date)
    {
        $this->authorize('update', $tour);

        $tourDate = $tour->tourDates()->findOrFail($date);

        if ($tourDate->sold_count > 0) {
            return response()->json([
                'success' => false,
                'message' => 'Satışı olan tur tarihi silinemez.'
            ], 422);
        }

        $tourDate->delete();

        return response()->json([
            'success' => true,
            'message' => 'Tur tarihi başarıyla silindi.'
        ]);
    }

    public function toggleStatus(Tour $tour, $date)
    {
        $this->authorize('update', $tour);

        $tourDate = $tour->tourDates()->findOrFail($date);
        $tourDate->update(['is_active' => !$tourDate->is_active]);

        return response()->json([
            'success' => true,
            'is_active' => $tourDate->is_active,
            'message' => $tourDate->is_active ? 'Tur tarihi aktif edildi.' : 'Tur tarihi pasif edildi.'
        ]);
    }

    /**
     * Mevcut bir tarihi kopyalayarak yeni bir taslak tarih oluşturur.
     * Fiyat/kapasite/ödeme alanları kopyalanır; satış sayaçları sıfırlanır.
     */
    public function duplicate(Request $request, Tour $tour, $date)
    {
        $this->authorize('update', $tour);

        $request->validate(['offset_days' => 'nullable|integer|min:0|max:3650']);

        $source = $tour->tourDates()->findOrFail($date);

        $clone = $source->replicate([
            'code', 'sold_count', 'reserved_count', 'remaining_capacity',
            'view_count', 'inquiry_count', 'booking_attempt_count',
            'published_at', 'confirmed_at', 'confirmed_by',
        ]);

        // Yeni tarih için sayaçları ve tarihi ayarla
        $clone->sold_count = 0;
        $clone->reserved_count = 0;
        $clone->remaining_capacity = $source->total_capacity;
        $clone->status = 'draft';
        $clone->is_published = false;
        $clone->code = $this->generateDateCode($tour);

        // Yeni tarih = kaynağın BİTİŞİ + (offset gün). offset istekten gelir; yoksa periyottan otomatik.
        $offset = $request->filled('offset_days')
            ? max(0, (int) $request->input('offset_days'))
            : $this->inferOffsetAfterEnd($tour, $source);

        $duration = ($source->start_date && $source->end_date)
            ? $source->start_date->diffInDays($source->end_date)
            : max(0, (int) ($source->duration_days ?? 1) - 1);

        if ($source->end_date) {
            $clone->start_date = $source->end_date->copy()->addDays($offset);
            $clone->end_date = $clone->start_date->copy()->addDays($duration);
        } elseif ($source->start_date) {
            $clone->start_date = $source->start_date->copy()->addDays($offset);
        }

        $clone->save();

        // Pazaryeri fiyat matrisini de kopyala
        foreach ($source->marketplacePrices as $mp) {
            $clone->marketplacePrices()->create($mp->only([
                'marketplace_id', 'tour_class_id', 'currency', 'exchange_rate',
                'adult_price', 'child_price', 'child_price_1', 'child_price_2',
                'infant_price', 'single_supplement', 'extra_bed_price',
            ]));
        }

        return response()->json([
            'success' => true,
            'tourDate' => $clone,
            'message' => 'Tarih kopyalandı (bitişten ' . $offset . ' gün sonrasına).'
        ]);
    }

    /**
     * Seri tarih oluşturma: aynı fiyat/kapasite/ayarlarla birden çok tarih üretir.
     * frequency: weekly | interval (her N gün), count: kaç adet.
     */
    public function bulkStore(Request $request, Tour $tour)
    {
        $this->authorize('update', $tour);

        $activeCurrencies = auth()->user()->agency->getActiveCurrencies();
        $allowedCurrencies = $activeCurrencies->pluck('code')->toArray();

        $validator = Validator::make($request->all(), [
            'start_date' => 'required|date|after:today',
            'end_date' => 'required|date|after_or_equal:start_date',
            'total_capacity' => 'required|integer|min:1',
            'currency' => 'nullable|in:' . implode(',', $allowedCurrencies),
            'marketplace_prices' => 'nullable|array',
            'season_type' => 'required|in:low,medium,high,peak',
            'status' => 'required|in:draft,published,booking_open,booking_closed,confirmed,in_progress,completed,cancelled',
            // Seri ayarları
            'repeat_frequency' => 'required|in:weekly,biweekly,monthly,interval',
            'repeat_interval_days' => 'nullable|integer|min:1|max:365',
            'repeat_count' => 'required|integer|min:1|max:52',
        ], [
            'start_date.required' => 'Başlangıç tarihi zorunludur.',
            'start_date.after' => 'Başlangıç tarihi bugünden sonra olmalıdır.',
            'end_date.after_or_equal' => 'Bitiş tarihi başlangıç tarihinden önce olamaz.',
            'total_capacity.required' => 'Toplam kapasite zorunludur.',
            'currency.required' => 'Para birimi zorunludur.',
            'repeat_frequency.required' => 'Tekrar sıklığı zorunludur.',
            'repeat_count.required' => 'Kaç adet tarih oluşturulacağını giriniz.',
            'repeat_count.max' => 'En fazla 52 tarih oluşturulabilir.',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'errors' => $validator->errors(),
                'message' => 'Lütfen seri alanlarını doğru doldurunuz.'
            ], 422);
        }

        // Aralık gün sayısını sıklığa göre belirle
        $stepDays = match ($request->repeat_frequency) {
            'weekly' => 7,
            'biweekly' => 14,
            'monthly' => 30,
            'interval' => (int) ($request->repeat_interval_days ?: 7),
        };

        $baseStart = \Carbon\Carbon::parse($request->start_date);
        $baseEnd = \Carbon\Carbon::parse($request->end_date);
        $durationDays = $baseStart->diffInDays($baseEnd) + 1;

        // Tüm tarihlere uygulanacak ortak alanlar (fiyat/kapasite/ödeme vb.)
        $shared = $request->except([
            'start_date', 'end_date', 'repeat_frequency', 'repeat_interval_days', 'repeat_count', '_token',
            'marketplace_prices',
        ]);
        $shared['is_active'] = $request->has('is_active');
        $shared['is_published'] = !in_array($request->status, ['draft']);
        $shared['is_bookable'] = $request->has('is_bookable');
        $shared['guarantee_departure'] = $request->has('guarantee_departure');
        $shared['use_custom_payment_plan'] = $request->has('use_custom_payment_plan');
        $shared['auto_guarantee_on_min'] = $request->has('auto_guarantee_on_min');
        $shared['early_booking_rule'] = $this->sanitizeRule($request->input('early_booking_rule'));
        $shared['last_minute_rule'] = $this->sanitizeRule($request->input('last_minute_rule'));
        $shared['booking_deadline_rule'] = $this->sanitizeRule($request->input('booking_deadline_rule'));
        $shared['duration_days'] = $durationDays;
        $shared['duration_nights'] = max(0, $durationDays - 1);
        $shared['remaining_capacity'] = $request->total_capacity;

        $agencyId = auth()->user()->currentAgencyId();
        $mpInput = $request->input('marketplace_prices', []);

        $created = 0;
        for ($i = 0; $i < (int) $request->repeat_count; $i++) {
            $start = $baseStart->copy()->addDays($stepDays * $i);
            $end = $start->copy()->addDays($durationDays - 1);

            $data = $shared;
            $data['start_date'] = $start->toDateString();
            $data['end_date'] = $end->toDateString();
            $data['code'] = $this->generateDateCode($tour);

            $tourDate = $tour->tourDates()->create($data);

            // Aynı pazaryeri fiyat matrisini her seri tarihe uygula
            $this->syncMarketplacePrices($tourDate, $mpInput, $agencyId);
            $this->applyPrimaryToDate($tourDate, $mpInput, $agencyId, $this->baseFieldMap, $tour->product?->primary_marketplace_id);

            $created++;
        }

        \App\Models\Agency\ActivityLog::custom('create', $created . ' tur tarihi toplu oluşturuldu — ' . $tour->name, [
            'tour_id' => $tour->id,
            'count' => $created,
            'first_start' => $baseStart->toDateString(),
            'frequency' => $request->repeat_frequency,
        ]);

        return response()->json([
            'success' => true,
            'created' => $created,
            'message' => $created . ' adet tarih oluşturuldu.'
        ]);
    }
}
