<?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\Events\PasswordResetRequested;
use App\Domains\Notification\Services\NotificationMailService;
use App\Domains\Purchase\Models\Purchase;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Tenant\Models\WebsiteType;
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_client_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
    {
        $this->useWebsiteTypeBranding();

        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 OnTicket');

            return str_contains($mail->render(), 'Ada Lovelace')
                && str_contains($mail->render(), 'OnTicket')
                && ! str_contains($mail->render(), 'Mail Tenant')
                && str_contains($mail->render(), 'border-top: 4px solid #ff7006');
        });
    }

    public function test_it_sends_a_branded_password_reset_email(): void
    {
        $this->useWebsiteTypeBranding();
        $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 - OnTicket');
            $rendered = $mail->render();

            return str_contains($rendered, '0123')
                && str_contains($rendered, 'Ada Lovelace')
                && str_contains($rendered, 'OnTicket')
                && ! str_contains($rendered, 'Mail Tenant')
                && str_contains($rendered, '#ff7006')
                && ! str_contains($rendered, 'border: 2px solid #112233');
        });
    }

    public function test_it_links_scanner_password_resets_to_the_scanner_domain(): void
    {
        $websiteType = WebsiteType::query()->create([
            'codigo' => 'scanner-mail',
            'nombre' => 'Scanner Mail',
            'dominio' => 'admin.mail.local',
            'scanner_domain' => 'scanner.mail.local',
        ]);
        $this->tenant->update(['website_type_code' => $websiteType->codigo]);
        $attempt = $this->user->resetPasswordAttempts()->create([
            'codigo' => '0123',
            'reason' => ResetPasswordAttempt::REASON_STAFF_CREATED,
        ]);

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

        Mail::assertSent(Mailable::class, function (Mailable $mail): bool {
            $rendered = $mail->render();

            return str_contains($rendered, 'https://scanner.mail.local/recuperar-contrasena/codigo')
                && str_contains($rendered, 'email=ada%40example.com')
                && str_contains($rendered, 'code=0123')
                && str_contains($rendered, 'Crear mi');
        });
    }

    public function test_it_sends_one_purchase_confirmation_with_generated_tickets_attached(): void
    {
        $this->useWebsiteTypeBranding();
        $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(),
            'source_purchase_id' => $purchase->id,
            'source_catalog_item_id' => $catalogItem->id,
            'user_id' => $this->user->id,
        ]);
        $service = app(NotificationMailService::class);

        $service->sendPurchaseConfirmed($purchase->id);

        Mail::assertSent(Mailable::class, 1);
        Mail::assertSent(Mailable::class, function (Mailable $mail) use ($purchase, $ticket): bool {
            $mail->assertTo('checkout@example.com');
            $attachment = collect($mail->rawAttachments)->firstWhere('name', "tickets_{$ticket->id}.pdf");

            return $mail->subject === "Compra confirmada - Compra #{$purchase->id}"
                && str_contains($mail->render(), '¡Compra realizada con éxito!')
                && str_contains($mail->render(), 'Total pagado')
                && str_contains($mail->render(), 'Tus tickets ya están disponibles')
                && $attachment !== null
                && $attachment['options'] === ['mime' => 'application/pdf']
                && str_starts_with($attachment['data'], '%PDF-')
                && str_contains($mail->render(), 'border-top: 4px solid #112233')
                && ! str_contains($mail->render(), 'border-top: 4px solid #ff7006');
        });
    }

    public function test_purchase_confirmation_omits_ticket_content_and_attachment_without_tickets(): void
    {
        $purchase = Purchase::query()->create([
            'tenant_codigo' => $this->tenant->codigo,
            'user_id' => $this->user->id,
            'status' => Purchase::STATUS_PAID,
            'payment_method' => 'transfer',
            'total' => 25,
        ]);

        app(NotificationMailService::class)->sendPurchaseConfirmed($purchase->id);

        Mail::assertSent(Mailable::class, function (Mailable $mail) use ($purchase): bool {
            return $mail->subject === "Compra confirmada - Compra #{$purchase->id}"
                && str_contains($mail->render(), '¡Compra realizada con éxito!')
                && ! str_contains($mail->render(), 'Tus tickets ya están disponibles')
                && $mail->rawAttachments === [];
        });
    }

    private function useWebsiteTypeBranding(): void
    {
        $websiteType = WebsiteType::query()->create([
            'codigo' => 'onticket',
            'nombre' => 'OnTicket',
            'dominio' => 'onticket.local',
            'primary_color' => '#ff7006',
            'body_color' => '#666666',
            'background_color' => '#f8f8f8',
            'surface_color' => '#ffffff',
            'login_header_footer_color' => '#838383',
        ]);

        $this->tenant->update(['website_type_code' => $websiteType->codigo]);
        $this->tenant->unsetRelation('websiteType');
    }
}
