<?php

namespace App\Services\Rental;

use App\Models\Car;
use App\Models\Rental\Rental;
use App\Models\Rental\RentalInspection;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;

class RentalService
{
    public function createRental(array $data)
    {
        return DB::transaction(function () use ($data) {
            $car = Car::findOrFail($data['car_id']);
            $customer = \App\Models\Customer::findOrFail($data['customer_id']);

            // Check if customer is blacklisted
            if ($customer->isBlacklisted()) {
                $blacklist = $customer->getActiveBlacklist();
                throw new \Exception(app()->getLocale() == 'ar' 
                    ? "لا يمكن تأجير سيارة لهذا العميل. العميل محظور من قائمة الحظر. السبب: {$blacklist->reason}"
                    : "Cannot rent to this customer. Customer is blacklisted. Reason: {$blacklist->reason}");
            }

            // Check if customer has high-risk level
            $rating = $customer->rating ?? $customer->createRating();
            if ($rating->risk_level === 'critical') {
                throw new \Exception(app()->getLocale() == 'ar' 
                    ? "لا يمكن تأجير سيارة لهذا العميل. العميل ذو مخاطر عالية جداً (عميل حرج)."
                    : "Cannot rent to this customer. Customer has critical risk level.");
            }

            // Check if car has active insurance
            $insurance = $car->insurances()->where('status', 'active')
                ->whereDate('start_date', '<=', now())
                ->whereDate('end_date', '>=', now())
                ->first();

            if (!$insurance) {
                throw new \Exception('لا يمكن تأجير هذه السيارة لعدم وجود تأمين ساري المفعول.');
            }

            // Check if car has valid registration and inspection documents
            $document = $car->document;
            if (!$document) {
                throw new \Exception(app()->getLocale() == 'ar' ? 'لا يمكن تأجير هذه السيارة لعدم وجود بيانات الاستمارة والفحص الدوري.' : 'Car documents (Registration/Inspection) not found.');
            }

            if ($document->registration_expiry_date->isPast()) {
                throw new \Exception(app()->getLocale() == 'ar' ? 'لا يمكن تأجير هذه السيارة لأن الاستمارة منتهية الصلاحية.' : 'Registration (Istimara) has expired.');
            }

            if ($document->inspection_expiry_date->isPast()) {
                throw new \Exception(app()->getLocale() == 'ar' ? 'لا يمكن تأجير هذه السيارة لأن الفحص الدوري منتهى الصلاحية.' : 'Periodic Inspection (Fahas) has expired.');
            }

            // Check if customer has outstanding dues from previous rentals
            $outstandingDues = $customer->rentals()->where('status', '!=', 'cancelled')->sum('remaining_amount');

            if ($outstandingDues > 0) {
                throw new \Exception(app()->getLocale() == 'ar' ? "لا يمكن تأجير سيارة لهذا العميل لوجود مديونية سابقة قدرها {$outstandingDues} ر.س." : "Cannot rent to this customer due to outstanding dues of {$outstandingDues} SAR.");
            }

            if ($car->rental_status !== 'available') {
                throw new \Exception('Car is not available for rental.');
            }

            $startDate = Carbon::parse($data['start_date']);
            $endDate = Carbon::parse($data['end_date']);
            $days = $startDate->diffInDays($endDate);
            if ($days == 0) {
                $days = 1;
            } // Minimum 1 day

            $baseCost = $data['daily_price'] * $days;
            $discount = $data['discount'] ?? 0;
            $insuranceAmount = $data['insurance_amount'] ?? 0;
            $vatPercentage = $data['vat_percentage'] ?? 15.00;

            // Addons calculation (New System)
            $addonsTotal = 0;
            $selectedAddonsData = [];
            if (isset($data['selected_addons'])) {
                foreach ($data['selected_addons'] as $addonId) {
                    $addOn = \App\Models\AddOn::find($addonId);
                    $carAddOn = $car->addOns()->find($addonId);
                    $priceApplied = $carAddOn ? ($carAddOn->pivot->custom_price ?? $addOn->price) : $addOn->price;
                    
                    $totalPrice = ($addOn->price_type === 'daily') ? ($priceApplied * $days) : $priceApplied;
                    
                    $addonsTotal += $totalPrice;
                    $selectedAddonsData[] = [
                        'add_on_id' => $addonId,
                        'price_applied' => $priceApplied,
                        'quantity' => 1,
                        'total_price' => $totalPrice,
                    ];
                }
            }

            // Subtotal for tax calculation (Rental + Addons - Discount)
            $subtotalForTax = ($baseCost + $addonsTotal) - $discount;
            $taxAmount = $subtotalForTax * ($vatPercentage / 100);
            
            // Final Total = Subtotal + Tax + Insurance (Insurance is not taxed)
            $finalTotal = $subtotalForTax + $taxAmount + $insuranceAmount;

            $rental = Rental::create([
                'branch_id' => $data['branch_id'] ?? auth()->user()->branch_id,
                'car_id' => $car->id,
                'customer_id' => $data['customer_id'],
                'contract_number' => $this->generateContractNumber(),
                'start_date' => $startDate,
                'end_date' => $endDate,
                'start_odometer' => $data['start_odometer'],
                'fuel_level_out' => $data['fuel_level_out'],
                'daily_price' => $data['daily_price'],
                'discount' => $discount,
                'vat_percentage' => $vatPercentage,
                'tax' => $taxAmount,
                'insurance_amount' => $insuranceAmount,
                'insurance_status' => 'held',
                'insurance_notes' => $data['insurance_notes'] ?? null,
                'deposit_type' => $data['deposit_type'] ?? null,
                'late_fee_per_day' => $data['late_fee_per_day'] ?? 0,
                'contract_source' => $data['contract_source'] ?? 'direct',
                'allowed_km_per_day' => $data['allowed_km_per_day'],
                'extra_km_price' => $data['extra_km_price'],
                'total_amount' => $finalTotal,
                'additional_terms' => $data['additional_terms'] ?? null,
                'paper_contract' => $data['paper_contract'] ?? null,
                'status' => 'open',
                'created_by' => auth()->id(),
            ]);

            if (!empty($selectedAddonsData)) {
                foreach ($selectedAddonsData as $addonData) {
                    $rental->selectedAddOns()->attach($addonData['add_on_id'], [
                        'price_applied' => $addonData['price_applied'],
                        'quantity' => $addonData['quantity'],
                        'total_price' => $addonData['total_price'],
                    ]);
                }
            }

            if (isset($data['payment'])) {
                $rental->payments()->create([
                    'amount' => $data['payment']['amount'],
                    'method' => $data['payment']['method'],
                    'type' => $data['payment']['type'],
                    'notes' => $data['payment']['notes'] ?? null,
                    'created_by' => auth()->id(),
                ]);
            }

            if (isset($data['inspection'])) {
                $inspectionData = array_merge(
                    $data['inspection'],
                    ['inspection_type' => 'pickup']
                );
                $rental->inspections()->create($inspectionData);
            }

            $car->update(['rental_status' => 'rented']);

            return $rental;
        });
    }

    public function closeRental(Rental $rental, array $data)
    {
        return DB::transaction(function () use ($rental, $data) {
            $endDate = Carbon::now();
            $days = Carbon::parse($rental->start_date)->diffInDays($endDate);
            if ($days == 0) {
                $days = 1;
            }

            $endOdometer = $data['end_odometer'];
            $totalKmUsed = $endOdometer - $rental->start_odometer;
            $allowedKm = $days * $rental->allowed_km_per_day;

            $extraKm = max(0, $totalKmUsed - $allowedKm);
            $extraKmCharges = $extraKm * $rental->extra_km_price;

            $rental->update([
                'end_odometer' => $endOdometer,
                'fuel_level_in' => $data['fuel_level_in'],
                'extra_km_charges' => $extraKmCharges,
                'total_amount' => $rental->total_amount + $extraKmCharges,
                'status' => 'closed',
            ]);

            if (isset($data['violations'])) {
                foreach ($data['violations'] as $violation) {
                    $rental->violations()->create($violation);
                }
            }

            $rental->car->update([
                'rental_status' => 'available',
                'mileage' => $endOdometer
            ]);

            return $rental;
        });
    }

    private function generateContractNumber()
    {
        return 'RENT-'.strtoupper(Str::random(8));
    }

    public function getOverdueDays(Rental $rental)
    {
        if ($rental->status !== 'open' || Carbon::now()->isBefore($rental->end_date)) {
            return 0;
        }

        return Carbon::parse($rental->end_date)->diffInDays(Carbon::now());
    }
}
