<?php

namespace App\Http\Controllers\Agency;

use App\Http\Controllers\Controller;
use App\Models\Customer\Customer;
use App\Models\Agency\AgencySalesTarget;
use App\Models\Product\Product;
use App\Models\Product\ProductType;
use App\Models\Sale\Sale;
use App\Models\Sale\SaleActivity;
use App\Models\Sale\SaleItem;
use App\Models\User;
use App\Services\Operation\DepartureInventoryService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class SalesController extends Controller
{
    private function agencyId(): int
    {
        return Auth::user()->currentAgencyId();
    }

    /**
     * Ayarlardaki kurlara göre para birimi → TL çarpanı haritası (TRY = 1).
     * Pasif bırakılmış kurlar da dahil edilir; eski satışlar o birimde olabilir.
     */
    private function currencyRates(): array
    {
        $agency = Auth::user()->agency;
        $agency->getActiveCurrencies(); // hiç kur tanımı yoksa varsayılanları oluşturur

        $rates = [];
        foreach ($agency->currencies()->get() as $c) {
            $rate = (float) $c->exchange_rate;
            $rates[strtoupper((string) $c->code)] = $rate > 0 ? $rate : 1.0;
        }
        $rates['TRY'] = 1.0;

        return $rates;
    }

    /**
     * Sorgudaki tutar kolonunu para birimine göre gruplayıp ayar kurlarıyla
     * TL karşılığına çevirerek toplar (74 USD → 74 × kur TL).
     */
    private function sumInTry($query, string $column, array $rates): float
    {
        $total = 0.0;
        $rows = (clone $query)->reorder()
            ->select('currency', DB::raw("SUM({$column}) as t"))
            ->groupBy('currency')
            ->get();
        foreach ($rows as $row) {
            $code = strtoupper((string) ($row->currency ?: 'TRY'));
            $total += (float) $row->t * ($rates[$code] ?? 1.0);
        }

        return $total;
    }

    private function inventory(): DepartureInventoryService
    {
        return app(DepartureInventoryService::class);
    }

    private function operations(): \App\Services\Operation\OperationService
    {
        return app(\App\Services\Operation\OperationService::class);
    }

    /**
     * Bir satışa bağlı kalkışın kapasitesini yeniden sayar ve operasyon
     * durumunu (otomatik kesin kalkış vb.) değerlendirir.
     */
    private function refreshDeparture(Sale $sale): void
    {
        $this->inventory()->recountForSale($sale);
        $this->operations()->evaluateForSale($sale);
    }

    /**
     * Satışı seçilen tur tarihine (kalkışa) bağlar ve etkilenen tarih(ler)in
     * kapasitesini yeniden sayar. reservable_type (productable) üzerinden doğru
     * tarih modeli sınıfı belirlenir.
     */
    private function syncDeparture(Sale $sale, $tourDateId): void
    {
        $service = $this->inventory();

        $oldType = $sale->getOriginal('tour_date_type');
        $oldId = $sale->getOriginal('tour_date_id');

        $dateClass = $service->dateClassForProductable($sale->reservable_type);
        $tourDateId = $tourDateId ? (int) $tourDateId : null;

        if ($tourDateId && $dateClass) {
            $sale->tour_date_type = $dateClass;
            $sale->tour_date_id = $tourDateId;
        } else {
            $sale->tour_date_type = null;
            $sale->tour_date_id = null;
        }
        $sale->save();

        // Yeni bağlı kalkışı say + operasyon durumunu değerlendir
        $service->recountForSale($sale);
        $this->operations()->evaluateForSale($sale);

        // Bağ değiştiyse eski kalkışı da güncelle
        if ($oldType && $oldId && ($oldType !== $sale->tour_date_type || (int) $oldId !== (int) $sale->tour_date_id)) {
            if ($oldDate = $service->resolve($oldType, (int) $oldId)) {
                $service->recount($oldDate);
                $this->operations()->evaluate($oldDate);
            }
        }
    }

    // ─── INDEX ────────────────────────────────────────────────────────────────

    public function index(Request $request)
    {
        $agencyId = $this->agencyId();
        $view = $request->get('view', 'dashboard');

        $query = Sale::byAgency($agencyId)
            ->with(['customer', 'productType', 'creator', 'assignedAgent', 'reservable', 'tourDate'])
            ->orderBy('created_at', 'desc');

        // Filtreler
        if ($request->filled('status')) {
            $query->byStatus($request->status);
        }
        if ($request->filled('product_type_id')) {
            $query->byProductType($request->product_type_id);
        }
        // Diğer Satışlar: ürüne bağlı olmayan (elle başlık/fiyat girilmiş ya da hiç ürün eklenmemiş) satışlar
        if ($request->boolean('other')) {
            $query->whereNull('product_id')->whereNull('reservable_id');
        }
        if ($request->filled('search')) {
            $s = $request->search;
            $query->where(function ($q) use ($s) {
                $q->where('sale_code', 'like', "%$s%")
                    ->orWhereHas('customer', fn($cq) => $cq->where('first_name', 'like', "%$s%")
                        ->orWhere('last_name', 'like', "%$s%")
                        ->orWhere('emails', 'like', "%$s%"));
            });
        }
        if ($request->filled('date_from')) {
            $query->where('start_date', '>=', $request->date_from);
        }
        if ($request->filled('date_to')) {
            $query->where('start_date', '<=', $request->date_to);
        }

        // Görünüm Moduna Göre Veri Hazırlama
        $sales = null;
        $kanbanGroups = [];

        if ($view === 'list') {
            // Default: devam eden satışlar (status filtresi ve "diğer" filtresi yoksa)
            if (!$request->filled('status') && !$request->boolean('other')) {
                $query->whereIn('status', ['potential', 'offer_sent', 'revised']);
            }
            $allowedSorts = ['start_date', 'total_amount', 'status', 'payment_status', 'sale_code', 'created_at'];
        $sortBy = in_array($request->get('sort'), $allowedSorts) ? $request->get('sort') : 'created_at';
        $sortDir = $request->get('dir') === 'asc' ? 'asc' : 'desc';
        $query->reorder($sortBy, $sortDir);

        $perPage = (int) $request->input('per_page', 20);
        $perPage = in_array($perPage, [20, 50, 100, 200], true) ? $perPage : 20;
        $sales = $query->paginate($perPage)->withQueryString();
        } elseif ($view === 'kanban') {
            // Kanban için aktif ve tamamlanan satışları alıyoruz (İptal ve İade hariç)
            $kanbanData = $query->whereNotIn('status', ['cancelled', 'refunded'])
                ->get();

            $kanbanGroups = $kanbanData->groupBy('status');
        }

        // İstatistikler (Filtrelere göre dinamikleşsin istiyorsak aşağıdaki gibi baz query üzerinden gidebiliriz)
        // Ancak genellikle "Genel Durum" istendiği için tüm ajans verisi kalsın, biz sadece baz istatistiği filtrelenmiş yapalım
        $baseStatsQuery = Sale::byAgency($agencyId);
        if ($request->filled('product_type_id'))
            $baseStatsQuery->byProductType($request->product_type_id);
        if ($request->boolean('other'))
            $baseStatsQuery->whereNull('product_id')->whereNull('reservable_id');
        if ($request->filled('date_from'))
            $baseStatsQuery->where('start_date', '>=', $request->date_from);
        if ($request->filled('date_to'))
            $baseStatsQuery->where('start_date', '<=', $request->date_to);

        // Tutar toplamları ayarlardaki kurlarla TL'ye çevrilir (74 USD ≠ 74 TL)
        $rates = $this->currencyRates();

        $stats = [
            'total' => $baseStatsQuery->count(),
            'potential_val' => $this->sumInTry((clone $baseStatsQuery)->whereIn('status', ['potential', 'offer_sent', 'revised', 'pending']), 'total_amount', $rates),
            'won_val' => $this->sumInTry((clone $baseStatsQuery)->whereIn('status', ['confirmed', 'in_progress', 'completed']), 'total_amount', $rates),
            'paid_val' => $this->sumInTry(clone $baseStatsQuery, 'paid_amount', $rates),
            'unpaid_val' => $this->sumInTry((clone $baseStatsQuery)->whereNotIn('status', ['cancelled', 'refunded']), 'remaining_amount', $rates),
            'monthly_count' => (clone $baseStatsQuery)->whereMonth('created_at', now()->month)->count(),
            'pending_count' => (clone $baseStatsQuery)->whereIn('status', ['potential', 'offer_sent', 'revised', 'pending'])->count(),
        ];

        $productTypes = ProductType::active()->orderBy('sort_order')->get();

        // ─── SATIŞ HEDEFLERİ & FİLTRELEME ──────────────────────────────────────
        $targetPeriod = $request->get('period', 'year');
        $currentYear = $request->get('year', now()->year);
        $currentMonth = $request->get('month', now()->month);

        $targetsQuery = \App\Models\Agency\AgencySalesTarget::where('agency_id', $agencyId)
            ->where('target_year', $currentYear)
            ->where('target_period', $targetPeriod);
        
        if ($targetPeriod === 'month') {
            $targetsQuery->where('target_month', $currentMonth);
        }
        
        $targets = $targetsQuery->get();

        // Varsayılan hedef tipi: revenue (ciro)
        $targetType = $request->get('target_type', 'revenue');
        
        $achievedQuery = Sale::byAgency($agencyId)
            ->whereIn('status', ['confirmed', 'in_progress', 'completed'])
            ->whereYear('created_at', $currentYear);

        if ($targetPeriod === 'month') {
            $achievedQuery->whereMonth('created_at', $currentMonth);
        }

        if ($targetType === 'revenue') {
            // Para birimi bazında grupla, ayar kurlarıyla TL'ye çevirip tur tipine topla
            $achievedData = [];
            $achievedRows = $achievedQuery->select('product_type_id', 'currency', DB::raw('SUM(total_amount) as total'))
                ->groupBy('product_type_id', 'currency')
                ->get();
            foreach ($achievedRows as $row) {
                $code = strtoupper((string) ($row->currency ?: 'TRY'));
                $achievedData[$row->product_type_id ?? 0] = ($achievedData[$row->product_type_id ?? 0] ?? 0.0)
                    + (float) $row->total * ($rates[$code] ?? 1.0);
            }
        } else {
            $achievedData = $achievedQuery->select('product_type_id', DB::raw('COUNT(*) as count'))
                ->groupBy('product_type_id')
                ->pluck('count', 'product_type_id');
        }

        $salesTargets = [];
        foreach ($productTypes as $pt) {
            $target = $targets->where('product_type_id', $pt->id)->where('target_type', $targetType)->first();
            $targetValue = $target ? (float)$target->target_value : 0;
            $achievedValue = isset($achievedData[$pt->id]) ? (float)$achievedData[$pt->id] : 0;
            
            $salesTargets[$pt->id] = [
                'name' => $pt->name,
                'target' => $targetValue,
                'achieved' => $achievedValue,
                'percentage' => $targetValue > 0 ? min(100, round(($achievedValue / $targetValue) * 100, 1)) : 0,
                'color' => $pt->color ?? '#2563eb'
            ];
        }

        // Genel Hedef Hesabı
        $totalTarget = collect($salesTargets)->sum('target');
        $totalAchieved = collect($salesTargets)->sum('achieved');
        $totalPercentage = $totalTarget > 0 ? min(100, round(($totalAchieved / $totalTarget) * 100, 1)) : 0;

        // İlerleme Çizgisi Hesabı (Seçilen döneme göre)
        if ($targetPeriod === 'month') {
            $yearProgress = round((now()->day / now()->daysInMonth) * 100, 1);
        } else {
            $yearProgress = round((now()->dayOfYear() / 365) * 100, 1);
        }

        // ─── Diğer Satışlar (ürüne bağlı olmayan) özeti ──────────────────────────
        $otherBase = Sale::byAgency($agencyId)->whereNull('product_id')->whereNull('reservable_id');
        $otherSalesStats = [
            'count' => (clone $otherBase)->count(),
            'total' => $this->sumInTry((clone $otherBase)->whereNotIn('status', ['cancelled', 'refunded']), 'total_amount', $rates),
        ];

        return view('agency.sales.index', compact(
            'sales',
            'kanbanGroups',
            'stats',
            'productTypes',
            'view',
            'salesTargets',
            'totalTarget',
            'totalAchieved',
            'totalPercentage',
            'yearProgress',
            'currentYear',
            'currentMonth',
            'targetType',
            'targetPeriod',
            'otherSalesStats'
        ));
    }

    // ─── LEADS (Müşteri Adayları) ─────────────────────────────────────────────

    public function leads(Request $request)
    {
        $agencyId = $this->agencyId();

        $query = Sale::byAgency($agencyId)
            ->with(['customer', 'productType', 'creator', 'assignedAgent', 'reservable', 'tourDate'])
            ->whereIn('status', ['potential', 'offer_sent', 'revised'])
            ->orderBy('created_at', 'desc');

        if ($request->filled('search')) {
            $s = $request->search;
            $query->where(function ($q) use ($s) {
                $q->where('sale_code', 'like', "%$s%")
                    ->orWhereHas('customer', fn($cq) => $cq->where('first_name', 'like', "%$s%")
                        ->orWhere('last_name', 'like', "%$s%"));
            });
        }
        if ($request->filled('status')) {
            $query->where('status', $request->status);
        }
        if ($request->filled('date_from')) {
            $query->where('start_date', '>=', $request->date_from);
        }
        if ($request->filled('date_to')) {
            $query->where('start_date', '<=', $request->date_to);
        }

        $allowedSorts = ['start_date', 'total_amount', 'status', 'payment_status', 'sale_code', 'created_at'];
        $sortBy = in_array($request->get('sort'), $allowedSorts) ? $request->get('sort') : 'created_at';
        $sortDir = $request->get('dir') === 'asc' ? 'asc' : 'desc';
        $query->reorder($sortBy, $sortDir);

        $sales = $query->paginate(20)->withQueryString();
        $productTypes = ProductType::active()->orderBy('sort_order')->get();

        return view('agency.sales.leads', compact('sales', 'productTypes'));
    }

    // ─── DEALS (Anlaşmalar) ───────────────────────────────────────────────────

    public function deals(Request $request)
    {
        $agencyId = $this->agencyId();

        $query = Sale::byAgency($agencyId)
            ->with(['customer', 'productType', 'creator', 'assignedAgent', 'reservable', 'tourDate'])
            ->whereIn('status', ['confirmed', 'in_progress', 'completed'])
            ->orderBy('created_at', 'desc');

        if ($request->filled('search')) {
            $s = $request->search;
            $query->where(function ($q) use ($s) {
                $q->where('sale_code', 'like', "%$s%")
                    ->orWhereHas('customer', fn($cq) => $cq->where('first_name', 'like', "%$s%")
                        ->orWhere('last_name', 'like', "%$s%"));
            });
        }
        if ($request->filled('status')) {
            $query->where('status', $request->status);
        }
        if ($request->filled('date_from')) {
            $query->where('start_date', '>=', $request->date_from);
        }
        if ($request->filled('date_to')) {
            $query->where('start_date', '<=', $request->date_to);
        }

        $allowedSorts = ['start_date', 'total_amount', 'status', 'payment_status', 'sale_code', 'created_at'];
        $sortBy = in_array($request->get('sort'), $allowedSorts) ? $request->get('sort') : 'created_at';
        $sortDir = $request->get('dir') === 'asc' ? 'asc' : 'desc';
        $query->reorder($sortBy, $sortDir);

        $sales = $query->paginate(20)->withQueryString();
        $productTypes = ProductType::active()->orderBy('sort_order')->get();

        return view('agency.sales.deals', compact('sales', 'productTypes'));
    }

    // ─── CANCELLATIONS (İptal ve İadeler) ─────────────────────────────────────

    public function cancellations(Request $request)
    {
        $agencyId = $this->agencyId();

        $query = Sale::byAgency($agencyId)
            ->with(['customer', 'productType', 'creator', 'assignedAgent', 'reservable', 'tourDate'])
            ->whereIn('status', ['cancelled', 'refunded'])
            ->orderBy('created_at', 'desc');

        if ($request->filled('search')) {
            $s = $request->search;
            $query->where(function ($q) use ($s) {
                $q->where('sale_code', 'like', "%$s%")
                    ->orWhereHas('customer', fn($cq) => $cq->where('first_name', 'like', "%$s%")
                        ->orWhere('last_name', 'like', "%$s%"));
            });
        }
        if ($request->filled('status')) {
            $query->where('status', $request->status);
        }
        if ($request->filled('date_from')) {
            $query->where('start_date', '>=', $request->date_from);
        }
        if ($request->filled('date_to')) {
            $query->where('start_date', '<=', $request->date_to);
        }

        $allowedSorts = ['start_date', 'total_amount', 'status', 'payment_status', 'sale_code', 'created_at'];
        $sortBy = in_array($request->get('sort'), $allowedSorts) ? $request->get('sort') : 'created_at';
        $sortDir = $request->get('dir') === 'asc' ? 'asc' : 'desc';
        $query->reorder($sortBy, $sortDir);

        $sales = $query->paginate(20)->withQueryString();
        $productTypes = ProductType::active()->orderBy('sort_order')->get();

        return view('agency.sales.cancellations', compact('sales', 'productTypes'));
    }

    // ─── CREATE / STORE ───────────────────────────────────────────────────────

    public function create(Request $request)
    {
        $agencyId = $this->agencyId();

        $productTypes = ProductType::active()->orderBy('sort_order')->get();

        $customers = Customer::byAgency($agencyId)
            ->where('status', '!=', 'blocked')
            ->orderBy('first_name')
            ->get(['id', 'first_name', 'last_name', 'emails', 'phone']);

        $agents = User::byAgency($agencyId)
            ->where('is_active', true)
            ->orderBy('first_name')
            ->get(['id', 'first_name', 'last_name']);

        $products = collect();
        $selectedProductType = null;
        $extraFields = [];

        if ($request->filled('product_type_id')) {
            $selectedProductType = ProductType::find($request->product_type_id);
            if ($selectedProductType) {
                $products = Product::byAgency($agencyId)
                    ->byProductType($selectedProductType->id)
                    ->bookable()
                    ->orderBy('name')
                    ->get(['id', 'name', 'base_price', 'currency', 'slug', 'productable_type', 'productable_id']);

                $extraFields = Sale::extraFieldsFor($selectedProductType->code);
            }
        }

        $preselectedCustomer = null;
        if ($request->filled('customer_id')) {
            $preselectedCustomer = Customer::byAgency($agencyId)->find($request->customer_id);

            // Eğer müşteri listede yoksa (örneğin engellenmişse veya filtreye takılmışsa) listeye ekliyoruz
            if ($preselectedCustomer && !$customers->contains('id', $preselectedCustomer->id)) {
                $customers->push($preselectedCustomer);
            }
        }

        return view('agency.sales.create', compact(
            'productTypes',
            'customers',
            'agents',
            'products',
            'selectedProductType',
            'extraFields',
            'preselectedCustomer'
        ));
    }

    public function quickCreate()
    {
        $agencyId = $this->agencyId();

        $productTypes = ProductType::active()->orderBy('sort_order')->get();

        $customers = Customer::byAgency($agencyId)
            ->where('status', '!=', 'blocked')
            ->orderBy('first_name')
            ->get(['id', 'first_name', 'last_name', 'emails', 'phone']);

        $agents = User::byAgency($agencyId)
            ->where('is_active', true)
            ->orderBy('first_name')
            ->get(['id', 'first_name', 'last_name']);

        $products = Product::byAgency($agencyId)
            ->with('productType')
            ->bookable()
            ->orderBy('name')
            ->get(['id', 'name', 'base_price', 'currency', 'product_type_id', 'productable_type', 'productable_id']);

        $activeCurrencies = auth()->user()->agency->getActiveCurrencies();
        $taxRates = auth()->user()->agency->getActiveTaxRates(\App\Models\Agency\TaxType::CODE_KDV);

        // Tedarikçi hizmet kataloğu (otel odası, transfer, menü, vize...) — satılabilir fiyat kalemleri.
        $supplierCatalog = $this->supplierCatalog($agencyId);

        return view('agency.sales.quick-create', compact('productTypes', 'customers', 'agents', 'products', 'activeCurrencies', 'taxRates', 'supplierCatalog'));
    }

    /**
     * Satış kataloğu için acentenin aktif tedarikçi fiyat kalemlerini normalize eder.
     * Otel odası / transfer / menü vb. hepsi supplier_price_items'ta; tip farkı metadata'da.
     */
    private function supplierCatalog(int $agencyId)
    {
        $typeLabels = \App\Models\Supplier\Supplier::supplierTypes();
        $typeIcons = [
            'hotel' => 'fa-hotel',
            'transportation' => 'fa-bus',
            'restaurant' => 'fa-utensils',
            'insurance' => 'fa-shield-heart',
            'visa' => 'fa-passport',
            'airline' => 'fa-plane',
        ];
        $roomTypes = ['single' => 'Single', 'double' => 'Double', 'triple' => 'Triple', 'child_0_6' => 'Çocuk 0-6', 'child_0_12' => 'Çocuk 0-12'];

        $items = \App\Models\Supplier\SupplierPriceItem::whereHas('priceList', function ($q) use ($agencyId) {
                $q->where('agency_id', $agencyId)->where('is_active', true);
            })
            ->with('priceList.supplier:id,type,company_name,first_name,last_name,supplier_type')
            ->orderByDesc('id')
            ->get();

        return $items->map(function ($it) use ($typeLabels, $typeIcons, $roomTypes) {
            $meta = is_array($it->metadata) ? $it->metadata : [];
            $sup = $it->priceList?->supplier;
            $type = $sup?->supplier_type ?? 'other';

            // Tipe göre okunur alt başlık (metadata'dan)
            $subtitle = match ($type) {
                'hotel' => trim(implode(' · ', array_filter([
                    $roomTypes[$meta['room_type'] ?? ''] ?? ($meta['room_type'] ?? null),
                    $meta['board_type'] ?? null,
                    isset($meta['market']) ? ucfirst($meta['market']) : null,
                ]))),
                'transportation' => trim(($meta['from_location'] ?? '') . (!empty($meta['to_location']) ? ' → ' . $meta['to_location'] : '') . (!empty($meta['vehicle_type']) ? ' · ' . $meta['vehicle_type'] : '')),
                'restaurant' => $meta['menu_name'] ?? '',
                'insurance' => $meta['policy_name'] ?? '',
                'visa' => trim(($meta['visa_type'] ?? '') . (!empty($meta['country']) ? ' · ' . strtoupper($meta['country']) : '')),
                'airline' => trim(($meta['route'] ?? '') . (!empty($meta['flight_class']) ? ' · ' . $meta['flight_class'] : '')),
                default => '',
            };

            return [
                'id' => $it->id,
                'title' => $it->title,
                'subtitle' => $subtitle,
                'sale_price' => (float) $it->sale_price,
                'net_price' => (float) $it->net_price,
                'currency' => $it->currency ?: 'TRY',
                'tax_rate' => (float) $it->tax_rate,
                'supplier_name' => $sup?->full_name ?: '—',
                'type' => $type,
                'type_label' => $typeLabels[$type] ?? ucfirst($type),
                'type_icon' => $typeIcons[$type] ?? 'fa-cube',
            ];
        })->values();
    }

    /**
     * "Yeni Satış"a basınca anında potansiyel (müşterisiz) satış oluşturur → quick-view URL döner.
     * Ürün modülündeki taslak deseninin (openDraftQuickView) satış muadili.
     */
    public function quickDraft(Request $request)
    {
        $agencyId = $this->agencyId();
        try {
            $sale = new Sale();
            $sale->agency_id = $agencyId;
            $sale->status = 'potential';
            $sale->payment_status = 'unpaid';
            $sale->start_date = today();
            $sale->adult_count = 1;
            $sale->child_count = 0;
            $sale->infant_count = 0;
            $sale->currency = 'TRY';
            $sale->assigned_to = Auth::id();
            $sale->source = 'manual';

            // Ürün tipi ekranından açıldıysa taslağa ön-tanımla → quick-create formunda seçili gelir
            $ptId = (int) $request->input('product_type_id');
            if ($ptId && ProductType::whereKey($ptId)->exists()) {
                $sale->product_type_id = $ptId;
            }

            // Müşteri kartından açıldıysa müşteriyi ön-tanımla
            $custId = (int) $request->input('customer_id');
            if ($custId && \App\Models\Customer\Customer::where('id', $custId)->where('agency_id', $agencyId)->exists()) {
                $sale->customer_id = $custId;
            }

            $sale->save(); // sale_code boot() ile üretilir

            return response()->json([
                'success' => true,
                'sale_id' => $sale->id,
                'quick_view_url' => route('agency.sales.quick-view', $sale),
            ]);
        } catch (\Throwable $e) {
            Log::error('Sale quick-draft error', ['message' => $e->getMessage(), 'agency' => $agencyId]);
            return response()->json(['success' => false, 'message' => 'Taslak oluşturulamadı: ' . $e->getMessage()], 500);
        }
    }

    /**
     * Quick-view alanları değiştikçe debounce'lu tam-durum otomatik kaydı (submit yerine).
     */
    public function quickUpdate(Request $request, Sale $sale)
    {
        $this->authorizeAgency($sale);
        try {
            DB::beginTransaction();

            $fields = ['customer_id', 'title', 'start_date', 'end_date', 'product_type_id', 'assigned_to',
                'adult_count', 'child_count', 'infant_count', 'total_amount', 'paid_amount',
                'currency', 'payment_status', 'status', 'pickup_location', 'flight_number',
                'customer_note', 'internal_note'];
            foreach ($fields as $f) {
                if (!$request->has($f)) continue;
                $v = $request->input($f);
                if (in_array($f, ['customer_id', 'product_type_id', 'assigned_to', 'end_date'], true) && $v === '') $v = null;
                $sale->{$f} = $v;
            }

            // Ürün → reservable bağı (boşsa temizle)
            if ($request->has('product_id')) {
                $pid = $request->input('product_id');
                if (!empty($pid) && ($product = Product::find($pid)) && $product->productable_type) {
                    $sale->product_id = $product->id;
                    $sale->reservable_type = $product->productable_type;
                    $sale->reservable_id = $product->productable_id;
                } else {
                    $sale->product_id = null;
                    $sale->reservable_type = null;
                    $sale->reservable_id = null;
                }
            }

            $sale->save();

            // Kalemler (gönderildiyse sıfırla + yeniden yaz)
            if ($request->has('items')) {
                $sale->items()->delete();
                foreach ((array) $request->input('items', []) as $it) {
                    if (empty($it['name'])) continue;
                    $taxRate = (float) ($it['tax_rate'] ?? 0);
                    $qty = (float) ($it['quantity'] ?? 1);
                    $price = (float) ($it['unit_price'] ?? 0);
                    $taxAmt = round($qty * $price * ($taxRate / 100), 2);
                    SaleItem::create([
                        'sale_id' => $sale->id,
                        'product_id' => !empty($it['product_id']) ? $it['product_id'] : null,
                        'itemable_type' => !empty($it['itemable_type']) ? $it['itemable_type'] : null,
                        'itemable_id' => !empty($it['itemable_id']) ? $it['itemable_id'] : null,
                        'name' => $it['name'],
                        'quantity' => $qty,
                        'unit_price' => $price,
                        'tax_rate' => $taxRate,
                        'tax_amount' => $taxAmt,
                        'total_price' => round($qty * $price + $taxAmt, 2),
                        'currency' => $it['currency'] ?? 'TRY',
                    ]);
                }
                if ($sale->items()->exists()) {
                    $sale->calculateTotals(); // kalem varsa toplamı kalemlerden hesapla
                }
            }

            // Kalkışa bağla (tur tarihi seçiliyse)
            $this->syncDeparture($sale, $request->input('tour_date_id'));

            DB::commit();
            return response()->json([
                'success' => true,
                'sale_id' => $sale->id,
                'sale_code' => $sale->sale_code,
                'total_amount' => (float) $sale->total_amount,
                'remaining_amount' => (float) $sale->remaining_amount,
            ]);
        } catch (\Throwable $e) {
            DB::rollBack();
            Log::error('Sale quick-update error', ['sale' => $sale->id, 'message' => $e->getMessage()]);
            return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
        }
    }

    public function store(Request $request)
    {
        $agencyId = $this->agencyId();

        $productType = null;
        $extraFields = [];

        if ($request->filled('product_type_id')) {
            $productType = ProductType::find($request->product_type_id);
            if ($productType) {
                $extraFields = Sale::extraFieldsFor($productType->code);
            }
        }

        $rules = [
            'customer_id' => 'required|exists:customers,id',
            'product_type_id' => 'nullable|exists:product_types,id',
            'product_id' => 'nullable|exists:products,id',
            'start_date' => 'required|date',
            'end_date' => 'nullable|date|after_or_equal:start_date',
            'pickup_time' => 'nullable|date',
            'adult_count' => 'required|integer|min:1',
            'child_count' => 'nullable|integer|min:0',
            'infant_count' => 'nullable|integer|min:0',
            'unit_price' => 'nullable|numeric|min:0',
            'child_price' => 'nullable|numeric|min:0',
            'infant_price' => 'nullable|numeric|min:0',
            'discount_rate' => 'nullable|numeric|min:0|max:100',
            'discount_amount' => 'nullable|numeric|min:0',
            'tax_amount' => 'nullable|numeric|min:0',
            'total_amount' => 'nullable|numeric|min:0',
            'currency' => 'nullable|string|max:3',
            'status' => 'required|in:potential,offer_sent,revised,pending,confirmed,in_progress,completed,cancelled,refunded',
            'payment_status' => 'required|in:unpaid,partial,paid,refunded',
            'paid_amount' => 'nullable|numeric|min:0',
            'pickup_location' => 'nullable|string|max:255',
            'dropoff_location' => 'nullable|string|max:255',
            'flight_number' => 'nullable|string|max:30',
            'source' => 'nullable|string|max:50',
            'assigned_to' => 'nullable|exists:users,id',
            'customer_note' => 'nullable|string',
            'internal_note' => 'nullable|string',
        ];

        foreach ($extraFields as $field) {
            $rules["extra_data.{$field['key']}"] = 'nullable|string|max:255';
        }

        try {
            $validated = $request->validate($rules);

            $customer = Customer::byAgency($agencyId)->findOrFail($validated['customer_id']);

            DB::beginTransaction();

            $sale = new Sale($validated);
            $sale->agency_id = $agencyId;
            $sale->remaining_amount = (string) max(0.0, (float) ($validated['total_amount'] ?? 0) - (float) ($validated['paid_amount'] ?? 0));

            if (!empty($validated['product_id'])) {
                $product = Product::find($validated['product_id']);
                if ($product?->productable_type && $product?->productable_id) {
                    $sale->reservable_type = $product->productable_type;
                    $sale->reservable_id = $product->productable_id;
                }
            }

            $sale->save();

            // ─── ÜRÜNLERİ KAYDET ─────────────────────────────────────────────
            if ($request->has('items') && is_array($request->items)) {
                foreach ($request->items as $itemData) {
                    if (empty($itemData['name'])) continue;
                    $taxRate = (float) ($itemData['tax_rate'] ?? 0);
                    $qty     = (float) ($itemData['quantity'] ?? 1);
                    $price   = (float) ($itemData['unit_price'] ?? 0);
                    $taxAmt  = round($qty * $price * ($taxRate / 100), 2);
                    $total   = round($qty * $price + $taxAmt, 2);

                    // Tedarikçi hizmeti / tur kalemi için polimorfik itemable + metadata izlenebilirliği
                    $itemableType = !empty($itemData['itemable_type']) ? $itemData['itemable_type'] : null;
                    $itemableId   = !empty($itemData['itemable_id']) ? $itemData['itemable_id'] : null;
                    $metadata     = (isset($itemData['metadata']) && is_array($itemData['metadata'])) ? $itemData['metadata'] : null;

                    SaleItem::create([
                        'sale_id'       => $sale->id,
                        'product_id'    => !empty($itemData['product_id']) ? $itemData['product_id'] : null,
                        'itemable_type' => $itemableType,
                        'itemable_id'   => $itemableId,
                        'name'          => $itemData['name'],
                        'quantity'      => $qty,
                        'unit_price'    => $price,
                        'tax_rate'      => $taxRate,
                        'tax_amount'    => $taxAmt,
                        'total_price'   => $total,
                        'currency'      => $itemData['currency'] ?? 'TRY',
                        'metadata'      => $metadata,
                    ]);
                }
            }

            $sale->calculateTotals();

            // ─── YOLCULARI KAYDET ─────────────────────────────────────────────
            if ($request->has('passengers')) {
                foreach ($request->passengers as $pData) {
                    $passengerId = $pData['id'] ?? null;

                    // Eğer yolcu zaten varsa, bilgilerini güncelle
                    if ($passengerId) {
                        $p = \App\Models\CustomerPassenger::find($passengerId);
                        if ($p) {
                            $p->first_name = $pData['first_name'] ?? $p->first_name;
                            $p->last_name = $pData['last_name'] ?? $p->last_name;
                            $p->gender = $pData['gender'] ?? $p->gender;
                            $p->birth_date = !empty($pData['birth_date']) ? $pData['birth_date'] : $p->birth_date;
                            $p->national_id = $pData['national_id'] ?? $p->national_id;
                            $p->phone = $pData['phone'] ?? $p->phone;
                            $p->email = $pData['email'] ?? $p->email;
                            $p->relationship = $pData['relationship'] ?? $p->relationship;
                            $p->save();
                        }
                    }

                    // Eğer yeni yolcu ise CustomerPassenger olarak kaydet
                    if (!$passengerId && !empty($pData['first_name'])) {
                        $newP = new \App\Models\CustomerPassenger();
                        $newP->customer_id = $customer->id;
                        $newP->first_name = $pData['first_name'];
                        $newP->last_name = $pData['last_name'] ?? '';
                        $newP->gender = $pData['gender'] ?? null;
                        $newP->birth_date = $pData['birth_date'] ?? null;
                        $newP->national_id = $pData['national_id'] ?? null;
                        $newP->passport_number = $pData['passport_number'] ?? null;
                        $newP->passport_expiry = $pData['passport_expiry'] ?? null;
                        $newP->phone = $pData['phone'] ?? null;
                        $newP->email = $pData['email'] ?? null;
                        $newP->relationship = $pData['relationship'] ?? null;
                        $newP->created_by = Auth::id();
                        $newP->save();
                        $passengerId = $newP->id;
                    }

                    if ($passengerId) {
                        $sale->passengers()->attach($passengerId, [
                            'room_number' => $pData['room_number'] ?? null,
                            'seat_number' => $pData['seat_number'] ?? null,
                            'special_request' => $pData['special_request'] ?? null,
                        ]);
                    }
                }
            }

            // Kalkışa bağla + envanteri güncelle
            $this->syncDeparture($sale, $request->input('tour_date_id'));

            if ((float) $sale->total_amount > 0) {
                $customer->recordBooking((float) $sale->total_amount);
            } else {
                $customer->update(['last_booking_date' => today()]);
            }


            DB::commit();

            if ($request->expectsJson()) {
                return response()->json([
                    'success' => true,
                    'message' => 'Rezervasyon başarıyla oluşturuldu.',
                    'sale_id' => $sale->id,
                    'sale_code' => $sale->sale_code
                ]);
            }

            return redirect()
                ->route('agency.sales.show', $sale)
                ->with('success', 'Rezervasyon başarıyla oluşturuldu. Kod: ' . $sale->sale_code);

        } catch (\Illuminate\Validation\ValidationException $e) {
            Log::warning('Sale store validation error', ['errors' => $e->errors(), 'agency' => $agencyId]);
            if ($request->expectsJson()) {
                return response()->json(['success' => false, 'errors' => $e->errors()], 422);
            }
            throw $e;
        } catch (\Throwable $e) {
            DB::rollBack();
            Log::error('Sale store error', ['message' => $e->getMessage(), 'agency' => $agencyId]);
            if ($request->expectsJson()) {
                return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
            }
            return back()->withInput()->with('error', 'Rezervasyon oluşturulurken bir hata oluştu: ' . $e->getMessage());
        }
    }

    // ─── SHOW ─────────────────────────────────────────────────────────────────

    public function show(Sale $sale)
    {
        $this->authorizeAgency($sale);

        $sale->load([
            'customer',
            'productType',
            'product',
            'reservable',
            'creator',
            'assignedAgent',
            'confirmedBy',
            'cancelledBy',
        ]);

        $productType = $sale->productType;
        $extraFields = $productType ? Sale::extraFieldsFor($productType->code) : [];

        return view('agency.sales.show', compact('sale', 'extraFields', 'productType'));
    }

    // ─── EDIT / UPDATE ────────────────────────────────────────────────────────

    public function edit(Sale $sale)
    {
        $this->authorizeAgency($sale);
        $agencyId = $this->agencyId();

        $productTypes = ProductType::active()->orderBy('sort_order')->get();

        $customers = Customer::byAgency($agencyId)
            ->orderBy('first_name')
            ->get(['id', 'first_name', 'last_name', 'emails', 'phone']);

        $agents = User::byAgency($agencyId)
            ->where('is_active', true)
            ->orderBy('first_name')
            ->get(['id', 'first_name', 'last_name']);

        $products = collect();
        $extraFields = [];
        $selectedProductType = $sale->productType;

        if ($selectedProductType) {
            $products = Product::byAgency($agencyId)
                ->byProductType($selectedProductType->id)
                ->bookable()
                ->orderBy('name')
                ->get(['id', 'name', 'base_price', 'currency', 'productable_type', 'productable_id']);

            $extraFields = Sale::extraFieldsFor($selectedProductType->code);
        }

        return view('agency.sales.edit', compact(
            'sale',
            'productTypes',
            'customers',
            'agents',
            'products',
            'selectedProductType',
            'extraFields'
        ));
    }

    public function update(Request $request, Sale $sale)
    {
        $this->authorizeAgency($sale);

        $productType = $sale->productType;
        $extraFields = $productType ? Sale::extraFieldsFor($productType->code) : [];

        $rules = [
            'customer_id' => 'required|exists:customers,id',
            'product_type_id' => 'nullable|exists:product_types,id',
            'product_id' => 'nullable|exists:products,id',
            'start_date' => 'required|date',
            'end_date' => 'nullable|date|after_or_equal:start_date',
            'pickup_time' => 'nullable|date',
            'adult_count' => 'required|integer|min:1',
            'child_count' => 'nullable|integer|min:0',
            'infant_count' => 'nullable|integer|min:0',
            'unit_price' => 'nullable|numeric|min:0',
            'child_price' => 'nullable|numeric|min:0',
            'infant_price' => 'nullable|numeric|min:0',
            'discount_rate' => 'nullable|numeric|min:0|max:100',
            'discount_amount' => 'nullable|numeric|min:0',
            'tax_amount' => 'nullable|numeric|min:0',
            'status' => 'required|in:pending,confirmed,in_progress,completed,cancelled,refunded',
            'payment_status' => 'required|in:unpaid,partial,paid,refunded',
            'paid_amount' => 'nullable|numeric|min:0',
            'pickup_location' => 'nullable|string|max:255',
            'dropoff_location' => 'nullable|string|max:255',
            'flight_number' => 'nullable|string|max:30',
            'assigned_to' => 'nullable|exists:users,id',
            'customer_note' => 'nullable|string',
            'internal_note' => 'nullable|string',
            'cancellation_reason' => 'nullable|string',
        ];

        foreach ($extraFields as $field) {
            $rules["extra_data.{$field['key']}"] = 'nullable';
        }

        try {
            $validated = $request->validate($rules);

            DB::beginTransaction();

            $sale->update($validated);
            $sale->calculateTotals();

            if ($request->has('passengers')) {
                $passengerIds = [];
                foreach ($request->passengers as $pData) {
                    $passengerId = $pData['id'] ?? null;

                    // Eğer yolcu zaten varsa, bilgilerini güncelle
                    if ($passengerId) {
                        $p = \App\Models\CustomerPassenger::find($passengerId);
                        if ($p) {
                            $p->first_name = $pData['first_name'] ?? $p->first_name;
                            $p->last_name = $pData['last_name'] ?? $p->last_name;
                            $p->gender = $pData['gender'] ?? $p->gender;
                            $p->birth_date = !empty($pData['birth_date']) ? $pData['birth_date'] : $p->birth_date;
                            $p->national_id = $pData['national_id'] ?? $p->national_id;
                            $p->phone = $pData['phone'] ?? $p->phone;
                            $p->email = $pData['email'] ?? $p->email;
                            $p->relationship = $pData['relationship'] ?? $p->relationship;
                            $p->save();
                        }
                    }

                    // Eğer yeni yolcu ise CustomerPassenger olarak kaydet
                    if (!$passengerId && !empty($pData['first_name'])) {
                        $newP = new \App\Models\CustomerPassenger();
                        $newP->customer_id = $sale->customer_id;
                        $newP->first_name = $pData['first_name'];
                        $newP->last_name = $pData['last_name'] ?? '';
                        $newP->gender = $pData['gender'] ?? null;
                        $newP->birth_date = $pData['birth_date'] ?? null;
                        $newP->national_id = $pData['national_id'] ?? null;
                        $newP->passport_number = $pData['passport_number'] ?? null;
                        $newP->passport_expiry = $pData['passport_expiry'] ?? null;
                        $newP->phone = $pData['phone'] ?? null;
                        $newP->email = $pData['email'] ?? null;
                        $newP->relationship = $pData['relationship'] ?? null;
                        $newP->created_by = Auth::id();
                        $newP->save();
                        $passengerId = $newP->id;
                    }

                    if ($passengerId) {
                        $passengerIds[$passengerId] = [
                            'room_number' => $pData['room_number'] ?? null,
                            'seat_number' => $pData['seat_number'] ?? null,
                            'special_request' => $pData['special_request'] ?? null,
                        ];
                    }
                }
                $sale->passengers()->sync($passengerIds);
            }

            if (!empty($validated['product_id'])) {

                $product = \App\Models\Product\Product::find($validated['product_id']);
                if ($product?->productable_type && $product?->productable_id) {
                    $sale->reservable_type = $product->productable_type;
                    $sale->reservable_id = $product->productable_id;
                    $sale->save();
                }
            }

            if ($validated['status'] === 'cancelled' && !$sale->cancelled_at) {
                $sale->cancelled_at = now();
                $sale->cancelled_by = auth()->id();
                $sale->save();
            }

            // Kalkış bağını güncelle + envanteri yeniden say (durum/pax/tarih değişmiş olabilir)
            $this->syncDeparture($sale, $request->input('tour_date_id', $sale->tour_date_id));

            DB::commit();

            return back()->with('success', 'Rezervasyon başarıyla güncellendi.');

        } catch (\Illuminate\Validation\ValidationException $e) {
            throw $e;
        } catch (\Throwable $e) {
            DB::rollBack();
            Log::error('Sale update error', ['message' => $e->getMessage(), 'sale_id' => $sale->id]);
            return back()->withInput()->with('error', 'Güncelleme sırasında hata: ' . $e->getMessage());
        }
    }

    // ─── DELETE ───────────────────────────────────────────────────────────────

    public function destroy(Sale $sale)
    {
        $this->authorizeAgency($sale);

        $code = $sale->sale_code;
        $sale->delete();
        $this->refreshDeparture($sale);

        return redirect()
            ->route('agency.sales.index')
            ->with('success', "$code numaralı rezervasyon silindi.");
    }

    public function bulkDelete(Request $request)
    {
        $request->validate([
            'ids' => 'required|array',
            'ids.*' => 'integer',
        ]);

        $sales = Sale::byAgency($this->agencyId())->whereIn('id', $request->ids)->get();
        foreach ($sales as $sale) {
            $sale->delete();
            $this->refreshDeparture($sale);
        }

        return response()->json([
            'success' => true,
            'message' => $sales->count() . ' satış kaydı silindi.',
        ]);
    }

    // ─── QUICK ACTIONS ────────────────────────────────────────────────────────

    public function confirm(Request $request, Sale $sale)
    {
        $this->authorizeAgency($sale);
        $sale->confirm();
        $this->refreshDeparture($sale);
        return back()->with('success', 'Rezervasyon onaylandı.');
    }

    public function cancel(Request $request, Sale $sale)
    {
        $this->authorizeAgency($sale);
        $request->validate(['reason' => 'nullable|string|max:500']);
        $sale->cancel($request->reason ?? '');
        $this->refreshDeparture($sale);
        return back()->with('success', 'Rezervasyon iptal edildi.');
    }

    public function addPayment(Request $request, Sale $sale)
    {
        $this->authorizeAgency($sale);
        $request->validate(['amount' => 'required|numeric|min:0.01']);

        $newPaid = (float) $sale->paid_amount + (float) $request->amount;
        $sale->update([
            'paid_amount' => $newPaid,
            'remaining_amount' => number_format(max(0, (float) $sale->total_amount - $newPaid), 2, '.', ''),
            'payment_status' => $newPaid >= (float) $sale->total_amount ? 'paid'
                : ($newPaid > 0 ? 'partial' : 'unpaid'),
        ]);

        // Otomatik görev: ödeme alındı (her ödeme ayrı görev üretebilsin diye dedupe_suffix)
        app(\App\Services\Task\AutoTaskService::class)->fireSafe('payment_received', $sale, $sale->autoTaskContext() + [
            'amount' => number_format((float) $request->amount, 2, ',', '.'),
            'currency' => $sale->currency,
            'paid_suffix' => $sale->payment_status === 'paid' ? ' — tamamı tahsil edildi' : '',
            'dedupe_suffix' => 'p' . now()->format('YmdHis'),
        ], $sale->autoTaskRelations());

        return back()->with('success', number_format($request->amount, 2) . ' ' . $sale->currency . ' ödeme kaydedildi.');
    }

    // ─── AJAX: Ürün tipi → ürünler + extra alanlar ───────────────────────────

    public function getProductsByType(Request $request)
    {
        $agencyId = $this->agencyId();
        $productType = ProductType::find($request->product_type_id);

        if (!$productType) {
            return response()->json(['products' => [], 'extra_fields' => [], 'type_code' => null]);
        }

        $products = Product::byAgency($agencyId)
            ->byProductType($productType->id)
            ->with(['productable.departureCity'])
            ->bookable()
            ->orderBy('name')
            ->get(['id', 'name', 'base_price', 'currency', 'slug', 'productable_type', 'productable_id', 'code'])
            ->map(function($p) {
                $item = [
                    'id' => $p->id,
                    'name' => $p->name,
                    'code' => $p->code,
                    'base_price' => (float) $p->base_price,
                    'currency' => $p->currency,
                    'has_dates' => !empty($p->productable_type),
                    'productable_type' => $p->productable_type,
                    'productable_id' => $p->productable_id,
                ];

                if ($p->productable) {
                    $item['duration'] = $p->productable->duration_hours ?? ($p->productable->duration_days ?? null);
                    $item['departure_city'] = $p->productable->departureCity?->name;
                    $item['visit_locations'] = is_array($p->productable->visit_locations) ? implode(' - ', array_slice($p->productable->visit_locations, 0, 3)) : null;
                    $item['meal_included'] = $p->productable->meal_included ?? false;
                }

                return $item;
            });

        $extraFields = Sale::extraFieldsFor($productType->code);

        return response()->json([
            'products' => $products,
            'extra_fields' => $extraFields,
            'type_code' => $productType->code,
        ]);
    }

    // ─── AJAX: Ürün → tarihler + fiyatlar ────────────────────────────────────

    public function getProductDates(Request $request)
    {
        $product = Product::find($request->product_id);

        if (!$product) {
            return response()->json(['dates' => [], 'has_dates' => false]);
        }

        $dates = [];
        $hasDates = false;

        // Polimorfik ilişkiyle bağlı modeli belirle
        $productableType = $product->productable_type ?? '';

        // Kültür/yurtdışı fiyatları tarih tablosunda değil pazaryeri matrisinde:
        // ürünün ANA PAZARININ taban (sınıfsız) satırını seç; yoksa herhangi bir satıra düş.
        $pickRow = function ($d) use ($product) {
            $rows = $d->marketplacePrices;
            $pmId = $product->primary_marketplace_id;
            $mine = $pmId ? $rows->where('marketplace_id', $pmId) : collect();
            $pool = $mine->isNotEmpty() ? $mine : $rows;
            return $pool->firstWhere('tour_class_id', null)
                ?? $pool->sortBy(fn ($r) => (float) $r->adult_price)->first();
        };

        if (str_contains($productableType, 'InternationalTour')) {
            // Yurt Dışı Turu → InternationalTourDate (international_tour_dates)
            $tourDates = \App\Models\InternationalTour\InternationalTourDate::where('international_tour_id', $product->productable_id)
                ->where('is_bookable', true)
                ->where('is_active', true)
                ->where('start_date', '>=', now()->toDateString())
                ->orderBy('start_date')
                ->with('marketplacePrices')
                ->get(['id', 'start_date', 'end_date', 'currency', 'remaining_capacity', 'duration_days', 'season_type', 'special_discount', 'guarantee_departure']);

            $dates = $tourDates->map(function($d) use ($pickRow) {
                $row = $pickRow($d);
                $startDate = $d->start_date;
                $searchText = $startDate->format('d.m.Y') . ' ' .
                             $startDate->translatedFormat('d F Y') . ' ' .
                             $startDate->translatedFormat('d M Y') . ' ' .
                             $startDate->format('Y-m-d');

                return [
                    'id' => $d->id,
                    'date_type' => 'international_date',
                    'start_date' => $startDate->format('Y-m-d'),
                    'end_date' => $d->end_date?->format('Y-m-d'),
                    'start_date_display' => $startDate->translatedFormat('d M Y'),
                    'end_date_display' => $d->end_date?->translatedFormat('d M Y'),
                    'search_text' => strtolower($searchText),
                    'adult_price' => (float) ($row?->adult_price ?? 0),
                    'child_price' => (float) ($row?->child_price_1 ?? $row?->child_price ?? 0),
                    'infant_price' => (float) ($row?->infant_price ?? 0),
                    'single_supplement' => (float) ($row?->single_supplement ?? 0),
                    'extra_bed_price' => (float) ($row?->extra_bed_price ?? 0),
                    'currency' => $row?->currency ?: 'TRY',
                    'remaining_capacity' => $d->remaining_capacity,
                    'duration_days' => $d->duration_days,
                    'season_type' => $d->season_type,
                    'special_discount' => (float) $d->special_discount,
                    'guarantee_departure' => $d->guarantee_departure,
                ];
            })->toArray();
            $hasDates = count($dates) > 0;

        } elseif (str_contains($productableType, 'Tour') && !str_contains($productableType, 'Day')) {
            // Kültür Turu → TourDate (cultural_tour_dates)
            $tourDates = \App\Models\Tour\TourDate::where('cultural_tour_id', $product->productable_id)
                ->where('is_bookable', true)
                ->where('is_active', true)
                ->where('start_date', '>=', now()->toDateString())
                ->orderBy('start_date')
                ->with('marketplacePrices')
                ->get(['id', 'start_date', 'end_date', 'currency', 'remaining_capacity', 'duration_days', 'season_type', 'special_discount', 'guarantee_departure']);

            $dates = $tourDates->map(function($d) use ($pickRow) {
                $row = $pickRow($d);
                $startDate = $d->start_date;
                $searchText = $startDate->format('d.m.Y') . ' ' . 
                             $startDate->translatedFormat('d F Y') . ' ' . 
                             $startDate->translatedFormat('d M Y') . ' ' .
                             $startDate->format('Y-m-d');
                
                return [
                    'id' => $d->id,
                    'date_type' => 'tour_date',
                    'start_date' => $startDate->format('Y-m-d'),
                    'end_date' => $d->end_date?->format('Y-m-d'),
                    'start_date_display' => $startDate->translatedFormat('d M Y'),
                    'end_date_display' => $d->end_date?->translatedFormat('d M Y'),
                    'search_text' => strtolower($searchText),
                    'adult_price' => (float) ($row?->adult_price ?? 0),
                    'child_price' => (float) ($row?->child_price_1 ?? $row?->child_price ?? 0),
                    'infant_price' => (float) ($row?->infant_price ?? 0),
                    'single_supplement' => (float) ($row?->single_supplement ?? 0),
                    'extra_bed_price' => (float) ($row?->extra_bed_price ?? 0),
                    'currency' => $row?->currency ?: 'TRY',
                    'remaining_capacity' => $d->remaining_capacity,
                    'duration_days' => $d->duration_days,
                    'season_type' => $d->season_type,
                    'special_discount' => (float) $d->special_discount,
                    'guarantee_departure' => $d->guarantee_departure,
                ];
            })->toArray();
            $hasDates = count($dates) > 0;

        } elseif (str_contains($productableType, 'DayTour')) {
            // Günübirlik Tur → DayTourDate
            $dayDates = \App\Models\DayTour\DayTourDate::where('day_tour_id', $product->productable_id)
                ->where('is_active', true)
                ->where('tour_date', '>=', now()->toDateString())
                ->orderBy('tour_date')
                ->get();

            $dates = $dayDates->map(function($d) {
                $tourDate = \Carbon\Carbon::parse($d->tour_date);
                $searchText = $tourDate->format('d.m.Y') . ' ' . 
                             $tourDate->translatedFormat('d F Y') . ' ' . 
                             $tourDate->translatedFormat('d M Y') . ' ' .
                             $tourDate->format('Y-m-d');

                return [
                    'id' => $d->id,
                    'date_type' => 'day_tour_date',
                    'start_date' => $tourDate->format('Y-m-d'),
                    'end_date' => $tourDate->format('Y-m-d'),
                    'start_date_display' => $tourDate->translatedFormat('d M Y'),
                    'end_date_display' => null,
                    'search_text' => strtolower($searchText),
                    'adult_price' => (float) $d->adult_price,
                    'child_price' => (float) $d->child_price,
                    'infant_price' => (float) $d->infant_price,
                    'single_supplement' => 0,
                    'extra_bed_price' => 0,
                    'currency' => 'TRY',
                    'remaining_capacity' => $d->remaining_capacity,
                    'duration_days' => 1,
                    'departure_time' => $d->start_time ? \Carbon\Carbon::parse($d->start_time)->format('H:i') : null,
                    'return_time' => $d->end_time ? \Carbon\Carbon::parse($d->end_time)->format('H:i') : null,
                    'guarantee_departure' => $d->is_guaranteed,
                ];
            })->toArray();
            $hasDates = count($dates) > 0;

        } elseif (str_contains($productableType, 'DayTrip')) {
            // Diğer Günübirlik Tur Versiyonu → DayTripTourDate
            $dayDates = \App\Models\Product\DayTripTourDate::where('day_trip_tour_id', $product->productable_id)
                ->where('is_bookable', true)
                ->where('is_active', true)
                ->where('tour_date', '>=', now()->toDateString())
                ->orderBy('tour_date')
                ->get();

            $dates = $dayDates->map(function($d) {
                $tourDate = \Carbon\Carbon::parse($d->tour_date);
                $searchText = $tourDate->format('d.m.Y') . ' ' . 
                             $tourDate->translatedFormat('d F Y') . ' ' . 
                             $tourDate->translatedFormat('d M Y') . ' ' .
                             $tourDate->format('Y-m-d');

                return [
                    'id' => $d->id,
                    'date_type' => 'day_trip_date',
                    'start_date' => $tourDate->format('Y-m-d'),
                    'end_date' => $tourDate->format('Y-m-d'),
                    'start_date_display' => $tourDate->translatedFormat('d M Y'),
                    'end_date_display' => null,
                    'search_text' => strtolower($searchText),
                    'adult_price' => (float) $d->price_adult,
                    'child_price' => (float) $d->price_child,
                    'infant_price' => (float) $d->price_infant,
                    'single_supplement' => 0,
                    'extra_bed_price' => 0,
                    'currency' => 'TRY',
                    'remaining_capacity' => $d->remaining_capacity,
                    'duration_days' => 1,
                    'departure_time' => $d->departure_time ? \Carbon\Carbon::parse($d->departure_time)->format('H:i') : null,
                    'return_time' => $d->return_time ? \Carbon\Carbon::parse($d->return_time)->format('H:i') : null,
                    'guarantee_departure' => $d->guarantee_departure,
                ];
            })->toArray();
            $hasDates = count($dates) > 0;
        }

        return response()->json([
            'has_dates' => $hasDates,
            'dates' => $dates,
            'base_price' => (float) $product->base_price,
            'currency' => $product->currency,
        ]);
    }

    // ─── AJAX: Ürün → tarihler + fiyatlar ────────────────────────────────────

    public function quickStoreCustomer(Request $request)
    {
        $agencyId = $this->agencyId();

        try {
            $validated = $request->validate([
                'first_name' => 'required|string|max:255',
                'last_name' => 'required|string|max:255',
                'email' => 'nullable|email|max:255',
                'phone' => 'nullable|string|max:20',
                'gender' => 'nullable|in:male,female,other',
                'national_id' => 'nullable|string|max:20',
                'birth_date' => 'nullable|date',
            ], [
                'first_name.required' => 'Ad alanı zorunludur.',
                'last_name.required' => 'Soyad alanı zorunludur.',
                'email.email' => 'Geçerli bir e-posta adresi girin (örn. ad@site.com).',
                'email.max' => 'E-posta 255 karakteri aşamaz.',
                'birth_date.date' => 'Doğum tarihi geçerli bir tarih olmalıdır.',
                'gender.in' => 'Cinsiyet değeri geçersiz.',
            ], [
                'first_name' => 'Ad',
                'last_name' => 'Soyad',
                'email' => 'E-posta',
                'phone' => 'Telefon',
                'national_id' => 'T.C. / Pasaport',
                'birth_date' => 'Doğum Tarihi',
            ]);

            $customer = new Customer();
            $customer->agency_id = $agencyId;
            $customer->first_name = $validated['first_name'];
            $customer->last_name = $validated['last_name'];
            $customer->phone = $validated['phone'] ?? null;
            $customer->gender = $validated['gender'] ?? null;
            $customer->national_id = $validated['national_id'] ?? null;
            $customer->birth_date = $validated['birth_date'] ?? null;

            if (!empty($validated['email'])) {
                $customer->emails = [$validated['email']];
            }

            $customer->status = 'active';
            $customer->created_by = Auth::id();
            $customer->save();

            return response()->json([
                'success' => true,
                'customer' => [
                    'id' => $customer->id,
                    'full_name' => $customer->full_name,
                    'first_name' => $customer->first_name,
                    'last_name' => $customer->last_name,
                    'phone' => $customer->phone,
                    'email' => $validated['email'] ?? '',
                    'initials' => $customer->initials,
                ]
            ]);

        } catch (\Illuminate\Validation\ValidationException $e) {
            return response()->json(['success' => false, 'errors' => $e->errors()], 422);
        } catch (\Throwable $e) {
            return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
        }
    }

    public function getCustomerPassengers(Request $request)
    {
        $agencyId = $this->agencyId();
        $customerId = $request->customer_id;

        $customer = Customer::byAgency($agencyId)->findOrFail($customerId);
        $passengers = $customer->passengers()->orderBy('first_name')->get();

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


    // ─── YARDIMCI ─────────────────────────────────────────────────────────────

    public function storeTargets(Request $request)
    {
        $agencyId = $this->agencyId();
        $validated = $request->validate([
            'year' => 'required|integer',
            'period' => 'required|in:year,month',
            'month' => 'nullable|integer|min:1|max:12',
            'type' => 'required|in:revenue,quantity',
            'targets' => 'required|array',
            'targets.*' => 'nullable|string', // String because of formatting dots
        ]);

        $targetMonth = ($validated['period'] === 'month') ? $validated['month'] : null;

        foreach ($validated['targets'] as $productTypeId => $value) {
            $numericValue = (float)str_replace('.', '', $value);

            \App\Models\Agency\AgencySalesTarget::updateOrCreate(
                [
                    'agency_id' => $agencyId,
                    'product_type_id' => $productTypeId,
                    'target_year' => $validated['year'],
                    'target_period' => $validated['period'],
                    'target_month' => $targetMonth,
                    'target_type' => $validated['type'],
                ],
                [
                    'target_value' => $numericValue,
                ]
            );
        }

        return back()->with('success', 'Satış hedefleri başarıyla güncellendi.');
    }

    public function getTargetsJson(Request $request)
    {
        $agencyId = $this->agencyId();
        $targets = \App\Models\Agency\AgencySalesTarget::where('agency_id', $agencyId)
            ->where('target_year', $request->year)
            ->where('target_period', $request->period)
            ->where('target_type', $request->type)
            ->when($request->period === 'month', function($q) use ($request) {
                return $q->where('target_month', $request->month);
            })
            ->pluck('target_value', 'product_type_id');

        return response()->json($targets);
    }

    public function quickView(Sale $sale)
    {
        $this->authorizeAgency($sale);
        $agencyId = $this->agencyId();

        // Yeni satış kartıyla BİRLEŞİK tasarım: quick-create blade'ini mevcut satışa bağlı render eder.
        $sale->load(['customer', 'productType', 'product', 'reservable', 'tourDate', 'items', 'passengers']);

        $productTypes = ProductType::active()->orderBy('sort_order')->get();
        $agents = User::byAgency($agencyId)->where('is_active', true)->orderBy('first_name')->get(['id', 'first_name', 'last_name']);
        $products = Product::byAgency($agencyId)
            ->with('productType')
            ->bookable()
            ->orderBy('name')
            ->get(['id', 'name', 'base_price', 'currency', 'product_type_id', 'productable_type', 'productable_id']);
        $activeCurrencies = auth()->user()->agency->getActiveCurrencies();
        $taxRates = auth()->user()->agency->getActiveTaxRates(\App\Models\Agency\TaxType::CODE_KDV);
        $supplierCatalog = $this->supplierCatalog($agencyId);

        return view('agency.sales.quick-create', compact('sale', 'productTypes', 'agents', 'products', 'activeCurrencies', 'taxRates', 'supplierCatalog'));
    }

    public function updateField(Request $request, Sale $sale)
    {
        $this->authorizeAgency($sale);

        $request->validate([
            'field' => 'required|string',
            'value' => 'nullable'
        ]);

        $field = $request->field;
        $value = $request->value;

        if (str_starts_with($field, 'custom_field_')) {
            $defId = (int) str_replace('custom_field_', '', $field);
            $definition = \App\Models\Sale\SaleFieldDefinition::where('id', $defId)
                ->where('agency_id', $sale->agency_id)
                ->first();
            if (!$definition) {
                return response()->json(['success' => false, 'message' => 'Geçersiz özel alan.'], 422);
            }
            
            try {
                DB::beginTransaction();
                
                $oldValueRecord = \App\Models\Sale\SaleFieldValue::where('sale_id', $sale->id)
                    ->where('field_definition_id', $defId)
                    ->first();
                $oldValue = $oldValueRecord?->value ?? '—';
                
                \App\Models\Sale\SaleFieldValue::updateOrCreate(
                    ['sale_id' => $sale->id, 'field_definition_id' => $defId],
                    ['value' => $value]
                );
                
                SaleActivity::create([
                    'agency_id' => $sale->agency_id,
                    'sale_id' => $sale->id,
                    'performed_by' => auth()->id(),
                    'activity_type' => 'update',
                    'subject' => 'Özel Alan Güncellendi: ' . $definition->label,
                    'description' => "<b>{$definition->label}</b> özel alanı '{$oldValue}' değerinden '{$value}' değerine güncellendi.",
                    'metadata' => ['field' => $field, 'old' => $oldValue, 'new' => $value]
                ]);
                
                DB::commit();
                
                return response()->json([
                    'success' => true,
                    'message' => 'Özel alan güncellendi.',
                    'display_value' => $value
                ]);
            } catch (\Exception $e) {
                DB::rollBack();
                return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
            }
        }

        // İzin verilen alanlar
        $allowedFields = [
            'title', 'status', 'start_date', 'end_date', 'assigned_to', 
            'customer_note', 'internal_note', 'pickup_location', 'dropoff_location',
            'currency'
        ];

        if (!in_array($field, $allowedFields)) {
            return response()->json(['success' => false, 'message' => 'Bu alan güncellenemez.'], 422);
        }

        try {
            DB::beginTransaction();

            $oldValue = $sale->$field;
            $sale->$field = $value;
            $sale->save();

            if ($field === 'currency') {
                $sale->calculateTotals();
            }

            // Daha açıklayıcı aktivite mesajı
            $subject = 'Alan Güncellendi: ' . $field;
            $desc = "'$field' alanı '$oldValue' değerinden '$value' değerine güncellendi.";

            if ($field === 'status') {
                $oldLabel = $sale->getStatusLabel($oldValue);
                $newLabel = $sale->status_label;
                $subject = 'Satış Durumu Değişti';
                $desc = "Satış durumu <b>$oldLabel</b> aşamasından <b>$newLabel</b> aşamasına çekildi.";
            }

            if ($field === 'assigned_to') {
                $oldUser = User::find($oldValue)?->full_name ?? 'Atanmamış';
                $newUser = User::find($value)?->full_name ?? 'Atanmamış';
                $subject = 'Sorumlu Değiştirildi';
                $desc = "Satış sorumlusu <b>$oldUser</b> yerine <b>$newUser</b> olarak güncellendi.";
            }

            // Aktivite kaydı
            SaleActivity::create([
                'agency_id' => $sale->agency_id,
                'sale_id' => $sale->id,
                'performed_by' => auth()->id(),
                'activity_type' => 'update',
                'subject' => $subject,
                'description' => $desc,
                'metadata' => ['field' => $field, 'old' => $oldValue, 'new' => $value]
            ]);

            DB::commit();

            $displayValue = $value;
            if ($field === 'status') $displayValue = $sale->status_label;
            if ($field === 'assigned_to') $displayValue = $sale->assignedAgent?->full_name ?? '—';

            return response()->json([
                'success' => true,
                'message' => 'Güncelleme başarılı.',
                'display_value' => $displayValue
            ]);

        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
        }
    }

    public function addItem(Request $request, Sale $sale)
    {
        $this->authorizeAgency($sale);

        $validated = $request->validate([
            'product_id' => 'nullable|exists:products,id',
            'product_type_id' => 'nullable|exists:product_types,id',
            'name' => 'required|string',
            'quantity' => 'required|numeric|min:0.01',
            'unit_price' => 'required|numeric',
            'tax_rate' => 'nullable|numeric|min:0|max:100',
            'currency' => 'required|string|max:3',
        ]);

        try {
            DB::beginTransaction();

            // Oran gelmediyse Ayarlar > Vergi Oranları'ndaki varsayılana düş.
            // Varsayılan işaretli tanım yoksa en yüksek aktif orana düşülür — sessizce %0 vergi yazmamak için.
            if (isset($validated['tax_rate'])) {
                $taxRate = (float) $validated['tax_rate'];
            } else {
                $agencyTaxRates = auth()->user()->agency->getActiveTaxRates(\App\Models\Agency\TaxType::CODE_KDV);
                $taxRate = (float) (($agencyTaxRates->firstWhere('is_default', true) ?? $agencyTaxRates->first())?->rate ?? 0);
            }
            $subtotalPrice = $validated['quantity'] * $validated['unit_price'];
            $taxAmount = $subtotalPrice * ($taxRate / 100);
            $totalPrice = $subtotalPrice + $taxAmount;

            $item = $sale->items()->create([
                'product_id' => $validated['product_id'] ?? null,
                'product_type_id' => $validated['product_type_id'] ?? ($validated['product_id'] ? \App\Models\Product\Product::find($validated['product_id'])->product_type_id : null),
                'name' => $validated['name'],
                'quantity' => $validated['quantity'],
                'unit_price' => $validated['unit_price'],
                'tax_rate' => $taxRate,
                'tax_amount' => $taxAmount,
                'total_price' => $totalPrice,
                'currency' => $validated['currency'],
            ]);

            // Rezervasyon toplamını güncelle
            $sale->calculateTotals(); // Bu metod subtotal, tax_amount ve total_amount'u günceller

            // Aktivite
            SaleActivity::create([
                'agency_id' => $sale->agency_id,
                'sale_id' => $sale->id,
                'performed_by' => auth()->id(),
                'activity_type' => 'item_added',
                'subject' => 'Ürün Eklendi: ' . $item->name,
                'description' => "Satışa {$item->quantity} adet {$item->name} eklendi.",
                'metadata' => ['item_id' => $item->id, 'total' => $item->total_price]
            ]);

            DB::commit();

            return response()->json(['success' => true, 'message' => 'Ürün eklendi.']);

        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
        }
    }

    public function removeItem(SaleItem $item)
    {
        $sale = $item->sale;
        $this->authorizeAgency($sale);

        try {
            DB::beginTransaction();

            $itemName = $item->name;
            $item->delete();

            // Rezervasyon toplamını güncelle
            $sale->calculateTotals();

            // Aktivite
            SaleActivity::create([
                'agency_id' => $sale->agency_id,
                'sale_id' => $sale->id,
                'performed_by' => auth()->id(),
                'activity_type' => 'item_removed',
                'subject' => 'Ürün Çıkarıldı: ' . $itemName,
                'description' => "Satıştan {$itemName} çıkarıldı.",
            ]);

            DB::commit();

            return response()->json(['success' => true, 'message' => 'Ürün çıkarıldı.']);

        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
        }
    }

    public function getActivities(Sale $sale)
    {
        $this->authorizeAgency($sale);
        
        $sale->load([
            'activities' => function ($q) {
                $q->orderBy('is_pinned', 'desc')->orderBy('created_at', 'desc');
            },
            'activities.performer'
        ]);

        $html = view('agency.sales.partials.activities-feed', compact('sale'))->render();

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

    public function storeActivity(Request $request, Sale $sale)
    {
        $this->authorizeAgency($sale);

        $validated = $request->validate([
            'activity_type' => 'required|string|in:' . implode(',', \App\Enums\ActivityType::values()),
            'subject' => 'nullable|string|max:255',
            'description' => 'nullable|string',
            'due_date' => 'nullable|date',
            'is_pinned' => 'boolean',
            'is_important' => 'boolean',
            'attachment' => 'nullable|file|max:10240',
        ]);

        $validated['agency_id'] = $this->agencyId();
        $validated['sale_id'] = $sale->id;
        $validated['performed_by'] = auth()->id();
        $validated['status'] = $validated['activity_type'] === 'task' ? 'pending' : 'completed';
        $validated['activity_date'] = now();

        if ($request->hasFile('attachment')) {
            $file = $request->file('attachment');
            $path = $file->store('sales/activities/' . $sale->id, 'public');
            
            $validated['attachments'] = [
                [
                    'name' => $file->getClientOriginalName(),
                    'path' => $path,
                    'size' => $file->getSize(),
                    'mime' => $file->getMimeType(),
                    'uploaded_at' => now()->toDateTimeString(),
                ]
            ];
        }

        $activity = SaleActivity::create($validated);

        $sale->load([
            'activities' => function ($q) {
                $q->orderBy('is_pinned', 'desc')->orderBy('created_at', 'desc');
            },
            'activities.performer'
        ]);

        $html = view('agency.sales.partials.activities-feed', compact('sale'))->render();

        return response()->json([
            'success' => true,
            'message' => 'Aktivite başarıyla kaydedildi.',
            'html' => $html
        ]);
    }

    public function togglePinActivity(Sale $sale, SaleActivity $activity)
    {
        $this->authorizeAgency($sale);
        
        if ($activity->sale_id !== $sale->id) {
            return response()->json(['success' => false, 'message' => 'Geçersiz aktivite.'], 404);
        }

        $activity->is_pinned = !$activity->is_pinned;
        $activity->save();

        $sale->load([
            'activities' => function ($q) {
                $q->orderBy('is_pinned', 'desc')->orderBy('created_at', 'desc');
            },
            'activities.performer'
        ]);

        $html = view('agency.sales.partials.activities-feed', compact('sale'))->render();

        return response()->json([
            'success' => true,
            'message' => $activity->is_pinned ? 'Aktivite sabitlendi.' : 'Sabitleme kaldırıldı.',
            'html' => $html
        ]);
    }

    public function destroyActivity(Sale $sale, SaleActivity $activity)
    {
        $this->authorizeAgency($sale);

        if ($activity->sale_id !== $sale->id) {
            return response()->json(['success' => false, 'message' => 'Geçersiz aktivite.'], 404);
        }

        $activity->delete();

        $sale->load([
            'activities' => function ($q) {
                $q->orderBy('is_pinned', 'desc')->orderBy('created_at', 'desc');
            },
            'activities.performer'
        ]);

        $html = view('agency.sales.partials.activities-feed', compact('sale'))->render();

        return response()->json([
            'success' => true,
            'message' => 'Aktivite silindi.',
            'html' => $html
        ]);
    }

    public function storeFieldDefinition(Request $request)
    {
        $agencyId = $this->agencyId();
        
        $validated = $request->validate([
            'label' => 'required|string|max:120',
            'field_type' => 'required|string|in:text,select,textarea,number,date',
            'options' => 'nullable|string',
            'is_required' => 'nullable|boolean',
        ]);
        
        $optionsArray = null;
        if ($validated['field_type'] === 'select' && !empty($validated['options'])) {
            $optionsArray = array_filter(array_map('trim', explode(',', $validated['options'])));
        }
        
        $fieldKey = \Str::slug($validated['label'], '_');
        $origKey = $fieldKey;
        $counter = 1;
        while (\App\Models\Sale\SaleFieldDefinition::where('agency_id', $agencyId)->where('field_key', $fieldKey)->exists()) {
            $fieldKey = $origKey . '_' . $counter;
            $counter++;
        }
        
        $definition = \App\Models\Sale\SaleFieldDefinition::create([
            'agency_id' => $agencyId,
            'field_key' => $fieldKey,
            'label' => $validated['label'],
            'field_type' => $validated['field_type'],
            'options' => $optionsArray,
            'is_required' => (bool)($request->is_required ?? false),
            'is_active' => true,
            'sort_order' => 0,
        ]);
        
        return response()->json([
            'success' => true,
            'message' => 'Özel alan tanımlandı.',
            'definition' => $definition
        ]);
    }

    public function updateFieldDefinition(Request $request, \App\Models\Sale\SaleFieldDefinition $definition)
    {
        if ($definition->agency_id !== $this->agencyId()) {
            return response()->json(['success' => false, 'message' => 'Yetkisiz erişim.'], 403);
        }
        
        $validated = $request->validate([
            'label' => 'required|string|max:120',
            'field_type' => 'required|string|in:text,select,textarea,number,date',
            'options' => 'nullable|string',
            'is_required' => 'nullable|boolean',
        ]);
        
        $optionsArray = null;
        if ($validated['field_type'] === 'select' && !empty($validated['options'])) {
            $optionsArray = array_filter(array_map('trim', explode(',', $validated['options'])));
        }
        
        $definition->update([
            'label' => $validated['label'],
            'field_type' => $validated['field_type'],
            'options' => $optionsArray,
            'is_required' => (bool)($request->is_required ?? false),
        ]);
        
        return response()->json([
            'success' => true,
            'message' => 'Özel alan tanımı güncellendi.',
            'definition' => $definition
        ]);
    }

    public function storeDocument(Request $request, Sale $sale)
    {
        $this->authorizeAgency($sale);

        $request->validate([
            'file' => 'required|file|max:10240', // 10MB limit
            'notes' => 'nullable|string|max:1000',
        ]);

        $file = $request->file('file');
        $originalName = $file->getClientOriginalName();
        $mimeType = $file->getMimeType();
        $fileSize = $file->getSize();

        $path = $file->store("agency/{$sale->agency_id}/sales/{$sale->id}/documents", 'public');

        $document = \App\Models\Sale\SaleDocument::create([
            'agency_id' => $sale->agency_id,
            'sale_id' => $sale->id,
            'file_name' => $originalName,
            'file_path' => $path,
            'file_size' => $fileSize,
            'mime_type' => $mimeType,
            'notes' => $request->notes,
            'created_by' => auth()->id(),
        ]);

        SaleActivity::create([
            'agency_id' => $sale->agency_id,
            'sale_id' => $sale->id,
            'performed_by' => auth()->id(),
            'activity_type' => 'document',
            'subject' => 'Yeni Belge Yüklendi',
            'description' => "Satışa <b>{$originalName}</b> adlı yeni bir belge yüklendi.",
            'metadata' => ['document_id' => $document->id, 'file_name' => $originalName]
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Belge başarıyla yüklendi.',
            'document' => [
                'id' => $document->id,
                'file_name' => $document->file_name,
                'size' => $document->formatted_size,
                'created_at' => $document->created_at->format('d.m.Y H:i'),
            ]
        ]);
    }

    public function destroyDocument(Sale $sale, \App\Models\Sale\SaleDocument $document)
    {
        $this->authorizeAgency($sale);

        if ($document->sale_id !== $sale->id) {
            return response()->json(['success' => false, 'message' => 'Geçersiz belge.'], 404);
        }

        \Storage::disk('public')->delete($document->file_path);
        
        $document->delete();

        SaleActivity::create([
            'agency_id' => $sale->agency_id,
            'sale_id' => $sale->id,
            'performed_by' => auth()->id(),
            'activity_type' => 'document',
            'subject' => 'Belge Silindi',
            'description' => "<b>{$document->file_name}</b> adlı belge silindi.",
            'metadata' => ['document_id' => $document->id, 'file_name' => $document->file_name]
        ]);

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

    public function updateItems(Request $request, Sale $sale)
    {
        $this->authorizeAgency($sale);
        
        $validated = $request->validate([
            'items' => 'present|array',
            'items.*.id' => 'nullable|integer',
            'items.*.product_id' => 'nullable|integer',
            'items.*.name' => 'required|string|max:255',
            'items.*.quantity' => 'required|numeric|min:0',
            'items.*.unit_price' => 'required|numeric|min:0',
            'items.*.tax_rate' => 'required|numeric|min:0|max:100',
            'items.*.currency' => 'required|string|max:3',
        ]);
        
        try {
            DB::beginTransaction();
            
            $sentIds = collect($validated['items'])->pluck('id')->filter()->toArray();
            
            $sale->items()->whereNotIn('id', $sentIds)->delete();
            
            foreach ($validated['items'] as $itemData) {
                $subtotalPrice = $itemData['quantity'] * $itemData['unit_price'];
                $taxAmount = $subtotalPrice * ($itemData['tax_rate'] / 100);
                $totalPrice = $subtotalPrice + $taxAmount;
                
                $data = [
                    'product_id' => $itemData['product_id'] ?? null,
                    'product_type_id' => $itemData['product_id'] ? \App\Models\Product\Product::find($itemData['product_id'])->product_type_id : null,
                    'name' => $itemData['name'],
                    'quantity' => $itemData['quantity'],
                    'unit_price' => $itemData['unit_price'],
                    'tax_rate' => $itemData['tax_rate'],
                    'tax_amount' => $taxAmount,
                    'total_price' => $totalPrice,
                    'currency' => $itemData['currency'],
                ];
                
                if (!empty($itemData['id'])) {
                    $sale->items()->where('id', $itemData['id'])->update($data);
                } else {
                    $sale->items()->create($data);
                }
            }
            
            $sale->calculateTotals();
            
            SaleActivity::create([
                'agency_id' => $sale->agency_id,
                'sale_id' => $sale->id,
                'performed_by' => auth()->id(),
                'activity_type' => 'update',
                'subject' => 'Ürünler Güncellendi',
                'description' => 'Satış ürün listesi ve fiyat hesaplamaları güncellendi.',
            ]);
            
            DB::commit();
            
            return response()->json([
                'success' => true,
                'message' => 'Ürünler başarıyla güncellendi.',
            ]);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json([
                'success' => false,
                'message' => $e->getMessage()
            ], 500);
        }
    }

    protected function authorizeAgency(Sale $sale): void
    {
        if ($sale->agency_id !== $this->agencyId()) {
            abort(403, 'Bu rezervasyona erişim yetkiniz yok.');
        }
    }
}

