<?php

namespace App\Jobs;

use App\Models\BulkOperationRun;
use App\Models\Policy;
use App\Services\BulkOperationService;
use Filament\Notifications\Notification;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Throwable;

class BulkPolicyUnignoreJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct(public int $bulkRunId) {}

    public function handle(BulkOperationService $service): void
    {
        $run = BulkOperationRun::with('user')->find($this->bulkRunId);

        if (! $run || $run->status !== 'pending') {
            return;
        }

        $service->start($run);

        try {
            $itemCount = 0;
            $succeeded = 0;
            $failed = 0;
            $skipped = 0;

            $chunkSize = max(1, (int) config('tenantpilot.bulk_operations.chunk_size', 10));

            foreach ($run->item_ids as $policyId) {
                $itemCount++;

                try {
                    $policy = Policy::find($policyId);

                    if (! $policy) {
                        $service->recordFailure($run, (string) $policyId, 'Policy not found');
                        $failed++;

                        continue;
                    }

                    if (! $policy->ignored_at) {
                        $service->recordSkipped($run);
                        $skipped++;

                        continue;
                    }

                    $policy->unignore();

                    $service->recordSuccess($run);
                    $succeeded++;
                } catch (Throwable $e) {
                    $service->recordFailure($run, (string) $policyId, $e->getMessage());
                    $failed++;
                }

                if ($itemCount % $chunkSize === 0) {
                    $run->refresh();
                }
            }

            $service->complete($run);

            if ($run->user) {
                $message = "Restored {$succeeded} policies";

                if ($skipped > 0) {
                    $message .= " ({$skipped} skipped)";
                }

                if ($failed > 0) {
                    $message .= " ({$failed} failed)";
                }

                $message .= '.';

                Notification::make()
                    ->title('Bulk Restore Completed')
                    ->body($message)
                    ->icon('heroicon-o-check-circle')
                    ->success()
                    ->sendToDatabase($run->user)
                    ->send();
            }
        } catch (Throwable $e) {
            $service->fail($run, $e->getMessage());

            $run->refresh();
            $run->load('user');

            if ($run->user) {
                Notification::make()
                    ->title('Bulk Restore Failed')
                    ->body($e->getMessage())
                    ->icon('heroicon-o-x-circle')
                    ->danger()
                    ->sendToDatabase($run->user)
                    ->send();
            }

            throw $e;
        }
    }
}
