<?php

namespace App\Services;

use App\Models\Invoice;
use App\Models\InvoiceInstallment;
use App\Models\Notification;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;

class InstallmentService
{
    /**
     * Create installments for an invoice
     *
     * @param Invoice $invoice
     * @param int $numberOfInstallments
     * @param string $frequency monthly|quarterly|custom
     * @param array $customDates Optional array of custom dates for installments
     * @param array $customAmounts Optional array of custom amounts for installments
     * @return array
     */
    public function createInstallments(Invoice $invoice, $numberOfInstallments, $frequency = 'monthly', $customDates = [], $customAmounts = [])
    {
        // Check if invoice already has installments
        if ($invoice->installments()->count() > 0) {
            throw new \Exception('الفاتورة لديها أقساط بالفعل. يرجى حذفها أولاً.');
        }

        // Check if invoice is fully paid
        if ($invoice->status === 'paid') {
            throw new \Exception('لا يمكن إنشاء أقساط لفاتورة مدفوعة بالكامل.');
        }

        // Calculate remaining amount to be paid
        $remainingAmount = $invoice->due_amount;

        if ($remainingAmount <= 0) {
            throw new \Exception('لا يوجد مبلغ متبقي للتقسيط.');
        }

        // Start transaction
        DB::beginTransaction();

        try {
            $installments = [];
            $startDate = Carbon::parse($invoice->due_date);

            // If using custom dates and amounts
            if ($frequency === 'custom' && !empty($customDates) && !empty($customAmounts)) {
                if (count($customDates) !== count($customAmounts)) {
                    throw new \Exception('عدد التواريخ المخصصة يجب أن يساوي عدد المبالغ المخصصة.');
                }

                if (count($customDates) !== $numberOfInstallments) {
                    throw new \Exception('عدد التواريخ المخصصة يجب أن يساوي عدد الأقساط.');
                }

                $totalCustomAmount = array_sum($customAmounts);
                if (abs($totalCustomAmount - $remainingAmount) > 0.01) {
                    throw new \Exception('مجموع المبالغ المخصصة يجب أن يساوي المبلغ المتبقي.');
                }

                for ($i = 0; $i < $numberOfInstallments; $i++) {
                    $installment = InvoiceInstallment::create([
                        'invoice_id' => $invoice->id,
                        'amount' => $customAmounts[$i],
                        'due_date' => $customDates[$i],
                        'status' => 'pending',
                        'notes' => 'القسط رقم ' . ($i + 1) . ' من ' . $numberOfInstallments,
                    ]);

                    $installments[] = $installment;
                }
            } else {
                // Calculate installment amount (rounded to 2 decimal places)
                $installmentAmount = round($remainingAmount / $numberOfInstallments, 2);

                // Calculate the last installment amount to account for rounding differences
                $lastInstallmentAmount = $remainingAmount - ($installmentAmount * ($numberOfInstallments - 1));

                for ($i = 0; $i < $numberOfInstallments; $i++) {
                    // Calculate due date based on frequency
                    if ($i > 0) {
                        switch ($frequency) {
                            case 'monthly':
                                $dueDate = $startDate->copy()->addMonths($i);
                                break;
                            case 'quarterly':
                                $dueDate = $startDate->copy()->addMonths($i * 3);
                                break;
                            default:
                                $dueDate = $startDate->copy()->addMonths($i);
                        }
                    } else {
                        $dueDate = $startDate->copy();
                    }

                    // Use the calculated amount for all installments except the last one
                    $amount = ($i == $numberOfInstallments - 1) ? $lastInstallmentAmount : $installmentAmount;

                    $installment = InvoiceInstallment::create([
                        'invoice_id' => $invoice->id,
                        'amount' => $amount,
                        'due_date' => $dueDate->format('Y-m-d'),
                        'status' => 'pending',
                        'notes' => 'القسط رقم ' . ($i + 1) . ' من ' . $numberOfInstallments,
                    ]);

                    $installments[] = $installment;
                }
            }

            // Update invoice status to reflect installment plan
            $invoice->update([
                'status' => 'partially_paid',
            ]);

            // Create notification
            Notification::create([
                'company_id' => $invoice->company_id,
                'user_id' => null, // Company-wide notification
                'type' => 'installment_plan_created',
                'notifiable_type' => 'App\Models\Invoice',
                'notifiable_id' => $invoice->id,
                'title' => 'تم إنشاء خطة تقسيط',
                'message' => 'تم إنشاء خطة تقسيط للفاتورة رقم ' . $invoice->invoice_number . ' بعدد ' . $numberOfInstallments . ' قسط',
                'data' => json_encode([
                    'invoice_id' => $invoice->id,
                    'invoice_number' => $invoice->invoice_number,
                    'customer_id' => $invoice->customer_id,
                    'customer_name' => $invoice->customer->name,
                    'installments_count' => $numberOfInstallments,
                    'total_amount' => $remainingAmount
                ]),
                'status' => 'pending',
                'priority' => 'normal',
            ]);

            DB::commit();

            return $installments;
        } catch (\Exception $e) {
            DB::rollBack();
            throw $e;
        }
    }

    /**
     * Update installment statuses based on due dates
     *
     * @return array Statistics about updated installments
     */
    public function updateInstallmentStatuses()
    {
        $stats = [
            'total' => 0,
            'overdue' => 0,
            'companies' => []
        ];

        $today = Carbon::today();

        // Get all pending installments that are overdue
        $overdueInstallments = InvoiceInstallment::where('status', 'pending')
            ->where('due_date', '<', $today)
            ->with(['invoice', 'invoice.company', 'invoice.customer'])
            ->get();

        $stats['total'] = $overdueInstallments->count();

        foreach ($overdueInstallments as $installment) {
            $invoice = $installment->invoice;
            $companyId = $invoice->company_id;

            if (!isset($stats['companies'][$companyId])) {
                $stats['companies'][$companyId] = [
                    'name' => $invoice->company->name,
                    'count' => 0
                ];
            }

            // Update status to overdue
            $installment->status = 'overdue';
            $installment->save();

            $stats['overdue']++;
            $stats['companies'][$companyId]['count']++;

            // Create notification
            Notification::create([
                'company_id' => $companyId,
                'user_id' => null, // Company-wide notification
                'type' => 'installment_overdue',
                'notifiable_type' => 'App\Models\InvoiceInstallment',
                'notifiable_id' => $installment->id,
                'title' => 'قسط متأخر',
                'message' => 'القسط رقم ' . $installment->id . ' للفاتورة رقم ' . $invoice->invoice_number . ' متأخر عن موعد استحقاقه',
                'data' => json_encode([
                    'installment_id' => $installment->id,
                    'invoice_id' => $invoice->id,
                    'invoice_number' => $invoice->invoice_number,
                    'customer_id' => $invoice->customer_id,
                    'customer_name' => $invoice->customer->name,
                    'amount' => $installment->amount,
                    'due_date' => $installment->due_date
                ]),
                'status' => 'pending',
                'priority' => 'high',
            ]);
        }

        return $stats;
    }

    /**
     * Record a payment for an installment
     *
     * @param InvoiceInstallment $installment
     * @param float $amount
     * @param array $paymentData
     * @return \App\Models\Payment
     */
    public function recordInstallmentPayment(InvoiceInstallment $installment, $amount, $paymentData)
    {
        $invoice = $installment->invoice;

        // Check if amount is valid
        if ($amount <= 0) {
            throw new \Exception('مبلغ الدفع يجب أن يكون أكبر من صفر.');
        }

        // Check if amount exceeds the remaining amount for this installment
        $remainingInstallmentAmount = $installment->amount - $installment->paid_amount;

        if ($amount > $remainingInstallmentAmount) {
            throw new \Exception('مبلغ الدفع يتجاوز المبلغ المتبقي للقسط.');
        }

        DB::beginTransaction();

        try {
            // Create payment record
            $payment = $invoice->payments()->create([
                'amount' => $amount,
                'payment_date' => $paymentData['payment_date'] ?? now(),
                'payment_method_id' => $paymentData['payment_method_id'],
                'reference' => $paymentData['reference'] ?? null,
                'notes' => $paymentData['notes'] ?? 'دفعة للقسط رقم ' . $installment->id,
                'company_id' => $invoice->company_id,
                'invoice_installment_id' => $installment->id,
            ]);

            // Update installment paid amount
            $newPaidAmount = $installment->paid_amount + $amount;
            $installment->paid_amount = $newPaidAmount;

            // Update installment status if fully paid
            if ($newPaidAmount >= $installment->amount) {
                $installment->status = 'paid';
            } elseif ($installment->status === 'overdue') {
                $installment->status = 'partially_paid';
            }

            $installment->save();

            // Update invoice paid and due amounts
            $invoice->paid_amount += $amount;
            $invoice->due_amount -= $amount;

            // Update invoice status
            if ($invoice->due_amount <= 0) {
                $invoice->status = 'paid';
            } else {
                $invoice->status = 'partially_paid';
            }

            $invoice->save();

            // Create notification
            Notification::create([
                'company_id' => $invoice->company_id,
                'user_id' => null, // Company-wide notification
                'type' => 'installment_payment_received',
                'notifiable_type' => 'App\Models\Payment',
                'notifiable_id' => $payment->id,
                'title' => 'تم استلام دفعة للقسط',
                'message' => 'تم استلام دفعة بقيمة ' . $amount . ' للقسط رقم ' . $installment->id . ' للفاتورة رقم ' . $invoice->invoice_number,
                'data' => json_encode([
                    'payment_id' => $payment->id,
                    'installment_id' => $installment->id,
                    'invoice_id' => $invoice->id,
                    'invoice_number' => $invoice->invoice_number,
                    'customer_id' => $invoice->customer_id,
                    'customer_name' => $invoice->customer->name,
                    'amount' => $amount,
                    'payment_date' => $paymentData['payment_date'] ?? now()
                ]),
                'status' => 'pending',
                'priority' => 'normal',
            ]);

            DB::commit();

            return $payment;
        } catch (\Exception $e) {
            DB::rollBack();
            throw $e;
        }
    }
}
