<?php

use App\Livewire\Studio\Information\Broadcast;
use App\Models\Broadcast as BroadcastModel;
use Illuminate\Support\Facades\Queue;
use Livewire\Livewire;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;

beforeEach(function () {
    $this->setupUser();

    $role = Role::firstOrCreate(['name' => 'Owner']);
    Permission::firstOrCreate(['name' => 'view broadcast']);
    Permission::firstOrCreate(['name' => 'create broadcast']);
    Permission::firstOrCreate(['name' => 'delete broadcast']);
    $role->givePermissionTo(['view broadcast', 'create broadcast', 'delete broadcast']);
    $this->user->assignRole($role);

    // Create additional roles for testing
    $this->customerRole = Role::firstOrCreate(['name' => 'Customer']);
    $this->employeeRole = Role::firstOrCreate(['name' => 'Employee']);
    $this->developerRole = Role::firstOrCreate(['name' => 'Developer']);
});

it('renders the broadcast page correctly', function () {
    $this->actingAs($this->user)
        ->get(route('studio.information.broadcast.index'))
        ->assertOk()
        ->assertSeeLivewire(Broadcast::class);
});

it('can open create modal', function () {
    Livewire::actingAs($this->user)
        ->test(Broadcast::class)
        ->dispatch('modal:open', method: 'create', modalTitle: 'Tambah Broadcast')
        ->assertSet('method', 'create')
        ->assertSet('modalTitle', 'Tambah Broadcast');
});

it('validates required fields on create', function () {
    Livewire::actingAs($this->user)
        ->test(Broadcast::class)
        ->call('create')
        ->assertHasErrors([
            'form.title' => 'required',
            'form.body' => 'required',
            'form.role_ids' => 'required',
        ]);
});

it('validates title max length', function () {
    Livewire::actingAs($this->user)
        ->test(Broadcast::class)
        ->set('form.title', str_repeat('a', 31))
        ->set('form.body', 'Test Body')
        ->set('form.role_ids', [$this->customerRole->id])
        ->call('create')
        ->assertHasErrors(['form.title' => 'max']);
});

it('validates body max length', function () {
    Livewire::actingAs($this->user)
        ->test(Broadcast::class)
        ->set('form.title', 'Test Title')
        ->set('form.body', str_repeat('a', 51))
        ->set('form.role_ids', [$this->customerRole->id])
        ->call('create')
        ->assertHasErrors(['form.body' => 'max']);
});

it('validates link must be valid url', function () {
    Livewire::actingAs($this->user)
        ->test(Broadcast::class)
        ->set('form.title', 'Test Title')
        ->set('form.body', 'Test Body')
        ->set('form.link', 'not-a-valid-url')
        ->set('form.role_ids', [$this->customerRole->id])
        ->call('create')
        ->assertHasErrors(['form.link' => 'url']);
});

it('validates role_ids must be array with at least one item', function () {
    Livewire::actingAs($this->user)
        ->test(Broadcast::class)
        ->set('form.title', 'Test Title')
        ->set('form.body', 'Test Body')
        ->set('form.role_ids', [])
        ->call('create')
        ->assertHasErrors(['form.role_ids' => 'required']);
});

it('can store a new broadcast', function () {
    Queue::fake();

    Livewire::actingAs($this->user)
        ->test(Broadcast::class)
        ->set('form.title', 'Broadcast Baru')
        ->set('form.body', 'Ini adalah broadcast baru')
        ->set('form.link', 'https://example.com')
        ->set('form.role_ids', [$this->customerRole->id])
        ->call('create')
        ->assertHasNoErrors()
        ->assertDispatched('refreshDatatable');

    $this->assertDatabaseHas('broadcasts', [
        'user_id' => $this->user->id,
        'title' => 'Broadcast Baru',
        'body' => 'Ini adalah broadcast baru',
        'link' => 'https://example.com',
    ]);

    $broadcast = BroadcastModel::where('title', 'Broadcast Baru')->first();
    $this->assertDatabaseHas('broadcast_audiences', [
        'broadcast_id' => $broadcast->id,
        'audience_id' => $this->customerRole->id,
    ]);
});

it('can store broadcast without link', function () {
    Queue::fake();

    Livewire::actingAs($this->user)
        ->test(Broadcast::class)
        ->set('form.title', 'Broadcast Tanpa Link')
        ->set('form.body', 'Broadcast ini tidak memiliki link')
        ->set('form.role_ids', [$this->employeeRole->id])
        ->call('create')
        ->assertHasNoErrors()
        ->assertDispatched('refreshDatatable');

    $this->assertDatabaseHas('broadcasts', [
        'title' => 'Broadcast Tanpa Link',
        'body' => 'Broadcast ini tidak memiliki link',
        'link' => null,
    ]);
});

it('can store broadcast with multiple audiences', function () {
    Queue::fake();

    Livewire::actingAs($this->user)
        ->test(Broadcast::class)
        ->set('form.title', 'Multi Audience')
        ->set('form.body', 'Broadcast untuk banyak role')
        ->set('form.role_ids', [$this->customerRole->id, $this->employeeRole->id])
        ->call('create')
        ->assertHasNoErrors()
        ->assertDispatched('refreshDatatable');

    $broadcast = BroadcastModel::where('title', 'Multi Audience')->first();
    expect($broadcast->audiences)->toHaveCount(2);
});

it('can delete a broadcast', function () {
    $broadcast = BroadcastModel::factory()->create([
        'user_id' => $this->user->id,
    ]);

    Livewire::actingAs($this->user)
        ->test(Broadcast::class)
        ->call('delete', $broadcast)
        ->assertDispatched('refreshDatatable');

    $this->assertDatabaseMissing('broadcasts', ['id' => $broadcast->id]);
});

it('cannot access broadcast page without permission', function () {
    $this->user->roles()->detach();
    $this->user->permissions()->detach();

    $this->actingAs($this->user)
        ->get(route('studio.information.broadcast.index'))
        ->assertForbidden();
});

it('cannot create broadcast without permission', function () {
    $this->user->roles()->detach();
    $this->user->permissions()->detach();

    Livewire::actingAs($this->user)
        ->test(Broadcast::class)
        ->set('form.title', 'Test')
        ->set('form.body', 'Test')
        ->set('form.role_ids', [$this->customerRole->id])
        ->call('create')
        ->assertForbidden();
});

it('cannot delete broadcast without permission', function () {
    $broadcast = BroadcastModel::factory()->create();

    $this->user->roles()->detach();
    $this->user->permissions()->detach();

    Livewire::actingAs($this->user)
        ->test(Broadcast::class)
        ->call('delete', $broadcast)
        ->assertForbidden();
});
