<?php

namespace App\Filament\Resources\ModerationCases\Tables;

use App\Enums\ModerationCaseStatus;
use App\Enums\ReportStatus;
use App\Models\MealPosts;
use App\Models\ModerationCase;
use App\Models\PostReviews;
use App\Models\User;
use Filament\Actions\Action;
use Filament\Actions\EditAction;
use Filament\Actions\ViewAction;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;

class ModerationCasesTable
{
    public static function configure(Table $table): Table
    {
        return $table
            ->columns([
                TextColumn::make('id')
                    ->label(__('admin.moderation_cases.fields.id'))
                    ->copyable()
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('target_type')
                    ->label(__('admin.moderation_cases.fields.target_type'))
                    ->state(fn (ModerationCase $record): string => $record->targetLabel())
                    ->badge(),
                TextColumn::make('target_title')
                    ->label(__('admin.moderation_cases.fields.target_title'))
                    ->state(fn (ModerationCase $record): string => $record->targetTitle())
                    ->searchable(query: function (Builder $query, string $search): Builder {
                        return $query->where(function (Builder $query) use ($search): void {
                            $query
                                ->whereHasMorph('caseable', [MealPosts::class], fn (Builder $query): Builder => $query->where('title', 'like', "%{$search}%"))
                                ->orWhereHasMorph('caseable', [PostReviews::class], fn (Builder $query): Builder => $query->where('comment', 'like', "%{$search}%"))
                                ->orWhereHasMorph('caseable', [User::class], fn (Builder $query): Builder => $query->where('name', 'like', "%{$search}%"));
                        });
                    }),
                TextColumn::make('status')
                    ->label(__('admin.moderation_cases.fields.status'))
                    ->badge()
                    ->sortable(),
                TextColumn::make('reports_count')
                    ->label(__('admin.moderation_cases.fields.reports_count'))
                    ->numeric()
                    ->sortable(),
                TextColumn::make('threshold')
                    ->label(__('admin.moderation_cases.fields.threshold'))
                    ->numeric()
                    ->sortable()
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('threshold_notified_at')
                    ->label(__('admin.moderation_cases.fields.threshold_notified_at'))
                    ->dateTime()
                    ->sortable()
                    ->placeholder(__('admin.moderation_cases.placeholders.empty')),
                TextColumn::make('assignedTo.name')
                    ->label(__('admin.moderation_cases.fields.assigned_to'))
                    ->placeholder(__('admin.moderation_cases.placeholders.empty'))
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('resolved_at')
                    ->label(__('admin.moderation_cases.fields.resolved_at'))
                    ->dateTime()
                    ->sortable()
                    ->placeholder(__('admin.moderation_cases.placeholders.empty')),
                TextColumn::make('created_at')
                    ->label(__('admin.moderation_cases.fields.created_at'))
                    ->dateTime()
                    ->sortable()
                    ->toggleable(isToggledHiddenByDefault: true),
            ])
            ->filters([
                SelectFilter::make('status')
                    ->label(__('admin.moderation_cases.fields.status'))
                    ->options(ModerationCaseStatus::class),
                SelectFilter::make('caseable_type')
                    ->label(__('admin.moderation_cases.filters.target_type'))
                    ->options([
                        MealPosts::class => __('admin.moderation_cases.targets.meal_post'),
                        PostReviews::class => __('admin.moderation_cases.targets.post_review'),
                        User::class => __('admin.moderation_cases.targets.user'),
                    ]),
            ])
            ->recordActions([
                ViewAction::make(),
                EditAction::make(),
                Action::make('markReviewing')
                    ->label(__('admin.moderation_cases.actions.mark_reviewing'))
                    ->visible(fn (ModerationCase $record): bool => $record->status !== ModerationCaseStatus::REVIEWING)
                    ->action(fn (ModerationCase $record): bool => self::markReviewing($record)),
                Action::make('hideMeal')
                    ->label(__('admin.moderation_cases.actions.hide_meal'))
                    ->color('warning')
                    ->requiresConfirmation()
                    ->visible(fn (ModerationCase $record): bool => $record->caseable_type === MealPosts::class
                        && $record->caseable instanceof MealPosts
                        && ! $record->caseable->isHidden())
                    ->action(fn (ModerationCase $record): bool => self::hideMeal($record)),
                Action::make('suspendUser')
                    ->label(__('admin.moderation_cases.actions.suspend_user'))
                    ->color('danger')
                    ->requiresConfirmation()
                    ->visible(fn (ModerationCase $record): bool => $record->caseable_type === User::class
                        && $record->caseable instanceof User
                        && ! $record->caseable->isSuspended())
                    ->action(fn (ModerationCase $record): bool => self::suspendUser($record)),
                Action::make('resolve')
                    ->label(__('admin.moderation_cases.actions.resolve'))
                    ->color('success')
                    ->requiresConfirmation()
                    ->visible(fn (ModerationCase $record): bool => $record->status !== ModerationCaseStatus::RESOLVED)
                    ->action(fn (ModerationCase $record): bool => self::closeCase($record, ModerationCaseStatus::RESOLVED, ReportStatus::RESOLVED)),
                Action::make('reject')
                    ->label(__('admin.moderation_cases.actions.reject'))
                    ->color('gray')
                    ->requiresConfirmation()
                    ->visible(fn (ModerationCase $record): bool => $record->status !== ModerationCaseStatus::REJECTED)
                    ->action(fn (ModerationCase $record): bool => self::closeCase($record, ModerationCaseStatus::REJECTED, ReportStatus::REJECTED)),
            ])
            ->toolbarActions([
                //
            ]);
    }

    private static function markReviewing(ModerationCase $record): bool
    {
        $record->forceFill([
            'status' => ModerationCaseStatus::REVIEWING,
            'assigned_to' => $record->assigned_to ?: auth()->id(),
        ])->save();

        $record->reports()
            ->where('status', ReportStatus::OPEN->value)
            ->update([
                'status' => ReportStatus::REVIEWING->value,
                'reviewed_by' => auth()->id(),
                'reviewed_at' => now(),
            ]);

        return true;
    }

    private static function hideMeal(ModerationCase $record): bool
    {
        $mealPost = $record->caseable;

        if (! $mealPost instanceof MealPosts) {
            return false;
        }

        $mealPost->forceFill([
            'hidden_at' => now(),
            'hidden_by' => auth()->id(),
            'hidden_reason' => __('admin.moderation_cases.actions.hide_meal'),
        ])->save();

        return self::markReviewing($record);
    }

    private static function suspendUser(ModerationCase $record): bool
    {
        $user = $record->caseable;

        if (! $user instanceof User) {
            return false;
        }

        $user->forceFill([
            'suspended_at' => now(),
            'suspended_by' => auth()->id(),
            'suspended_reason' => __('admin.moderation_cases.actions.suspend_user'),
        ])->save();

        return self::markReviewing($record);
    }

    private static function closeCase(
        ModerationCase $record,
        ModerationCaseStatus $caseStatus,
        ReportStatus $reportStatus,
    ): bool {
        $record->forceFill([
            'status' => $caseStatus,
            'assigned_to' => $record->assigned_to ?: auth()->id(),
            'resolved_by' => auth()->id(),
            'resolved_at' => now(),
        ])->save();

        $record->reports()->update([
            'status' => $reportStatus->value,
            'reviewed_by' => auth()->id(),
            'reviewed_at' => now(),
        ]);

        return true;
    }
}
