<?php

declare(strict_types=1);

namespace App\Filament\Resources\DberpDataImportBatches;

use App\Business\DataImport\DataImportBatchDeletionService;
use App\Business\DataImport\Enums\DataImportBatchStatus;
use App\Business\DataImport\Enums\DataImportType;
use App\Filament\Concerns\InteractsWithDberpPermissions;
use App\Filament\Pages\DataInitializationImportPage;
use App\Models\DberpDataImportBatch;
use App\Models\DberpDataImportBatchRow;
use App\Services\DberpPermissionService;
use Filament\Actions\DeleteAction;
use Filament\Actions\ViewAction;
use Filament\Infolists\Components\TextEntry;
use Filament\Resources\Resource;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Schema;
use Filament\Support\Enums\Width;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Model;

class DberpDataImportBatchResource extends Resource
{
    use InteractsWithDberpPermissions;

    protected static ?string $model = DberpDataImportBatch::class;

    protected static ?string $recordTitleAttribute = 'batch_no';

    protected static ?int $navigationSort = 31;

    protected static bool $shouldRegisterNavigation = false;

    public static function form(Schema $schema): Schema
    {
        return $schema->components([]);
    }

    public static function infolist(Schema $schema): Schema
    {
        return $schema->components([
            Section::make(__('dberp.data_import.sections.batch_summary'))
                ->schema([
                    TextEntry::make('batch_no')
                        ->label(__('dberp.fields.import_batch_no')),
                    TextEntry::make('import_type')
                        ->label(__('dberp.fields.import_type'))
                        ->formatStateUsing(fn ($state): string => $state?->label() ?? '-'),
                    TextEntry::make('status')
                        ->label(__('dberp.fields.status'))
                        ->badge()
                        ->formatStateUsing(fn ($state): string => $state?->label() ?? '-'),
                    TextEntry::make('source_filename')
                        ->label(__('dberp.fields.source_filename'))
                        ->placeholder('-'),
                    TextEntry::make('operator.name')
                        ->label(__('dberp.fields.operator'))
                        ->placeholder(__('dberp.data_import.values.system_operator')),
                    TextEntry::make('started_at')
                        ->label(__('dberp.fields.started_at'))
                        ->dateTime()
                        ->placeholder('-'),
                    TextEntry::make('finished_at')
                        ->label(__('dberp.fields.finished_at'))
                        ->dateTime()
                        ->placeholder('-'),
                    TextEntry::make('total_rows')
                        ->label(__('dberp.fields.total_rows')),
                    TextEntry::make('success_rows')
                        ->label(__('dberp.fields.success_rows')),
                    TextEntry::make('failed_rows')
                        ->label(__('dberp.fields.failed_rows')),
                    TextEntry::make('correlation_id')
                        ->label(__('dberp.fields.correlation_id'))
                        ->helperText(__('dberp.data_import.correlation_id_hint'))
                        ->placeholder('-')
                        ->copyable(),
                    TextEntry::make('error_summary')
                        ->label(__('dberp.fields.error_summary'))
                        ->formatStateUsing(function (?array $state): string {
                            $messages = is_array($state['messages'] ?? null) ? $state['messages'] : [];

                            if ($messages === []) {
                                return '-';
                            }

                            return implode("\n", $messages);
                        })
                        ->placeholder('-')
                        ->columnSpanFull(),
                    TextEntry::make('remark')
                        ->label(__('dberp.fields.remark'))
                        ->placeholder('-')
                        ->columnSpanFull(),
                ])
                ->columns(2),
            Section::make(__('dberp.data_import.batch_rows.section_heading'))
                ->schema([
                    TextEntry::make('rows_summary')
                        ->hiddenLabel()
                        ->columnSpanFull()
                        ->placeholder('-')
                        ->listWithLineBreaks()
                        ->state(fn (DberpDataImportBatch $record): array => self::batchRowSummaryLines($record)),
                ]),
        ]);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->defaultSort('created_at', 'desc')
            ->columns([
                TextColumn::make('batch_no')
                    ->label(__('dberp.fields.import_batch_no'))
                    ->searchable()
                    ->sortable(),
                TextColumn::make('import_type')
                    ->label(__('dberp.fields.import_type'))
                    ->badge()
                    ->formatStateUsing(fn ($state): string => $state?->label() ?? '-')
                    ->sortable(),
                TextColumn::make('status')
                    ->label(__('dberp.fields.status'))
                    ->badge()
                    ->formatStateUsing(fn ($state): string => $state?->label() ?? '-')
                    ->sortable(),
                TextColumn::make('source_filename')
                    ->label(__('dberp.fields.source_filename'))
                    ->placeholder('-')
                    ->toggleable(),
                TextColumn::make('operator.name')
                    ->label(__('dberp.fields.operator'))
                    ->placeholder(__('dberp.data_import.values.system_operator')),
                TextColumn::make('total_rows')
                    ->label(__('dberp.fields.total_rows'))
                    ->alignEnd()
                    ->sortable(),
                TextColumn::make('success_rows')
                    ->label(__('dberp.fields.success_rows'))
                    ->alignEnd()
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('failed_rows')
                    ->label(__('dberp.fields.failed_rows'))
                    ->alignEnd()
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('started_at')
                    ->label(__('dberp.fields.started_at'))
                    ->dateTime()
                    ->sortable()
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('finished_at')
                    ->label(__('dberp.fields.finished_at'))
                    ->dateTime()
                    ->sortable()
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('created_at')
                    ->label(__('dberp.fields.created_at'))
                    ->dateTime()
                    ->sortable(),
            ])
            ->filters([
                SelectFilter::make('import_type')
                    ->label(__('dberp.fields.import_type'))
                    ->options(DataImportType::supportedOptions()),
                SelectFilter::make('status')
                    ->label(__('dberp.fields.status'))
                    ->options(DataImportBatchStatus::options()),
            ])
            ->emptyStateHeading(__('dberp.data_import.empty_state.heading'))
            ->emptyStateDescription(__('dberp.data_import.empty_state.description'))
            ->recordActions([
                ViewAction::make()
                    ->modalWidth(Width::SevenExtraLarge),
                DeleteAction::make()
                    ->label(__('dberp.data_import.actions.delete_batch'))
                    ->modalHeading(__('dberp.data_import.delete_batch_confirm_heading'))
                    ->modalDescription(fn (DberpDataImportBatch $record): string => self::deleteBatchConfirmationMessage($record))
                    ->visible(fn (DberpDataImportBatch $record): bool => static::canDelete($record))
                    ->authorize(fn (DberpDataImportBatch $record): bool => static::canDelete($record))
                    ->using(function (DberpDataImportBatch $record): bool {
                        app(DataImportBatchDeletionService::class)->delete($record);

                        return true;
                    })
                    ->after(function (DberpDataImportBatch $record, mixed $livewire): void {
                        if ($livewire instanceof DataInitializationImportPage) {
                            $livewire->handleImportBatchDeleted((int) $record->getKey());
                        }
                    }),
            ])
            ->recordUrl(null);
    }

    public static function getRelations(): array
    {
        return [];
    }

    public static function getPages(): array
    {
        return [];
    }

    /**
     * @return list<string>
     */
    public static function batchRowSummaryLines(DberpDataImportBatch $record): array
    {
        $record->loadMissing([
            'rows' => static fn ($query) => $query->orderBy('row_number'),
        ]);

        if ($record->rows->isEmpty()) {
            return [];
        }

        return $record->rows
            ->map(static function (DberpDataImportBatchRow $row): string {
                $line = (string) __('dberp.data_import.batch_row_summary_line', [
                    'row' => (int) $row->row_number,
                    'status' => $row->status->label(),
                ]);

                if (is_array($row->error_messages) && $row->error_messages !== []) {
                    $line .= '：'.implode('；', array_map(strval(...), $row->error_messages));
                }

                return $line;
            })
            ->all();
    }

    public static function canViewAny(): bool
    {
        return static::allowsPermission(DberpPermissionService::VIEW_DATA_IMPORT_BATCH);
    }

    public static function canCreate(): bool
    {
        return false;
    }

    public static function canEdit(Model $record): bool
    {
        return false;
    }

    public static function canDelete(Model $record): bool
    {
        if (! $record instanceof DberpDataImportBatch) {
            return false;
        }

        if (! static::allowsPermission(DberpPermissionService::DELETE_DATA_IMPORT_BATCH)) {
            return false;
        }

        return app(DataImportBatchDeletionService::class)->canDelete($record);
    }

    public static function deleteBatchConfirmationMessage(DberpDataImportBatch $record): string
    {
        if ($record->status === DataImportBatchStatus::Completed) {
            return (string) __('dberp.data_import.delete_batch_confirm_body_completed');
        }

        return (string) __('dberp.data_import.delete_batch_confirm_body');
    }

    public static function getModelLabel(): string
    {
        return __('dberp.resources.data_import_batch.label');
    }

    public static function getPluralModelLabel(): string
    {
        return __('dberp.resources.data_import_batch.plural');
    }
}
