<?php

namespace Tests\Feature;

use App\Models\NotificationLog;
use Carbon\Carbon;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Mail;
use Tests\Feature\Concerns\BuildsFeatureData;
use Tests\TestCase;

class AdminNotificationsFeatureTest extends TestCase
{
    use BuildsFeatureData;
    use DatabaseTransactions;

    private function loginAsAdmin(): void
    {
        $this->actingAs($this->createAdminUser());
    }

    public function test_admin_can_open_notification_log_and_queue_pages(): void
    {
        $this->loginAsAdmin();

        $applicant = $this->createApplicant();
        $job = $this->createJob();
        $application = $this->createJobApplication($applicant, $job);
        $this->createNotificationLog($application);

        $this->get(route('admin.notifications'))->assertOk();
        $this->get(route('admin.notifications.queue'))->assertOk();
    }

    public function test_admin_can_cancel_scheduled_notification(): void
    {
        $this->loginAsAdmin();

        $applicant = $this->createApplicant();
        $job = $this->createJob();
        $application = $this->createJobApplication($applicant, $job);
        $notification = $this->createNotificationLog($application, [
            'status' => 'scheduled',
        ]);

        $response = $this->post(route('admin.notifications.cancel', $notification));

        $response->assertStatus(302);
        $this->assertDatabaseHas('notification_logs', [
            'id' => $notification->id,
            'status' => 'cancelled',
        ]);
    }

    public function test_admin_can_reschedule_scheduled_notification(): void
    {
        $this->loginAsAdmin();

        $applicant = $this->createApplicant();
        $job = $this->createJob();
        $application = $this->createJobApplication($applicant, $job);
        $notification = $this->createNotificationLog($application, [
            'status' => 'scheduled',
            'scheduled_at' => now()->addHour(),
        ]);

        $newSchedule = Carbon::now()->addHours(2)->startOfMinute();

        $response = $this->post(route('admin.notifications.reschedule', $notification), [
            'scheduled_at' => $newSchedule->toDateTimeString(),
        ]);

        $response->assertStatus(302);

        $notification->refresh();
        $this->assertSame($newSchedule->toDateTimeString(), $notification->scheduled_at?->toDateTimeString());
    }

    public function test_send_now_processes_notification_and_advances_application_status(): void
    {
        Mail::fake();
        $this->loginAsAdmin();

        $applicant = $this->createApplicant();
        $job = $this->createJob();
        $application = $this->createJobApplication($applicant, $job, [
            'status' => 'applied',
            'current_stage' => 0,
        ]);

        $notification = $this->createNotificationLog($application, [
            'type' => 'stage1_passed',
            'channel' => 'email',
            'status' => 'scheduled',
            'scheduled_at' => now()->subMinutes(1),
            'subject' => 'Lolos Tahap 1',
            'message' => 'Selamat, Anda lolos tahap 1.',
        ]);

        $response = $this->post(route('admin.notifications.send-now', $notification));

        $response->assertStatus(302);

        $notification->refresh();
        $application->refresh();

        $this->assertSame('sent', $notification->status);
        $this->assertSame('stage1_passed', $application->status);
        $this->assertSame(1, $application->current_stage);
    }

    public function test_admin_can_cancel_all_scheduled_notifications(): void
    {
        $this->loginAsAdmin();

        $applicant = $this->createApplicant();
        $job = $this->createJob();
        $application = $this->createJobApplication($applicant, $job);

        $this->createNotificationLog($application, [
            'status' => 'scheduled',
            'type' => 'stage1_passed',
        ]);
        $this->createNotificationLog($application, [
            'status' => 'scheduled',
            'type' => 'stage2_passed',
        ]);

        $response = $this->post(route('admin.notifications.cancel-all'));

        $response->assertStatus(302);
        $this->assertSame(0, NotificationLog::where('status', 'scheduled')->count());
        $this->assertGreaterThanOrEqual(2, NotificationLog::where('status', 'cancelled')->count());
    }

    public function test_send_all_due_returns_success_when_nothing_is_due(): void
    {
        $this->loginAsAdmin();

        $response = $this->post(route('admin.notifications.send-all-due'));

        $response->assertStatus(302);
        $response->assertSessionHas('success');
    }
}
