<?php

declare(strict_types=1);

use App\Models\EmailTemplate;
use App\Models\User;
use Database\Seeders\EmailTemplateSeeder;
use Database\Seeders\RoleAndPermissionSeeder;

beforeEach(function (): void {
    $this->seed(RoleAndPermissionSeeder::class);
    $this->adminUrl = 'http://'.config('app.domains.admin');
});

// ---------------------------------------------------------------------------
// Index
// ---------------------------------------------------------------------------
describe('Email Template Index', function (): void {
    it('allows admin to list email templates', function (): void {
        $admin = User::factory()->admin()->create();
        EmailTemplate::factory()->count(3)->create();

        $this->actingAs($admin)
            ->get($this->adminUrl.'/email-templates')
            ->assertOk()
            ->assertInertia(fn ($page) => $page
                ->component('Admin/EmailTemplates/Index')
                ->has('templates', 3)
            );
    });

    it('denies customer access to email templates', function (): void {
        $customer = User::factory()->customer()->create();

        $this->actingAs($customer)
            ->get($this->adminUrl.'/email-templates')
            ->assertForbidden();
    });
});

// ---------------------------------------------------------------------------
// Edit
// ---------------------------------------------------------------------------
describe('Email Template Edit', function (): void {
    it('allows admin to view edit form', function (): void {
        $admin = User::factory()->admin()->create();
        $template = EmailTemplate::factory()->create(['slug' => 'payment-succeeded']);

        $this->actingAs($admin)
            ->get($this->adminUrl.'/email-templates/'.$template->id.'/edit')
            ->assertOk()
            ->assertInertia(fn ($page) => $page
                ->component('Admin/EmailTemplates/Edit')
                ->has('template')
                ->where('template.slug', 'payment-succeeded')
            );
    });
});

// ---------------------------------------------------------------------------
// Update
// ---------------------------------------------------------------------------
describe('Email Template Update', function (): void {
    it('allows admin to update template subject and body', function (): void {
        $admin = User::factory()->admin()->create();
        $template = EmailTemplate::factory()->create();

        $this->actingAs($admin)
            ->put($this->adminUrl.'/email-templates/'.$template->id, [
                'subject' => 'New Subject {{customer_name}}',
                'body' => 'New body content with {{amount}}',
                'is_active' => true,
            ])
            ->assertRedirect();

        $template->refresh();
        expect($template->subject)->toBe('New Subject {{customer_name}}');
        expect($template->body)->toBe('New body content with {{amount}}');
    });

    it('allows admin to toggle active status', function (): void {
        $admin = User::factory()->admin()->create();
        $template = EmailTemplate::factory()->create(['is_active' => true]);

        $this->actingAs($admin)
            ->put($this->adminUrl.'/email-templates/'.$template->id, [
                'subject' => $template->subject,
                'body' => $template->body,
                'is_active' => false,
            ])
            ->assertRedirect();

        $template->refresh();
        expect($template->is_active)->toBeFalse();
    });

    it('validates subject is required', function (): void {
        $admin = User::factory()->admin()->create();
        $template = EmailTemplate::factory()->create();

        $this->actingAs($admin)
            ->put($this->adminUrl.'/email-templates/'.$template->id, [
                'subject' => '',
                'body' => 'Some body',
                'is_active' => true,
            ])
            ->assertSessionHasErrors('subject');
    });

    it('validates body is required', function (): void {
        $admin = User::factory()->admin()->create();
        $template = EmailTemplate::factory()->create();

        $this->actingAs($admin)
            ->put($this->adminUrl.'/email-templates/'.$template->id, [
                'subject' => 'Some subject',
                'body' => '',
                'is_active' => true,
            ])
            ->assertSessionHasErrors('body');
    });

    it('denies non-admin from updating templates', function (): void {
        $customer = User::factory()->customer()->create();
        $template = EmailTemplate::factory()->create();

        $this->actingAs($customer)
            ->put($this->adminUrl.'/email-templates/'.$template->id, [
                'subject' => 'Hacked',
                'body' => 'Hacked body',
                'is_active' => true,
            ])
            ->assertForbidden();
    });
});

// ---------------------------------------------------------------------------
// Preview
// ---------------------------------------------------------------------------
describe('Email Template Preview', function (): void {
    it('allows admin to preview template with sample data', function (): void {
        $admin = User::factory()->admin()->create();
        $template = EmailTemplate::factory()->create([
            'slug' => 'payment-succeeded',
            'subject' => 'Payment of {{currency}} {{amount}} Received',
            'body' => 'Hello {{customer_name}}, your payment of {{currency}} {{amount}} was received.',
            'available_variables' => ['customer_name', 'amount', 'currency', 'invoice_number', 'date'],
        ]);

        $this->actingAs($admin)
            ->postJson($this->adminUrl.'/email-templates/'.$template->id.'/preview')
            ->assertOk()
            ->assertJsonStructure(['subject', 'body'])
            ->assertJsonFragment(['subject' => 'Payment of USD 49.99 Received']);
    });
});

// ---------------------------------------------------------------------------
// Reset to Default
// ---------------------------------------------------------------------------
describe('Email Template Reset', function (): void {
    it('allows admin to reset template to default', function (): void {
        $admin = User::factory()->admin()->create();

        // Seed the default template first
        $this->seed(EmailTemplateSeeder::class);

        $template = EmailTemplate::query()->where('slug', 'payment-succeeded')->first();
        $originalSubject = $template->subject;

        // Modify it
        $template->update(['subject' => 'Custom Subject', 'body' => 'Custom body']);

        $this->actingAs($admin)
            ->post($this->adminUrl.'/email-templates/'.$template->id.'/reset')
            ->assertRedirect();

        $template->refresh();
        expect($template->subject)->toBe($originalSubject);
    });
});

// ---------------------------------------------------------------------------
// Model
// ---------------------------------------------------------------------------
describe('EmailTemplate Model', function (): void {
    it('can get active template by slug', function (): void {
        $template = EmailTemplate::factory()->create([
            'slug' => 'test-template',
            'is_active' => true,
        ]);

        $found = EmailTemplate::getTemplate('test-template');
        expect($found)->not->toBeNull();
        expect($found->id)->toBe($template->id);
    });

    it('returns null for inactive template', function (): void {
        EmailTemplate::factory()->create([
            'slug' => 'inactive-template',
            'is_active' => false,
        ]);

        $found = EmailTemplate::getTemplate('inactive-template');
        expect($found)->toBeNull();
    });

    it('can render template with variables', function (): void {
        EmailTemplate::factory()->create([
            'slug' => 'render-test',
            'subject' => 'Hello {{customer_name}}',
            'body' => 'Your amount is {{amount}} {{currency}}.',
            'available_variables' => ['customer_name', 'amount', 'currency'],
            'is_active' => true,
        ]);

        $result = EmailTemplate::render('render-test', [
            'customer_name' => 'Jane',
            'amount' => '99.99',
            'currency' => 'USD',
        ]);

        expect($result)->not->toBeNull();
        expect($result['subject'])->toBe('Hello Jane');
        expect($result['body'])->toBe('Your amount is 99.99 USD.');
    });

    it('returns null when rendering non-existent template', function (): void {
        $result = EmailTemplate::render('non-existent', ['customer_name' => 'Test']);
        expect($result)->toBeNull();
    });
});
