<?php

use App\Models\User;
use Livewire\Livewire;
use Maatwebsite\Excel\Excel as ExcelFormat;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Booking\Enums\BookingStatus;
use Modules\Booking\Models\Booking;
use Modules\Reporting\Exports\BookingsRevenueExport;
use Modules\Reporting\Filament\Pages\BookingsRevenueReport;
use PhpOffice\PhpSpreadsheet\IOFactory;
use Spatie\Permission\Models\Permission;

beforeEach(function () {
    Permission::findOrCreate('view_reports', 'web');

    $this->admin = User::factory()->create()->givePermissionTo(['view_reports']);
    $this->actingAs($this->admin);
});

test('it renders for a user with view_reports', function () {
    Livewire::test(BookingsRevenueReport::class)->assertOk();
});

test('a user without view_reports cannot access it', function () {
    $this->actingAs(User::factory()->create());

    expect(BookingsRevenueReport::canAccess())->toBeFalse();
});

test('it narrows results by travel date range and status', function () {
    $inRange = Booking::factory()->create(['travel_date' => today(), 'status' => BookingStatus::Confirmed]);
    $outOfRange = Booking::factory()->create(['travel_date' => today()->addMonths(2), 'status' => BookingStatus::Confirmed]);
    $wrongStatus = Booking::factory()->create(['travel_date' => today(), 'status' => BookingStatus::Cancelled]);

    Livewire::test(BookingsRevenueReport::class)
        ->fillForm([
            'travel_date_from' => today()->toDateString(),
            'travel_date_to' => today()->toDateString(),
            'status' => BookingStatus::Confirmed->value,
        ], 'filtersForm')
        ->assertCanSeeTableRecords([$inRange])
        ->assertCanNotSeeTableRecords([$outOfRange, $wrongStatus]);
});

test('exporting csv triggers a download', function () {
    Excel::fake();

    Booking::factory()->create();

    Livewire::test(BookingsRevenueReport::class)->callAction('exportCsv');

    Excel::assertDownloaded('bookings-revenue-'.now()->format('Y-m-d').'.csv');
});

test('exporting excel triggers a download', function () {
    Excel::fake();

    Booking::factory()->create();

    Livewire::test(BookingsRevenueReport::class)->callAction('exportXlsx');

    Excel::assertDownloaded('bookings-revenue-'.now()->format('Y-m-d').'.xlsx');
});

test('the export includes passenger name/count columns and a total row', function () {
    $a = Booking::factory()->create(['passenger_name' => 'Jane Doe', 'price' => 10000]);
    $a->vehicleOptions()->create(['vehicle_option' => 'back_seat', 'passenger_count' => 2, 'unit_price' => 5000, 'line_total' => 10000]);

    $b = Booking::factory()->create(['passenger_name' => 'John Roe', 'price' => 15000]);
    $b->vehicleOptions()->create(['vehicle_option' => 'back_seat', 'passenger_count' => 3, 'unit_price' => 5000, 'line_total' => 15000]);

    $export = new BookingsRevenueExport(Booking::query()->with(['route.fromDestination', 'route.toDestination', 'payments', 'vehicleOptions']));

    $path = storage_path('app/test-bookings-revenue.xlsx');
    file_put_contents($path, Excel::raw($export, ExcelFormat::XLSX));

    $sheet = IOFactory::load($path)->getActiveSheet();
    unlink($path);

    expect($sheet->getCell('F1')->getValue())->toBe('Passenger Name')
        ->and($sheet->getCell('G1')->getValue())->toBe('Passenger Count')
        ->and([$sheet->getCell('F2')->getValue(), $sheet->getCell('F3')->getValue()])->toContain('Jane Doe', 'John Roe');

    $totalRow = $sheet->getHighestRow();
    expect($sheet->getCell("A{$totalRow}")->getValue())->toBe('TOTAL')
        ->and((int) $sheet->getCell("G{$totalRow}")->getValue())->toBe(5) // 2 + 3 passengers
        ->and((float) $sheet->getCell("H{$totalRow}")->getValue())->toBe(25000.0); // 10000 + 15000 price
});
