<?php

namespace App\Filament\Support;

use Closure;
use Filament\Widgets\StatsOverviewWidget\Stat;
use Illuminate\Support\HtmlString;

/**
 * The KPI stat factory, carrying the patterns of the Inertia app's summary
 * cards into Filament: an icon, a tone, and — the part the Inertia app had and
 * the port lost — a threshold that flips the whole card to danger. "Outstanding
 * Balance" should read red the moment there IS an outstanding balance, and
 * nothing else; "Avg. payment delay" turns red only past 30 days.
 *
 *   Kpi::money('Outstanding balance', $outstanding)
 *       ->icon(Heroicon::OutlinedAlertCircle)
 *       ->alertWhen(fn (): bool => $outstanding > 0)
 *       ->toStat();
 */
class Kpi
{
    private Stat $stat;

    private string $tone = 'primary';

    private ?Closure $alertWhen = null;

    public function __construct(Stat $stat)
    {
        $this->stat = $stat;
    }

    public static function money(string $label, float $value): self
    {
        return new self(Stat::make($label, 'Rs. '.number_format($value, 2)));
    }

    public static function count(string $label, float|int $value): self
    {
        return new self(Stat::make($label, number_format((float) $value)));
    }

    /**
     * @param  class-string|\BackedEnum|string|null  $icon
     */
    public function icon(string|\BackedEnum|null $icon): self
    {
        $this->stat->icon($icon);

        return $this;
    }

    public function tone(string $tone): self
    {
        $this->tone = $tone;
        $this->stat->color($tone);

        return $this;
    }

    /**
     * The card flips to danger when the business threshold is crossed — the
     * Inertia "highlight-on-threshold" idea (Outstanding Balance turns red only
     * when there is an outstanding balance; Avg Payment Delay turns red past
     * 30 days). The predicate is evaluated at render time, so a reload with
     * new data re-colours the card without any extra wiring.
     */
    public function alertWhen(Closure $predicate): self
    {
        $this->alertWhen = $predicate;

        $this->stat->color(fn (): string => ($predicate)() ? 'danger' : $this->tone);

        return $this;
    }

    public function description(string|HtmlString|null $description): self
    {
        $this->stat->description($description);

        return $this;
    }

    /**
     * @param  class-string|\BackedEnum|string|null  $icon
     */
    public function descriptionIcon(string|\BackedEnum|null $icon): self
    {
        $this->stat->descriptionIcon($icon);

        return $this;
    }

    public function extraAttributes(array $attributes): self
    {
        $this->stat->extraAttributes($attributes);

        return $this;
    }

    public function toStat(): Stat
    {
        return $this->stat;
    }
}
