<?php

namespace App\Services;

use App\Models\Sale;
use App\Models\SaleItem;
use App\Models\Product; 
use App\Models\ProductStock; 
use App\Models\StockTransaction;
use App\Models\Customer;      // Tambahan untuk Poin
use App\Models\PointHistory;  // Tambahan untuk Poin
use App\Models\Setting;       // Tambahan untuk Poin
use App\Exceptions\StockException; 
use Illuminate\Support\Facades\DB;

class SaleService
{
    /**
     * Memproses penyimpanan transaksi penjualan + Point Reward.
     */
    public function createSale(array $saleData, array $itemData): Sale
    {
        return DB::transaction(function () use ($saleData, $itemData) {
            
            // 1. Buat Header Penjualan
            $sale = Sale::create($saleData);

            foreach ($itemData as $item) {
                
                $product = Product::findOrFail($item['product_id']); 
                $quantitySold = $item['quantity'];

                // 2. Cek Ketersediaan Stok (Validasi)
                $branchStock = ProductStock::where('product_id', $product->id)
                    ->where('branch_id', $saleData['branch_id']) 
                    ->first();
                
                $availableStock = (float)($branchStock->quantity ?? 0);
                
                // Hitung kebutuhan stok dalam satuan dasar (Kg/Pcs)
                $deductionQty = $quantitySold * $item['base_conversion_factor'];
                
                // Jika stok kurang, lempar error (Transaksi Batal)
                if ($availableStock < $deductionQty) {
                    throw new StockException("Stok tidak cukup untuk produk: " . $product->name . ". Sisa: " . $product->stok_terbilang($availableStock));
                }

                // 3. Simpan Item Nota (SaleItem)
                $saleItem = new SaleItem([
                    'sale_id' => $sale->id,
                    'product_id' => $product->id,
                    'product_name' => $product->name,
                    'quantity' => $quantitySold,
                    'unit' => $item['unit'], 
                    'unit_price' => $item['unit_price'],
                    'total_price' => $item['total_price'],
                    'base_conversion_factor' => $item['base_conversion_factor'],
                    'applied_price_level' => $item['applied_price_level'] ?? null,
                ]);
                $sale->items()->save($saleItem);

                // 4. CATAT PENGURANGAN STOK (StockTransaction)
                // Ini trigger utama. Observer akan update ProductStock otomatis.
                StockTransaction::create([
                    'branch_id' => $saleData['branch_id'],
                    'product_id' => $product->id,
                    'type' => 'sale', 
                    
                    // Input Quantity NEGATIF agar stok berkurang
                    'input_quantity' => -1 * abs($quantitySold), 
                    
                    'input_unit' => $item['unit'],
                    'user_id' => $saleData['user_id'],
                    'note' => 'Penjualan Nota No. ' . $sale->invoice_number,
                ]);
                
                // (Logika decrement manual SUDAH DIHAPUS agar tidak stok ganda)
            }

            // --- 5. LOGIKA BARU: HITUNG LOYALTY POINT ---
            // Hanya jika ada Customer (Bukan Guest)
            if (!empty($saleData['customer_id'])) {
                $this->processLoyaltyPoints($sale, $saleData['customer_id'], $saleData['grand_total']);
            }
            // --------------------------------------------

            return $sale;
        });
    }

    /**
     * Logic Hitung Poin Reward
     */
    private function processLoyaltyPoints($sale, $customerId, $grandTotal)
    {
        // 1. Ambil Setting Rate dari Database (Default 10.000 jika belum disetting)
        // Pastikan Anda sudah menjalankan seeder/insert untuk key 'point_rate' di tabel settings
        $rateSetting = Setting::where('key', 'point_rate')->value('value');
        $rate = $rateSetting ? (float)$rateSetting : 10000;

        // 2. Hitung Poin (Pembulatan ke bawah)
        // Contoh: Belanja 105.000 / 10.000 = 10.5 -> Dapat 10 Poin
        if ($rate > 0 && $grandTotal >= $rate) {
            $earnedPoints = floor($grandTotal / $rate);

            if ($earnedPoints > 0) {
                // Update Saldo Customer
                $customer = Customer::find($customerId);
                if ($customer) {
                    $customer->increment('loyalty_points', $earnedPoints);

                    // Catat History Poin
                    PointHistory::create([
                        'customer_id' => $customerId,
                        'sale_id' => $sale->id,
                        'type' => 'earned', // Tipe: Dapat Poin
                        'points' => $earnedPoints,
                        'transaction_amount' => $grandTotal,
                    ]);
                }
            }
        }
    }
}