<?php

declare(strict_types=1);

namespace App\Support\Filament;

use Carbon\CarbonImmutable;
use Filament\Forms\Components\DatePicker;
use Filament\Tables\Filters\Filter;
use Filament\Tables\Filters\TrashedFilter;
use Illuminate\Database\Eloquent\Builder;
use Throwable;

final class FilterPresets
{
    public static function archived(): TrashedFilter
    {
        return TrashedFilter::make()
            ->label('Archived')
            ->placeholder('Active')
            ->trueLabel('All')
            ->falseLabel('Archived');
    }

    /**
     * @param  array<string, mixed>|null  $default
     */
    public static function dateRange(string $name, string $label, string $column, ?array $default = null): Filter
    {
        $filter = Filter::make($name)
            ->label($label)
            ->schema([
                DatePicker::make('from')
                    ->label('From'),
                DatePicker::make('until')
                    ->label('Until'),
            ])
            ->query(function (Builder $query, array $data) use ($column): Builder {
                $from = $data['from'] ?? null;
                if ($from) {
                    $query->whereDate($column, '>=', $from);
                }

                $until = $data['until'] ?? null;
                if ($until) {
                    $query->whereDate($column, '<=', $until);
                }

                return $query;
            })
            ->indicateUsing(function (array $data) use ($label): ?array {
                $indicators = [];
                $from = self::formatIndicatorDate($data['from'] ?? null);
                $until = self::formatIndicatorDate($data['until'] ?? null);

                if ($from !== null) {
                    $indicators[] = "{$label} from {$from}";
                }

                if ($until !== null) {
                    $indicators[] = "{$label} until {$until}";
                }

                return $indicators === [] ? null : $indicators;
            });

        if ($default !== null) {
            $filter = $filter->default($default);
        }

        return $filter;
    }

    private static function formatIndicatorDate(mixed $value): ?string
    {
        if (! is_string($value) || trim($value) === '') {
            return null;
        }

        try {
            return CarbonImmutable::parse($value)->toFormattedDateString();
        } catch (Throwable) {
            return null;
        }
    }
}
