<?php

namespace Tests\Feature;

use App\Models\InvoiceInstallment;
use App\Models\Invoice;
use App\Models\User;
use App\Models\Customer;
use App\Models\Company;
use Carbon\Carbon;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;

class InvoiceInstallmentTest extends TestCase
{
    use RefreshDatabase, WithFaker;

    protected $user;
    protected $company;
    protected $customer;
    protected $invoice;

    /**
     * إعداد بيئة الاختبار.
     *
     * @return void
     */
    public function setUp(): void
    {
        parent::setUp();

        // إنشاء شركة للاختبار
        $this->company = Company::factory()->create();

        // إنشاء مستخدم للاختبار
        $this->user = User::factory()->create([
            'company_id' => $this->company->id,
        ]);

        // إنشاء عميل للاختبار
        $this->customer = Customer::factory()->create([
            'company_id' => $this->company->id,
        ]);

        // إنشاء فاتورة للاختبار
        $this->invoice = Invoice::factory()->create([
            'company_id' => $this->company->id,
            'customer_id' => $this->customer->id,
            'total_amount' => 1000,
            'due_amount' => 1000,
            'status' => 'pending',
        ]);

        // تسجيل دخول المستخدم
        $this->actingAs($this->user);
    }

    /**
     * اختبار إنشاء قسط جديد.
     *
     * @return void
     */
    public function testCreateInstallment()
    {
        $response = $this->post(route('invoice-installments.store'), [
            'invoice_id' => $this->invoice->id,
            'amount' => 500,
            'due_date' => Carbon::now()->addDays(30)->format('Y-m-d'),
            'notes' => 'قسط اختبار',
        ]);

        $response->assertRedirect(route('invoice-installments.index'));
        $response->assertSessionHas('success');

        $this->assertDatabaseHas('invoice_installments', [
            'invoice_id' => $this->invoice->id,
            'amount' => 500,
            'status' => 'pending',
        ]);
    }

    /**
     * اختبار عرض قائمة الأقساط.
     *
     * @return void
     */
    public function testIndexInstallments()
    {
        // إنشاء بعض الأقساط للاختبار
        InvoiceInstallment::factory()->count(3)->create([
            'invoice_id' => $this->invoice->id,
        ]);

        $response = $this->get(route('invoice-installments.index'));

        $response->assertStatus(200);
        $response->assertViewIs('invoice_installments.index');
        $response->assertViewHas('installments');
    }

    /**
     * اختبار عرض تفاصيل قسط.
     *
     * @return void
     */
    public function testShowInstallment()
    {
        $installment = InvoiceInstallment::factory()->create([
            'invoice_id' => $this->invoice->id,
        ]);

        $response = $this->get(route('invoice-installments.show', $installment->id));

        $response->assertStatus(200);
        $response->assertViewIs('invoice_installments.show');
        $response->assertViewHas('installment');
    }

    /**
     * اختبار تحديث قسط.
     *
     * @return void
     */
    public function testUpdateInstallment()
    {
        $installment = InvoiceInstallment::factory()->create([
            'invoice_id' => $this->invoice->id,
            'amount' => 500,
            'status' => 'pending',
        ]);

        $response = $this->put(route('invoice-installments.update', $installment->id), [
            'invoice_id' => $this->invoice->id,
            'amount' => 600,
            'due_date' => Carbon::now()->addDays(45)->format('Y-m-d'),
            'status' => 'pending',
            'notes' => 'قسط محدث',
        ]);

        $response->assertRedirect(route('invoice-installments.index'));
        $response->assertSessionHas('success');

        $this->assertDatabaseHas('invoice_installments', [
            'id' => $installment->id,
            'amount' => 600,
            'notes' => 'قسط محدث',
        ]);
    }

    /**
     * اختبار تسجيل دفعة لقسط.
     *
     * @return void
     */
    public function testRecordPayment()
    {
        // إنشاء طريقة دفع للاختبار
        $paymentMethod = \App\Models\PaymentMethod::factory()->create([
            'company_id' => $this->company->id,
        ]);

        $installment = InvoiceInstallment::factory()->create([
            'invoice_id' => $this->invoice->id,
            'amount' => 500,
            'paid_amount' => 0,
            'status' => 'pending',
        ]);

        $response = $this->post(route('invoice-installments.record-payment', $installment->id), [
            'amount' => 300,
            'payment_date' => Carbon::now()->format('Y-m-d'),
            'payment_method_id' => $paymentMethod->id,
            'reference_number' => 'REF123',
            'notes' => 'دفعة اختبار',
        ]);

        $response->assertRedirect(route('invoice-installments.show', $installment->id));
        $response->assertSessionHas('success');

        // التحقق من تحديث القسط
        $this->assertDatabaseHas('invoice_installments', [
            'id' => $installment->id,
            'paid_amount' => 300,
        ]);

        // التحقق من إنشاء سجل الدفعة
        $this->assertDatabaseHas('payments', [
            'invoice_id' => $this->invoice->id,
            'amount' => 300,
            'reference_number' => 'REF123',
        ]);
    }

    /**
     * اختبار تحديث حالة الأقساط المتأخرة.
     *
     * @return void
     */
    public function testUpdateOverdueInstallments()
    {
        // إنشاء قسط متأخر
        $installment = InvoiceInstallment::factory()->create([
            'invoice_id' => $this->invoice->id,
            'amount' => 500,
            'paid_amount' => 0,
            'status' => 'pending',
            'due_date' => Carbon::now()->subDays(5)->format('Y-m-d'),
        ]);

        // تنفيذ الأمر المجدول
        $this->artisan('installments:update-overdue')
            ->assertExitCode(0);

        // التحقق من تحديث حالة القسط
        $this->assertDatabaseHas('invoice_installments', [
            'id' => $installment->id,
            'status' => 'overdue',
        ]);

        // التحقق من تحديث حالة الفاتورة
        $this->assertDatabaseHas('invoices', [
            'id' => $this->invoice->id,
            'status' => 'overdue',
        ]);
    }

    /**
     * اختبار طرق التحقق من حالة القسط.
     *
     * @return void
     */
    public function testInstallmentStatusMethods()
    {
        // قسط مدفوع بالكامل
        $paidInstallment = InvoiceInstallment::factory()->create([
            'invoice_id' => $this->invoice->id,
            'amount' => 500,
            'paid_amount' => 500,
            'status' => 'paid',
        ]);

        $this->assertTrue($paidInstallment->isPaid());
        $this->assertFalse($paidInstallment->isPartiallyPaid());
        $this->assertFalse($paidInstallment->isOverdue());

        // قسط مدفوع جزئياً
        $partiallyPaidInstallment = InvoiceInstallment::factory()->create([
            'invoice_id' => $this->invoice->id,
            'amount' => 500,
            'paid_amount' => 200,
            'status' => 'pending',
        ]);

        $this->assertFalse($partiallyPaidInstallment->isPaid());
        $this->assertTrue($partiallyPaidInstallment->isPartiallyPaid());

        // قسط متأخر
        $overdueInstallment = InvoiceInstallment::factory()->create([
            'invoice_id' => $this->invoice->id,
            'amount' => 500,
            'paid_amount' => 0,
            'status' => 'overdue',
            'due_date' => Carbon::now()->subDays(10)->format('Y-m-d'),
        ]);

        $this->assertFalse($overdueInstallment->isPaid());
        $this->assertFalse($overdueInstallment->isPartiallyPaid());
        $this->assertTrue($overdueInstallment->isOverdue());
    }
}
