<?php

namespace App\Notifications;

use App\Filament\Resources\BulkOperationRunResource;
use App\Filament\Resources\EntraGroupSyncRunResource;
use App\Filament\Resources\RestoreRunResource;
use App\Models\Tenant;
use Filament\Actions\Action;
use Illuminate\Notifications\Notification;

class RunStatusChangedNotification extends Notification
{
    /**
     * @param  array{
     *   tenant_id:int,
     *   run_type:string,
     *   run_id:int,
     *   status:string,
     *   counts?:array{total?:int, processed?:int, succeeded?:int, failed?:int, skipped?:int}
     * }  $metadata
     */
    public function __construct(public array $metadata) {}

    /**
     * @return array<int, string>
     */
    public function via(object $notifiable): array
    {
        return ['database'];
    }

    /**
     * @return array<string, mixed>
     */
    public function toDatabase(object $notifiable): array
    {
        $status = (string) ($this->metadata['status'] ?? 'queued');
        $runType = (string) ($this->metadata['run_type'] ?? 'run');
        $tenantId = (int) ($this->metadata['tenant_id'] ?? 0);
        $runId = (int) ($this->metadata['run_id'] ?? 0);

        $title = match ($status) {
            'queued' => 'Run queued',
            'running' => 'Run started',
            'completed', 'succeeded' => 'Run completed',
            'partial', 'partially succeeded', 'completed_with_errors' => 'Run completed (partial)',
            'failed' => 'Run failed',
            default => 'Run updated',
        };

        $body = sprintf('A %s run changed status to: %s.', str_replace('_', ' ', $runType), $status);

        $color = match ($status) {
            'queued', 'running' => 'gray',
            'completed', 'succeeded' => 'success',
            'partial', 'partially succeeded', 'completed_with_errors' => 'warning',
            'failed' => 'danger',
            default => 'gray',
        };

        $actions = [];

        if (in_array($runType, ['bulk_operation', 'restore', 'directory_groups'], true) && $tenantId > 0 && $runId > 0) {
            $tenant = Tenant::query()->find($tenantId);

            if ($tenant) {
                $url = match ($runType) {
                    'bulk_operation' => BulkOperationRunResource::getUrl('view', ['record' => $runId], tenant: $tenant),
                    'restore' => RestoreRunResource::getUrl('view', ['record' => $runId], tenant: $tenant),
                    'directory_groups' => EntraGroupSyncRunResource::getUrl('view', ['record' => $runId], tenant: $tenant),
                    default => null,
                };

                if (! $url) {
                    return [
                        'format' => 'filament',
                        'title' => $title,
                        'body' => $body,
                        'color' => $color,
                        'duration' => 'persistent',
                        'actions' => [],
                        'icon' => null,
                        'iconColor' => null,
                        'status' => null,
                        'view' => null,
                        'viewData' => [
                            'metadata' => $this->metadata,
                        ],
                    ];
                }

                $actions[] = Action::make('view_run')
                    ->label('View run')
                    ->url($url)
                    ->toArray();
            }
        }

        return [
            'format' => 'filament',
            'title' => $title,
            'body' => $body,
            'color' => $color,
            'duration' => 'persistent',
            'actions' => $actions,
            'icon' => null,
            'iconColor' => null,
            'status' => null,
            'view' => null,
            'viewData' => [
                'metadata' => $this->metadata,
            ],
        ];
    }
}
