<?php

declare(strict_types=1);

namespace App\Support\Reports;

use App\Enums\ReportCategory;
use App\Services\ReportService;
use Closure;
use Illuminate\Database\Eloquent\Builder;

/**
 * The full shape of one report: what it's called, what filters it offers,
 * how to query it, and how to turn one result row into the plain array the
 * HTML table, the Excel export and the PDF export all render identically.
 *
 * `query` never sorts — {@see ReportService::run()} is the one
 * place that applies `sort`/`direction`, against the whitelist in
 * `sortable`, so every report is sorted the same way and a report can never
 * declare a sortable column that silently does nothing.
 */
final readonly class ReportDefinition
{
    /**
     * @param  list<ReportColumn>  $columns
     * @param  list<ReportFilter>  $filters
     * @param  Closure(array<string, mixed>): Builder<*>  $query
     * @param  Closure(mixed): array<string, mixed>  $row
     * @param  array<string, string>  $sortable  UI sort key => real column/expression
     */
    public function __construct(
        public string $key,
        public ReportCategory $category,
        public string $title,
        public string $description,
        public string $icon,
        public array $columns,
        public array $filters,
        public Closure $query,
        public Closure $row,
        public array $sortable,
        public string $defaultSort,
        public string $defaultDirection = 'asc',
        public string $emptyTitle = 'No records match these filters',
        public string $emptyMessage = 'Try widening the date range or clearing a filter.',
    ) {}

    public function hasFilterType(ReportFilterType $type): bool
    {
        foreach ($this->filters as $filter) {
            if ($filter->type === $type) {
                return true;
            }
        }

        return false;
    }
}
