<?php

namespace Tests\Unit;

use App\Services\FinanceService;
use PHPUnit\Framework\TestCase;

class FinanceServiceTest extends TestCase
{
    private FinanceService $service;

    protected function setUp(): void
    {
        parent::setUp();
        $this->service = new FinanceService;
    }

    /** @test */
    public function it_generates_invoice_numbers_with_correct_format(): void
    {
        $number = $this->service->generateInvoiceNumber();

        $this->assertStringStartsWith('INV-', $number);
        $this->assertMatchesRegularExpression('/^INV-\d{8}-[A-Z0-9]{6}$/', $number);
    }

    /** @test */
    public function it_generates_unique_invoice_numbers(): void
    {
        $numbers = array_map(fn () => $this->service->generateInvoiceNumber(), range(1, 10));
        $unique = array_unique($numbers);

        $this->assertCount(count($numbers), $unique, 'Invoice numbers should be unique');
    }

    /** @test */
    public function it_generates_transaction_ids_with_custom_prefix(): void
    {
        $id = $this->service->generateTransactionId('PAY');

        $this->assertStringStartsWith('PAY-', $id);
        $this->assertMatchesRegularExpression('/^PAY-\d{8}-[A-Z0-9]{6}$/', $id);
    }

    /** @test */
    public function it_generates_transaction_ids_with_default_prefix(): void
    {
        $id = $this->service->generateTransactionId();

        $this->assertStringStartsWith('TXN-', $id);
    }

    /** @test */
    public function it_calculates_invoice_totals_correctly(): void
    {
        $items = [
            ['description' => 'Oil Change', 'quantity' => 1, 'unit_price' => 200, 'tax_rate' => 14],
            ['description' => 'Brake Pads', 'quantity' => 2, 'unit_price' => 350, 'tax_rate' => 14],
        ];

        $result = $this->service->calculateInvoiceTotals($items);

        // Subtotal: (1*200) + (2*350) = 200 + 700 = 900
        $this->assertEquals(900, $result['subtotal']);

        // Tax: (200 * 0.14) + (700 * 0.14) = 28 + 98 = 126
        $this->assertEquals(126, $result['tax']);

        // Total: 900 + 126 = 1026
        $this->assertEquals(1026, $result['total']);

        $this->assertCount(2, $result['items']);
    }

    /** @test */
    public function it_calculates_totals_with_zero_tax(): void
    {
        $items = [
            ['description' => 'Consultation', 'quantity' => 1, 'unit_price' => 500],
        ];

        $result = $this->service->calculateInvoiceTotals($items);

        $this->assertEquals(500, $result['subtotal']);
        $this->assertEquals(0, $result['tax']);
        $this->assertEquals(500, $result['total']);
    }

    /** @test */
    public function it_handles_empty_items_array(): void
    {
        $result = $this->service->calculateInvoiceTotals([]);

        $this->assertEquals(0, $result['subtotal']);
        $this->assertEquals(0, $result['tax']);
        $this->assertEquals(0, $result['total']);
        $this->assertEmpty($result['items']);
    }

    /** @test */
    public function it_preserves_item_data_in_totals(): void
    {
        $items = [
            ['description' => 'Engine Repair', 'quantity' => 1, 'unit_price' => 5000, 'tax_rate' => 14, 'vehicle_id' => 'abc-123'],
        ];

        $result = $this->service->calculateInvoiceTotals($items);

        $item = $result['items'][0];
        $this->assertEquals('Engine Repair', $item['description']);
        $this->assertEquals(1, $item['quantity']);
        $this->assertEquals(5000, $item['unit_price']);
        $this->assertEquals(5000, $item['total_price']);
        $this->assertEquals(14, $item['tax_rate']);
        $this->assertEquals(700, $item['tax_amount']);
        $this->assertEquals('abc-123', $item['vehicle_id']);
    }

    /** @test */
    public function it_handles_large_quantities_and_prices(): void
    {
        $items = [
            ['description' => 'Vehicle Sale', 'quantity' => 1, 'unit_price' => 2500000, 'tax_rate' => 14],
        ];

        $result = $this->service->calculateInvoiceTotals($items);

        $this->assertEquals(2500000, $result['subtotal']);
        $this->assertEquals(350000, $result['tax']);
        $this->assertEquals(2850000, $result['total']);
    }

    /** @test */
    public function it_sets_null_vehicle_id_when_not_provided(): void
    {
        $items = [
            ['description' => 'Service', 'quantity' => 1, 'unit_price' => 100],
        ];

        $result = $this->service->calculateInvoiceTotals($items);

        $this->assertNull($result['items'][0]['vehicle_id']);
    }
}
