<?php

declare(strict_types=1);

namespace App\Support\OpsUx;

use App\Models\OperationRun;
use App\Models\Tenant;
use App\Support\OperationCatalog;
use Filament\Notifications\Notification as FilamentNotification;
use Illuminate\Support\Str;

final class OperationUxPresenter
{
    public const int QUEUED_TOAST_DURATION_MS = 4000;

    public const int FAILURE_MESSAGE_MAX_CHARS = 140;

    /**
     * Queued intent feedback toast (ephemeral, not persisted).
     */
    public static function queuedToast(string $operationType): FilamentNotification
    {
        $operationLabel = OperationCatalog::label($operationType);

        return FilamentNotification::make()
            ->title("{$operationLabel} queued")
            ->body('Running in the background.')
            ->warning()
            ->duration(self::QUEUED_TOAST_DURATION_MS);
    }

    /**
     * Terminal DB notification payload.
     *
     * Note: We intentionally return the built Filament notification builder to
     * keep DB formatting consistent with existing Notification classes.
     */
    public static function terminalDatabaseNotification(OperationRun $run, ?Tenant $tenant = null): FilamentNotification
    {
        $operationLabel = OperationCatalog::label((string) $run->type);

        $uxStatus = OperationStatusNormalizer::toUxStatus($run->status, $run->outcome);

        $titleSuffix = match ($uxStatus) {
            'succeeded' => 'completed',
            'partial' => 'completed with warnings',
            default => 'failed',
        };

        $body = match ($uxStatus) {
            'succeeded' => 'Completed successfully.',
            'partial' => 'Completed with warnings.',
            default => 'Failed.',
        };

        if ($uxStatus === 'failed') {
            $failureMessage = (string) (($run->failure_summary[0]['message'] ?? '') ?? '');

            $failureMessage = self::sanitizeFailureMessage($failureMessage);

            if ($failureMessage !== null) {
                $body = $body.' '.$failureMessage;
            }
        }

        $summary = SummaryCountsNormalizer::renderSummaryLine(is_array($run->summary_counts) ? $run->summary_counts : []);
        if ($summary !== null) {
            $body = $body."\n".$summary;
        }

        $status = match ($uxStatus) {
            'succeeded' => 'success',
            'partial' => 'warning',
            default => 'danger',
        };

        $notification = FilamentNotification::make()
            ->title("{$operationLabel} {$titleSuffix}")
            ->body($body)
            ->status($status);

        if ($tenant instanceof Tenant) {
            $notification->actions([
                \Filament\Actions\Action::make('view')
                    ->label('View run')
                    ->url(OperationRunUrl::view($run, $tenant)),
            ]);
        }

        return $notification;
    }

    private static function sanitizeFailureMessage(string $failureMessage): ?string
    {
        $failureMessage = trim($failureMessage);

        if ($failureMessage === '') {
            return null;
        }

        $failureMessage = Str::of($failureMessage)
            ->replace(["\r", "\n"], ' ')
            ->squish()
            ->toString();

        $failureMessage = Str::limit($failureMessage, self::FAILURE_MESSAGE_MAX_CHARS, '…');

        return $failureMessage !== '' ? $failureMessage : null;
    }
}
