<?php

namespace Tests\Unit\Sale;

use App\Domains\Auth\Models\User;
use App\Domains\Logging\Models\ValueChange;
use App\Domains\Purchase\Models\Purchase;
use App\Domains\Sale\Services\AdminAppSaleExcelService;
use App\Domains\Tenant\Models\Tenant;
use Illuminate\Support\Carbon;
use PhpOffice\PhpSpreadsheet\IOFactory;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Tests\TestCase;

class AdminAppSaleExcelServiceTest extends TestCase
{
    protected function setUp(): void
    {
        parent::setUp();

        Carbon::setTestNow(Carbon::parse('2026-08-24 17:53:00', 'UTC'));
    }

    protected function tearDown(): void
    {
        Carbon::setTestNow();

        parent::tearDown();
    }

    public function test_it_downloads_filtered_sales_as_an_excel_file(): void
    {
        $response = app(AdminAppSaleExcelService::class)->downloadSales(
            $this->tenant(),
            collect([$this->sale()]),
            'America/La_Paz',
        );

        $this->assertExcelResponse(
            $response,
            'ventas_acme_20260824_135300.xlsx',
            function (string $path): void {
                $sheet = IOFactory::load($path)->getActiveSheet();

                $this->assertSame('Ventas', $sheet->getTitle());
                $this->assertSame('Cliente Test', $sheet->getCell('C2')->getValue());
                $this->assertSame('Confirmado', $sheet->getCell('E2')->getValue());
                $this->assertSame(25000.0, $sheet->getCell('F2')->getValue());
            },
        );
    }

    public function test_it_downloads_the_modification_history_as_an_excel_file(): void
    {
        $sale = $this->sale();
        $admin = (new User)->forceFill([
            'id' => 10,
            'nombre_apellido' => 'Admin Test',
            'email' => 'admin@example.test',
        ]);
        $modification = (new ValueChange)->forceFill([
            'id' => 1,
            'trackable_id' => $sale->id,
            'attribute' => 'status',
            'old_value' => Purchase::STATUS_PENDING_PAYMENT,
            'new_value' => Purchase::STATUS_PAID,
            'changed_at' => now(),
            'actor_type' => 'user',
        ]);
        $modification->setRelation('trackable', $sale);
        $modification->setRelation('user', $admin);

        $response = app(AdminAppSaleExcelService::class)->downloadModifications(
            $this->tenant(),
            collect([$modification]),
            'America/La_Paz',
        );

        $this->assertExcelResponse(
            $response,
            'historial_modificaciones_acme_20260824_135300.xlsx',
            function (string $path): void {
                $sheet = IOFactory::load($path)->getActiveSheet();

                $this->assertSame('Modificaciones', $sheet->getTitle());
                $this->assertSame('#15', $sheet->getCell('C2')->getValue());
                $this->assertSame('pending_payment', $sheet->getCell('F2')->getValue());
                $this->assertSame('paid', $sheet->getCell('G2')->getValue());
                $this->assertSame('Admin Test', $sheet->getCell('H2')->getValue());
            },
        );
    }

    /** @param callable(string): void $assertSpreadsheet */
    private function assertExcelResponse(
        StreamedResponse $response,
        string $filename,
        callable $assertSpreadsheet,
    ): void {
        $this->assertSame(
            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            $response->headers->get('content-type'),
        );
        $this->assertStringContainsString(
            "attachment; filename={$filename}",
            (string) $response->headers->get('content-disposition'),
        );

        ob_start();
        ($response->getCallback())();
        $contents = ob_get_clean();
        $this->assertIsString($contents);
        $this->assertStringStartsWith('PK', $contents);

        $path = tempnam(sys_get_temp_dir(), 'shopit_excel_');
        $this->assertNotFalse($path);

        try {
            file_put_contents($path, $contents);
            $assertSpreadsheet($path);
        } finally {
            @unlink($path);
        }
    }

    private function tenant(): Tenant
    {
        return (new Tenant)->forceFill([
            'codigo' => 'acme',
            'nombre' => 'Acme Eventos',
        ]);
    }

    private function sale(): Purchase
    {
        return (new Purchase)->forceFill([
            'id' => 15,
            'created_at' => now(),
            'nombre_apellido' => 'Cliente Test',
            'quantity' => 2,
            'status' => Purchase::STATUS_PAID,
            'total' => '25000.00',
            'tickets_count' => 2,
        ]);
    }
}
