<?php

namespace App\Http\Controllers\Agency\Product;

use App\Http\Controllers\Controller;
use App\Models\Product\ExtraService;
use App\Models\Product\ProductCategory;
use Illuminate\Http\Request;
use Illuminate\Support\Str;

/**
 * Ekstra Hizmetler modülü.
 *
 * Tek sayfalık kategori raylı fiyat cetveli: kategoriler solda, hizmetler
 * sağda satır satır listelenir ve satır üzerinde inline düzenlenir. Ayrıntılar
 * (açıklama, birim, vergiye dahil…) quick-view drawer'ında açılır.
 */
class ExtraServiceController extends Controller
{
    /** Inline (update-field) ile düzenlenebilen alanlar. */
    private const EDITABLE = [
        'name', 'description', 'price', 'currency', 'unit',
        'tax_rate', 'tax_included', 'category_id', 'is_active', 'sort_order',
    ];

    // ─────────────────────────────────────────────────────────────
    // Liste
    // ─────────────────────────────────────────────────────────────

    public function index(Request $request)
    {
        $agency = $this->agency();
        $typeId = $this->typeId();

        $categories = $this->categoryQuery()->orderBy('sort_order')->orderBy('name')->get();

        $query = ExtraService::byAgency($agency->id)->with('category');

        if ($request->filled('search')) {
            $search = $request->search;
            $query->where(fn ($q) => $q->where('name', 'like', "%{$search}%")
                ->orWhere('code', 'like', "%{$search}%")
                ->orWhere('description', 'like', "%{$search}%"));
        }

        if ($request->filled('status')) {
            $query->where('is_active', $request->status === 'active');
        }

        // "uncategorized" → kategorisi olmayanlar; sayısal değer → o kategori
        $activeCategory = $request->get('category');
        if ($activeCategory === 'uncategorized') {
            $query->whereNull('category_id');
        } elseif (is_numeric($activeCategory)) {
            $query->where('category_id', (int) $activeCategory);
        }

        $services = $query->orderBy('sort_order')->orderBy('name')->get();

        // Rayda gösterilen sayaçlar filtreden bağımsız olmalı (toplam görünüm)
        $counts = ExtraService::byAgency($agency->id)
            ->selectRaw('category_id, COUNT(*) as total')
            ->groupBy('category_id')
            ->pluck('total', 'category_id');

        $stats = [
            'total' => ExtraService::byAgency($agency->id)->count(),
            'active' => ExtraService::byAgency($agency->id)->where('is_active', true)->count(),
            'categories' => $categories->count(),
        ];

        return view('agency.products.extra-services.index', [
            'services' => $services,
            'categories' => $categories,
            'counts' => $counts,
            'stats' => $stats,
            'activeCategory' => $activeCategory,
            'taxRates' => $agency->getActiveTaxRates(),
            'currencies' => $agency->getActiveCurrencies(),
            'units' => ExtraService::units(),
            'productTypeId' => $typeId,
        ]);
    }

    /**
     * Satış ekranındaki "Ekstra Hizmetler" sekmesini besleyen JSON kataloğu.
     * Yalnızca aktif hizmetler döner.
     */
    public function catalog()
    {
        $services = ExtraService::byAgency($this->agency()->id)
            ->active()
            ->with('category:id,name')
            ->orderBy('sort_order')
            ->orderBy('name')
            ->get()
            ->map(fn (ExtraService $s) => [
                'id' => $s->id,
                'product_id' => $s->product_id,
                'code' => $s->code,
                'name' => $s->name,
                'description' => $s->description,
                'category' => $s->category?->name,
                'category_id' => $s->category_id,
                'price' => (float) $s->price,
                'currency' => $s->currency,
                'unit' => $s->unit,
                'unit_label' => $s->unit_label,
                'tax_rate' => $s->tax_rate === null ? null : (float) $s->tax_rate,
                'tax_name' => $s->tax_name,
                'tax_included' => (bool) $s->tax_included,
                'tax_label' => $s->tax_label,
            ]);

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

    // ─────────────────────────────────────────────────────────────
    // Hizmet CRUD
    // ─────────────────────────────────────────────────────────────

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

        $validated = $request->validate([
            'name' => 'required|string|max:255',
            'category_id' => 'nullable|integer',
            'price' => 'required|numeric|min:0',
            'currency' => 'required|string|size:3',
            'unit' => 'nullable|string|max:20',
            'tax_rate' => 'nullable|numeric|min:0|max:100',
            'tax_included' => 'nullable|boolean',
            'description' => 'nullable|string|max:2000',
        ]);

        $validated['category_id'] = $this->resolveCategoryId($validated['category_id'] ?? null);
        $validated['tax_name'] = $this->taxNameFor($validated['tax_rate'] ?? null);
        $validated['tax_included'] = (bool) ($validated['tax_included'] ?? false);
        $validated['agency_id'] = $agency->id;
        $validated['product_type_id'] = $this->typeId();
        $validated['created_by'] = auth()->id();
        $validated['is_active'] = true;

        $service = ExtraService::create($validated);

        return response()->json([
            'success' => true,
            'message' => 'Ekstra hizmet eklendi.',
            'service' => $service->fresh('category'),
            'quick_view_url' => route('agency.products.extra-services.quick-view', $service),
        ]);
    }

    public function update(Request $request, ExtraService $extraService)
    {
        $this->authorizeService($extraService);

        $validated = $request->validate([
            'name' => 'required|string|max:255',
            'category_id' => 'nullable|integer',
            'price' => 'required|numeric|min:0',
            'currency' => 'required|string|size:3',
            'unit' => 'nullable|string|max:20',
            'tax_rate' => 'nullable|numeric|min:0|max:100',
            'tax_included' => 'nullable|boolean',
            'description' => 'nullable|string|max:2000',
            'sort_order' => 'nullable|integer|min:0',
        ]);

        $validated['category_id'] = $this->resolveCategoryId($validated['category_id'] ?? null);
        $validated['tax_name'] = $this->taxNameFor($validated['tax_rate'] ?? null);
        $validated['tax_included'] = (bool) ($validated['tax_included'] ?? false);

        $extraService->update($validated);

        return response()->json(['success' => true, 'message' => 'Hizmet güncellendi.']);
    }

    /** Inline düzenleme (liste satırı ve quick-view alanları). */
    public function updateField(Request $request, ExtraService $extraService)
    {
        $this->authorizeService($extraService);

        $field = (string) $request->input('field');
        $value = $request->input('value');

        if (!in_array($field, self::EDITABLE, true)) {
            return response()->json(['success' => false, 'message' => 'Bu alan düzenlenemez.'], 422);
        }

        // Boş string → null (vergisiz hizmet, kategorisiz hizmet, birimsiz…)
        if ($value === '') {
            $value = null;
        }

        $payload = [$field => $value];

        if ($field === 'category_id') {
            $payload['category_id'] = $this->resolveCategoryId($value);
        } elseif ($field === 'tax_rate') {
            $payload['tax_rate'] = $value === null ? null : (float) $value;
            $payload['tax_name'] = $this->taxNameFor($payload['tax_rate']);
        } elseif (in_array($field, ['is_active', 'tax_included'], true)) {
            $payload[$field] = (bool) $value;
        } elseif ($field === 'price') {
            $payload['price'] = (float) str_replace(',', '.', (string) $value);
        } elseif ($field === 'name' && trim((string) $value) === '') {
            return response()->json(['success' => false, 'message' => 'Hizmet adı boş bırakılamaz.'], 422);
        }

        $extraService->update($payload);
        $extraService->refresh();

        return response()->json([
            'success' => true,
            'message' => 'Güncellendi.',
            'display_value' => $this->displayValue($extraService, $field),
        ]);
    }

    public function toggleStatus(ExtraService $extraService)
    {
        $this->authorizeService($extraService);

        $extraService->update(['is_active' => !$extraService->is_active]);

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

    public function destroy(ExtraService $extraService)
    {
        $this->authorizeService($extraService);

        $extraService->delete();

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

    public function quickView(ExtraService $extraService)
    {
        $this->authorizeService($extraService);

        $agency = $this->agency();

        // İlişkili satışlar: bu hizmeti kalem (sale_items.itemable) olarak içeren
        // satışlar — quick-view'de satış kartına çapraz link verilir.
        $relatedSalesQuery = \App\Models\Sale\Sale::byAgency($agency->id)
            ->whereHas('items', fn ($q) => $q
                ->where('itemable_type', ExtraService::class)
                ->where('itemable_id', $extraService->id));
        $relatedSalesTotal = (clone $relatedSalesQuery)->count();
        $relatedSales = $relatedSalesQuery
            ->with('customer:id,customer_type,first_name,last_name,company_name')
            ->orderByDesc('created_at')
            ->limit(15)
            ->get();

        return view('agency.products.extra-services.quick-view', [
            'service' => $extraService->load('category', 'creator'),
            'categories' => $this->categoryQuery()->orderBy('name')->get(),
            'taxRates' => $agency->getActiveTaxRates(),
            'currencies' => $agency->getActiveCurrencies(),
            'units' => ExtraService::units(),
            'relatedSales' => $relatedSales,
            'relatedSalesTotal' => $relatedSalesTotal,
        ]);
    }

    // ─────────────────────────────────────────────────────────────
    // Kategoriler (yalnızca bu ürün tipi kapsamında)
    // ─────────────────────────────────────────────────────────────

    public function storeCategory(Request $request)
    {
        $agency = $this->agency();

        $validated = $request->validate([
            'name' => 'required|string|max:255',
            'color_code' => 'nullable|string|max:7',
        ]);

        $slug = $this->uniqueCategorySlug($validated['name']);

        $category = ProductCategory::create([
            'agency_id' => $agency->id,
            'product_type_id' => $this->typeId(),
            'name' => $validated['name'],
            'code' => $slug,
            'slug' => $slug,
            'color_code' => $validated['color_code'] ?? null,
            'level' => 0,
            'path' => '/' . $slug,
            'is_active' => true,
            'is_public' => true,
            'created_by' => auth()->id(),
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Kategori oluşturuldu.',
            'category' => ['id' => $category->id, 'name' => $category->name],
        ]);
    }

    public function updateCategory(Request $request, ProductCategory $category)
    {
        $this->authorizeCategory($category);

        $validated = $request->validate([
            'name' => 'required|string|max:255',
            'color_code' => 'nullable|string|max:7',
        ]);

        $category->update($validated);

        return response()->json(['success' => true, 'message' => 'Kategori güncellendi.']);
    }

    /** Kategori silinir; içindeki hizmetler silinmez, "Kategorisiz"e düşer. */
    public function destroyCategory(ProductCategory $category)
    {
        $this->authorizeCategory($category);

        $moved = ExtraService::byAgency($this->agency()->id)
            ->where('category_id', $category->id)
            ->update(['category_id' => null]);

        $category->delete();

        return response()->json([
            'success' => true,
            'message' => $moved
                ? "Kategori silindi, {$moved} hizmet Kategorisiz'e taşındı."
                : 'Kategori silindi.',
        ]);
    }

    // ─────────────────────────────────────────────────────────────
    // Yardımcılar
    // ─────────────────────────────────────────────────────────────

    private function agency()
    {
        return auth()->user()->agency;
    }

    private function typeId(): int
    {
        $typeId = ExtraService::typeId();

        abort_if($typeId === null, 500, 'Ekstra Hizmetler ürün tipi bulunamadı. Migration çalıştırılmalı.');

        return $typeId;
    }

    /** Bu acenteye + bu ürün tipine ait kategoriler. */
    private function categoryQuery()
    {
        return ProductCategory::where('agency_id', $this->agency()->id)
            ->where('product_type_id', $this->typeId());
    }

    private function authorizeService(ExtraService $service): void
    {
        abort_if($service->agency_id !== $this->agency()->id, 403);
    }

    private function authorizeCategory(ProductCategory $category): void
    {
        abort_if(
            $category->agency_id !== $this->agency()->id || $category->product_type_id !== $this->typeId(),
            403
        );
    }

    /** Gelen kategori id'si bu acenteye ait değilse yok sayılır (kategorisiz). */
    private function resolveCategoryId($value): ?int
    {
        if ($value === null || $value === '' || $value === 'uncategorized') {
            return null;
        }

        return $this->categoryQuery()->whereKey((int) $value)->exists() ? (int) $value : null;
    }

    /** Orana karşılık gelen vergi adını ayarlardan bulur (ör. 20 → "KDV"). */
    private function taxNameFor($rate): ?string
    {
        if ($rate === null || $rate === '') {
            return null;
        }

        return $this->agency()->getActiveTaxRates()
            ->first(fn ($tr) => (float) $tr->rate === (float) $rate)?->name;
    }

    private function uniqueCategorySlug(string $name): string
    {
        $base = Str::slug($name) ?: 'kategori';
        $slug = $base;
        $i = 2;

        while (ProductCategory::withTrashed()->where('slug', $slug)->exists()) {
            $slug = $base . '-' . $i++;
        }

        return $slug;
    }

    /** Inline düzenleme sonrası hücrede gösterilecek biçimli değer. */
    private function displayValue(ExtraService $service, string $field): string
    {
        return match ($field) {
            'price' => number_format((float) $service->price, 2, ',', '.'),
            'tax_rate' => $service->tax_label,
            'unit' => $service->unit_label ?? 'Birimsiz',
            'category_id' => $service->category?->name ?? 'Kategorisiz',
            'is_active' => $service->is_active ? 'Aktif' : 'Pasif',
            'tax_included' => $service->tax_included ? 'Evet' : 'Hayır',
            default => (string) ($service->{$field} ?? '—'),
        };
    }
}
