<?php

namespace App\Livewire;

use Filament\Actions\Action;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Filament\Tables\TableComponent;
use Illuminate\Contracts\View\View;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Str;

class SettingsCatalogSettingsTable extends TableComponent
{
    /**
     * @var array<int, array<string, mixed>>
     */
    public array $settingsRows = [];

    public string $context = 'policy';

    /**
     * @param  array<int, array<string, mixed>>  $settingsRows
     */
    public function mount(array $settingsRows = [], string $context = 'policy'): void
    {
        $this->settingsRows = $settingsRows;
        $this->context = $context;
    }

    public function table(Table $table): Table
    {
        return $table
            ->queryStringIdentifier('settingsCatalog'.Str::studly($this->context))
            ->defaultSort('definition')
            ->records(function (?string $search, int|string $page, int|string $recordsPerPage, ?string $sortColumn, ?string $sortDirection): LengthAwarePaginator {
                $records = collect($this->settingsRows);

                if (filled($search)) {
                    $needle = Str::lower($search);

                    $records = $records->filter(function (array $row) use ($needle): bool {
                        $haystack = implode(' ', [
                            (string) ($row['definition'] ?? ''),
                            (string) ($row['category'] ?? ''),
                            (string) ($row['data_type'] ?? ''),
                            (string) ($row['value'] ?? ''),
                            (string) ($row['description'] ?? ''),
                            (string) ($row['path'] ?? ''),
                        ]);

                        return Str::contains(Str::lower($haystack), $needle);
                    });
                }

                if (filled($sortColumn)) {
                    $direction = Str::lower((string) ($sortDirection ?? 'asc')) === 'desc' ? 'desc' : 'asc';

                    $records = $records->sortBy(
                        fn (array $row) => (string) ($row[$sortColumn] ?? ''),
                        SORT_NATURAL | SORT_FLAG_CASE,
                        $direction === 'desc'
                    );
                }

                $perPage = is_numeric($recordsPerPage) ? max(1, (int) $recordsPerPage) : 25;
                $currentPage = is_numeric($page) ? max(1, (int) $page) : 1;

                $total = $records->count();
                $items = $records->forPage($currentPage, $perPage)->values();

                return new LengthAwarePaginator(
                    $items,
                    $total,
                    $perPage,
                    $currentPage
                );
            })
            ->paginated(\App\Support\Filament\TablePaginationProfiles::picker())
            ->defaultPaginationPageOption(25)
            ->searchable()
            ->searchPlaceholder('Search definition/value…')
            ->striped()
            ->deferLoading(! app()->runningUnitTests())
            ->columns([
                TextColumn::make('definition')
                    ->label('Definition')
                    ->limit(50)
                    ->tooltip(fn (?string $state): ?string => filled($state) ? $state : null)
                    ->searchable()
                    ->sortable()
                    ->wrap(),
                TextColumn::make('category')
                    ->label('Category')
                    ->limit(30)
                    ->tooltip(fn (?string $state): ?string => filled($state) ? $state : null)
                    ->searchable()
                    ->sortable()
                    ->toggleable()
                    ->wrap(),
                TextColumn::make('data_type')
                    ->label('Data Type')
                    ->badge()
                    ->color(fn (?string $state): string => match ($state) {
                        'Number' => 'info',
                        'Boolean' => 'success',
                        'Choice' => 'warning',
                        'Text' => 'gray',
                        default => 'gray',
                    })
                    ->searchable()
                    ->sortable()
                    ->toggleable(),
                TextColumn::make('value')
                    ->label('Value')
                    ->badge(fn (?string $state): bool => $state === '(group)')
                    ->color(fn (?string $state): string => $state === '(group)' ? 'gray' : 'primary')
                    ->limit(40)
                    ->tooltip(fn (?string $state): ?string => filled($state) ? $state : null)
                    ->searchable()
                    ->wrap(),
                TextColumn::make('description')
                    ->label('Description')
                    ->limit(60)
                    ->tooltip(fn (?string $state): ?string => filled($state) ? $state : null)
                    ->searchable()
                    ->toggleable(isToggledHiddenByDefault: true)
                    ->wrap(),
                TextColumn::make('path')
                    ->label('Path')
                    ->limit(80)
                    ->tooltip(fn (?string $state): ?string => filled($state) ? $state : null)
                    ->toggleable(isToggledHiddenByDefault: true)
                    ->extraAttributes(['class' => 'font-mono text-xs']),
            ])
            ->actions([
                Action::make('details')
                    ->label('Details')
                    ->icon('heroicon-m-eye')
                    ->slideOver()
                    ->modalSubmitAction(false)
                    ->modalCancelActionLabel('Close')
                    ->modalHeading(fn (array $record): string => (string) ($record['definition'] ?? 'Setting details'))
                    ->modalContent(fn (array $record): View => view('filament.modals.settings-catalog-setting-details', ['record' => $record])),
            ])
            ->emptyStateHeading('No settings match this view')
            ->emptyStateDescription('Clear the current search or reopen the source policy to inspect its catalog settings.');
    }

    public function render(): View
    {
        return view('livewire.settings-catalog-settings-table');
    }
}
