<?php

namespace Tests\Feature\Notification;

use App\Domains\Attachable\Enums\AttachmentType;
use App\Domains\Attachable\Models\Attachment;
use App\Domains\Auth\Models\User;
use App\Domains\Catalog\Models\CatalogItem;
use App\Domains\Integration\Models\Integration;
use App\Domains\Notification\Services\NotificationMailService;
use App\Domains\Purchase\Models\Purchase;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Ticket\Models\Ticket;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Mail\Mailable;
use Illuminate\Support\Facades\Mail;
use Tests\TestCase;

class NotificationMailServiceTest extends TestCase
{
    use RefreshDatabase;

    private Tenant $tenant;

    private User $user;

    protected function setUp(): void
    {
        parent::setUp();

        Mail::fake();
        Integration::query()->create([
            'integration_code' => 'email',
            'name' => 'Email',
            'url' => null,
            'requires_tenant_configuration' => false,
            'integration_data_schema' => [],
        ]);
        $header = Attachment::query()->create([
            'path' => 'test/mail-header.png',
            'filename' => 'header.png',
            'type' => AttachmentType::Image,
            'mime_type' => 'image/png',
        ]);
        $footer = Attachment::query()->create([
            'path' => 'test/mail-footer.png',
            'filename' => 'footer.png',
            'type' => AttachmentType::Image,
            'mime_type' => 'image/png',
        ]);
        $this->tenant = Tenant::query()->create([
            'codigo' => 'mail-tenant',
            'nombre' => 'Mail Tenant',
            'dominio' => 'mail.local',
            'primary_color' => '#112233',
            'secondary_color' => '#000000',
            'danger_color' => '#000000',
            'success_color' => '#000000',
            'header_bg_color' => '#000000',
            'footer_bg_color' => '#000000',
            'header_logo_id' => $header->id,
            'footer_logo_id' => $footer->id,
        ]);
        $this->user = User::factory()->create([
            'nombre_apellido' => 'Ada Lovelace',
            'email' => 'ada@example.com',
        ]);
    }

    public function test_it_sends_a_branded_welcome_email(): void
    {
        app(NotificationMailService::class)->sendWelcome($this->user->id, $this->tenant->codigo);

        Mail::assertSent(Mailable::class, function (Mailable $mail): bool {
            $mail->assertTo('ada@example.com');
            $mail->assertHasSubject('Bienvenido a Mail Tenant');

            return str_contains($mail->render(), 'Ada Lovelace')
                && str_contains($mail->render(), 'Mail Tenant');
        });
    }

    public function test_it_sends_a_branded_password_reset_email(): void
    {
        $attempt = $this->user->resetPasswordAttempts()->create([
            'codigo' => '0123',
        ]);

        app(NotificationMailService::class)->sendPasswordResetCode(
            $attempt->id,
            $this->tenant->codigo,
        );

        Mail::assertSent(Mailable::class, function (Mailable $mail): bool {
            $mail->assertTo('ada@example.com');
            $mail->assertHasSubject('Código para recuperar tu contraseña - Mail Tenant');
            $rendered = $mail->render();

            return str_contains($rendered, '0123')
                && str_contains($rendered, 'Ada Lovelace')
                && str_contains($rendered, 'Mail Tenant')
                && str_contains($rendered, '#112233');
        });
    }

    public function test_it_sends_purchase_and_ticket_emails_to_the_purchase_recipient(): void
    {
        $purchase = Purchase::query()->create([
            'tenant_codigo' => $this->tenant->codigo,
            'user_id' => $this->user->id,
            'status' => Purchase::STATUS_PAID,
            'payment_method' => 'transfer',
            'total' => 25,
            'email' => 'checkout@example.com',
        ]);
        $catalogItem = CatalogItem::query()->create([
            'tenant_code' => $this->tenant->codigo,
            'slug' => 'entrada',
            'nombre' => 'Entrada',
            'descripcion' => 'Entrada general',
            'precio' => 25,
            'has_tickets' => true,
        ]);
        $purchase->items()->create([
            'source_catalog_item_id' => $catalogItem->id,
            'nombre' => 'Entrada',
            'descripcion' => 'Entrada general',
            'slug' => 'entrada',
            'item_nombre' => 'Entrada general',
            'variant_attributes' => [],
            'cantidad' => 1,
            'precio_unitario' => 25,
            'total' => 25,
        ]);
        $ticket = Ticket::query()->create([
            'tenant_code' => $this->tenant->codigo,
            'ticket' => fake()->uuid(),
            'name' => 'Entrada general',
            'description' => 'Entrada general',
            'user_id' => $this->user->id,
        ]);
        $service = app(NotificationMailService::class);

        $service->sendPurchasePaid($purchase->id);
        $service->sendTicketsAvailable($purchase->id, [$ticket->id]);

        Mail::assertSent(Mailable::class, 2);
        Mail::assertSent(Mailable::class, function (Mailable $mail) use ($purchase): bool {
            $mail->assertTo('checkout@example.com');

            return $mail->subject === "Pago confirmado - Compra #{$purchase->id}"
                && str_contains($mail->render(), 'Total pagado');
        });
        Mail::assertSent(Mailable::class, function (Mailable $mail): bool {
            $mail->assertTo('checkout@example.com');

            return $mail->subject === 'Tus tickets ya están disponibles'
                && str_contains($mail->render(), 'Entrada general');
        });
    }
}
