<?php

namespace App\Services;

use App\Models\Rental\Invoice;
use App\Models\Rental\InvoiceItem;
use App\Models\Rental\PaymentVoucher;
use App\Models\Rental\Rental;
use App\Models\Car;
use App\Models\Customer;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;

class InvoiceService
{
    const TAX_PERCENTAGE = 15; // السعودية VAT

    public function createInvoiceFromRental(Rental $rental, ?string $description = null, ?int $createdBy = null, bool $applyExistingPayments = false, bool $taxIncluded = false, ?float $vatPercentage = null): Invoice
    {
        return DB::transaction(function () use ($rental, $description, $createdBy, $applyExistingPayments, $taxIncluded, $vatPercentage) {
            $invoice = new Invoice();
            $invoice->branch_id = $rental->branch_id;
            $invoice->rental_id = $rental->id;
            $invoice->car_id = $rental->car_id;
            $invoice->customer_id = $rental->customer_id;
            $invoice->type = 'rental';
            $invoice->invoice_date = now();
            $invoice->due_date = now()->addDays(30);
            $invoice->description = $description ?? "فاتورة إيجار - " . $rental->contract_number;
            $invoice->created_by = $createdBy ?? auth()->id();

            $total = $rental->total_amount;
            $vatPercentage = $vatPercentage ?? self::TAX_PERCENTAGE;
            
            if ($taxIncluded) {
                $subtotal = round($total / (1 + ($vatPercentage / 100)), 2);
                $taxAmount = $total - $subtotal;
            } else {
                $subtotal = $total;
                $taxAmount = $this->calculateTax($subtotal, $vatPercentage);
                $total = $subtotal + $taxAmount;
            }

            $invoice->subtotal = $subtotal;
            $invoice->tax_percentage = $vatPercentage;
            $invoice->tax_amount = $taxAmount;
            $invoice->total_amount = $total;
            
            if ($applyExistingPayments) {
                $paidAmount = min($rental->paid_amount, $invoice->total_amount);
                $invoice->paid_amount = $paidAmount;
                $invoice->remaining_amount = $invoice->total_amount - $paidAmount;
                $invoice->status = ($invoice->remaining_amount <= 0) ? 'paid' : 'partially_paid';
                
                // ربط سندات القبض القديمة بالفاتورة الجديدة
                PaymentVoucher::where('rental_id', $rental->id)
                    ->whereNull('invoice_id')
                    ->update(['invoice_id' => $invoice->id]);
            } else {
                $invoice->remaining_amount = $invoice->total_amount;
                $invoice->status = 'draft';
            }

            $invoice->invoice_number = $invoice->generateInvoiceNumber();
            $invoice->qr_code_data = $invoice->generateQRCodeData();
            $invoice->save();

            $item = new InvoiceItem();
            $item->invoice_id = $invoice->id;
            $item->description = "إيجار سيارة - " . $rental->car->title;
            $item->quantity = $rental->start_date->diffInDays($rental->end_date) + 1;
            $item->unit_price = $rental->daily_price;
            $item->amount = $rental->total_amount;
            $item->save();

            return $invoice;
        });
    }

    public function createManualInvoice(
        int $branchId,
        int $customerId,
        array $items,
        ?string $type = 'service',
        ?string $description = null,
        ?int $carId = null,
        ?int $rentalId = null,
        ?int $createdBy = null,
        bool $taxIncluded = false,
        ?float $vatPercentage = null
    ): Invoice {
        return DB::transaction(function () use ($branchId, $customerId, $items, $type, $description, $carId, $rentalId, $createdBy, $taxIncluded, $vatPercentage) {
            $subtotalInput = 0;
            foreach ($items as $item) {
                $subtotalInput += $item['amount'];
            }

            $vatPercentage = $vatPercentage ?? self::TAX_PERCENTAGE;

            if ($taxIncluded) {
                $total = $subtotalInput;
                $subtotal = round($total / (1 + ($vatPercentage / 100)), 2);
                $taxAmount = $total - $subtotal;
            } else {
                $subtotal = $subtotalInput;
                $taxAmount = $this->calculateTax($subtotal, $vatPercentage);
                $total = $subtotal + $taxAmount;
            }

            $invoice = new Invoice();
            $invoice->branch_id = $branchId;
            $invoice->car_id = $carId;
            $invoice->rental_id = $rentalId;
            $invoice->customer_id = $customerId;
            $invoice->type = $type;
            $invoice->invoice_date = now();
            $invoice->due_date = now()->addDays(30);
            $invoice->description = $description ?? 'فاتورة';
            $invoice->created_by = $createdBy ?? auth()->id();
            $invoice->subtotal = $subtotal;
            $invoice->tax_percentage = $vatPercentage;
            $invoice->tax_amount = $taxAmount;
            $invoice->total_amount = $total;
            $invoice->remaining_amount = $invoice->total_amount;
            $invoice->invoice_number = $invoice->generateInvoiceNumber();
            $invoice->qr_code_data = $invoice->generateQRCodeData();
            $invoice->save();

            foreach ($items as $item) {
                InvoiceItem::create([
                    'invoice_id' => $invoice->id,
                    'description' => $item['description'],
                    'quantity' => $item['quantity'] ?? 1,
                    'unit_price' => $item['unit_price'],
                    'amount' => $item['amount'],
                ]);
            }

            return $invoice;
        });
    }

    public function recordPayment(Invoice $invoice, float $amount, string $paymentMethod = 'cash', ?string $referenceNumber = null, ?int $receivedBy = null): PaymentVoucher
    {
        return DB::transaction(function () use ($invoice, $amount, $paymentMethod, $referenceNumber, $receivedBy) {
            $invoice->recordPayment($amount);

            $voucher = new PaymentVoucher();
            $voucher->branch_id = $invoice->branch_id;
            $voucher->invoice_id = $invoice->id;
            $voucher->rental_id = $invoice->rental_id;
            $voucher->customer_id = $invoice->customer_id;
            $voucher->amount_paid = $amount;
            $voucher->payment_method = $paymentMethod;
            $voucher->reference_number = $referenceNumber;
            $voucher->voucher_date = now();
            $voucher->received_by = $receivedBy ?? auth()->id();
            $voucher->voucher_number = $voucher->generateVoucherNumber();
            $voucher->qr_code_data = $voucher->generateQRCodeData();
            $voucher->save();

            return $voucher;
        });
    }

    public function recordCheckPayment(
        Invoice $invoice,
        float $amount,
        string $checkNumber,
        Carbon $checkDate,
        ?string $bankName = null,
        ?string $referenceNumber = null,
        ?int $receivedBy = null
    ): PaymentVoucher {
        return DB::transaction(function () use ($invoice, $amount, $checkNumber, $checkDate, $bankName, $referenceNumber, $receivedBy) {
            $invoice->recordPayment($amount);

            $voucher = new PaymentVoucher();
            $voucher->branch_id = $invoice->branch_id;
            $voucher->invoice_id = $invoice->id;
            $voucher->rental_id = $invoice->rental_id;
            $voucher->customer_id = $invoice->customer_id;
            $voucher->amount_paid = $amount;
            $voucher->payment_method = 'check';
            $voucher->check_number = $checkNumber;
            $voucher->check_date = $checkDate;
            $voucher->bank_name = $bankName;
            $voucher->reference_number = $referenceNumber;
            $voucher->voucher_date = now();
            $voucher->received_by = $receivedBy ?? auth()->id();
            $voucher->voucher_number = $voucher->generateVoucherNumber();
            $voucher->qr_code_data = $voucher->generateQRCodeData();
            $voucher->save();

            return $voucher;
        });
    }

    public function cancelInvoice(Invoice $invoice, ?string $reason = null): void
    {
        DB::transaction(function () use ($invoice, $reason) {
            $invoice->update([
                'status' => 'cancelled',
                'notes' => ($invoice->notes ?? '') . "\nملغاة في: " . now() . ($reason ? " - السبب: " . $reason : ''),
            ]);

            $invoice->paymentVouchers()->update(['status' => 'cancelled']);
        });
    }

    public function issueInvoice(Invoice $invoice): void
    {
        if ($invoice->status === 'draft') {
            $invoice->update(['status' => 'issued']);
        }
    }

    private function calculateTax(float $amount, ?float $vatPercentage = null): float
    {
        $percentage = $vatPercentage ?? self::TAX_PERCENTAGE;
        return round($amount * ($percentage / 100), 2);
    }

    public function getInvoicesByCustomer(int $customerId, ?Carbon $startDate = null, ?Carbon $endDate = null)
    {
        $query = Invoice::where('customer_id', $customerId);

        if ($startDate) {
            $query->whereDate('invoice_date', '>=', $startDate);
        }

        if ($endDate) {
            $query->whereDate('invoice_date', '<=', $endDate);
        }

        return $query->orderBy('invoice_date', 'desc')->get();
    }

    public function getUnpaidInvoices(?int $branchId = null)
    {
        $query = Invoice::whereIn('status', ['issued', 'partially_paid']);

        if ($branchId) {
            $query->where('branch_id', $branchId);
        }

        return $query->orderBy('due_date')->get();
    }

    public function getInvoiceStatistics(?int $branchId = null, ?Carbon $startDate = null, ?Carbon $endDate = null)
    {
        $query = Invoice::query();

        if ($branchId) {
            $query->where('branch_id', $branchId);
        }

        if ($startDate) {
            $query->whereDate('invoice_date', '>=', $startDate);
        }

        if ($endDate) {
            $query->whereDate('invoice_date', '<=', $endDate);
        }

        return [
            'total_invoices' => $query->clone()->count(),
            'issued_invoices' => $query->clone()->where('status', 'issued')->count(),
            'paid_invoices' => $query->clone()->where('status', 'paid')->count(),
            'partially_paid_invoices' => $query->clone()->where('status', 'partially_paid')->count(),
            'cancelled_invoices' => $query->clone()->where('status', 'cancelled')->count(),
            'total_amount' => $query->clone()->sum('total_amount'),
            'paid_amount' => $query->clone()->sum('paid_amount'),
            'remaining_amount' => $query->clone()->sum('remaining_amount'),
        ];
    }
}
