<?php

namespace Tests\Feature;

use App\Domain\Billing\InvoiceService;
use App\Domain\Billing\PaymentService;
use App\Domain\Billing\RevenueService;
use App\Enums\PaymentMethod;
use App\Models\Patient;
use App\Models\Procedure;
use App\Models\Tenant;
use App\Support\Tenancy;
use Carbon\CarbonImmutable;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class RevenueReportTest extends TestCase
{
    use RefreshDatabase;

    public function test_collected_and_billed_analytics(): void
    {
        $this->seed();
        $tenant = Tenant::create(['name' => 'Smile', 'slug' => 'smile']);
        app(Tenancy::class)->set($tenant);

        $filling = Procedure::factory()->create(); // restorative 35k
        $crown = Procedure::factory()->create([
            'name_en' => 'Zirconia crown', 'name_ar' => 'تاج زيركون',
            'category' => 'prosthodontics', 'default_price' => 150000, 'default_condition' => 'crown',
        ]);

        $invSvc = app(InvoiceService::class);
        $invoice = $invSvc->createCustom(Patient::factory()->create(), [
            ['description' => 'Filling 16', 'qty' => 2, 'unit_price' => 35000, 'procedure_id' => $filling->id],
            ['description' => 'Crown 26', 'qty' => 1, 'unit_price' => 150000, 'procedure_id' => $crown->id],
        ]);
        $invSvc->issue($invoice);
        app(PaymentService::class)->record($invoice->fresh(), 100000, PaymentMethod::Cash);
        app(PaymentService::class)->record($invoice->fresh(), 50000, PaymentMethod::ZainCash, reference: 'Z1');

        $rev = app(RevenueService::class);
        $from = CarbonImmutable::now()->subDay();
        $to = CarbonImmutable::now()->addDay();

        $this->assertSame(150000, $rev->collectedBetween($from, $to));

        $byMethod = $rev->collectedByMethod($from, $to);
        $this->assertSame(100000, (int) $byMethod->firstWhere('method', 'cash')->total);
        $this->assertSame(50000, (int) $byMethod->firstWhere('method', 'zaincash')->total);

        $byCategory = $rev->billedByCategory($from, $to);
        $this->assertSame(150000, (int) $byCategory->firstWhere('category', 'prosthodontics')->total);
        $this->assertSame(70000, (int) $byCategory->firstWhere('category', 'restorative')->total);

        $top = $rev->billedByProcedure($from, $to);
        $this->assertSame($crown->id, (int) $top->first()->procedure_id); // top service
        $this->assertSame(150000, (int) $top->first()->total);
    }
}
