<?php

namespace App\Filament\Association\Resources\ElectionResource\RelationManagers;

use App\Events\CandidateApproved;
use App\Events\CandidateRejected;
use App\Models\ElectionAuditLog;
use App\Models\ElectionCandidate;
use App\Services\Elections\ElectionAuditService;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Notifications\Notification;
use Filament\Resources\RelationManagers\RelationManager;
use Filament\Tables;
use Filament\Tables\Table;

class CandidatesRelationManager extends RelationManager
{
    protected static string $relationship = 'candidates';
    protected static ?string $title = 'Candidates';

    public function form(Form $form): Form
    {
        return $form->schema([
            Forms\Components\Select::make('position_id')
                ->label('Position')
                ->relationship('position', 'title')
                ->required(),
            Forms\Components\Select::make('user_id')
                ->label('Member')
                ->relationship('user', 'firstname')
                ->getOptionLabelFromRecordUsing(fn ($record) => trim($record->firstname . ' ' . $record->surname) . ' (' . $record->email . ')')
                ->searchable(['firstname', 'surname', 'email'])
                ->required(),
            Forms\Components\Select::make('status')
                ->options(ElectionCandidate::STATUSES)
                ->default(ElectionCandidate::STATUS_PENDING)
                ->required(),
            Forms\Components\Textarea::make('manifesto')
                ->rows(4)
                ->maxLength(10000),
            Forms\Components\TextInput::make('campaign_slogan')
                ->maxLength(255),
            Forms\Components\FileUpload::make('photo_path')
                ->label('Candidate Photo')
                ->image()
                ->directory('elections/candidates'),
            Forms\Components\Hidden::make('association_id')
                ->default(fn () => filament()->getTenant()?->id),
            Forms\Components\Hidden::make('election_id')
                ->default(fn () => $this->getOwnerRecord()->id),
        ]);
    }

    public function table(Table $table): Table
    {
        return $table
            ->columns([
                Tables\Columns\ImageColumn::make('user.profile_photo_path')
                    ->label('')
                    ->circular()
                    ->defaultImageUrl(fn () => asset('images/default-avatar.png'))
                    ->getStateUsing(fn ($record) => $record->user?->profile_photo_path),
                Tables\Columns\TextColumn::make('user.firstname')
                    ->label('Name')
                    ->formatStateUsing(fn ($record) => $record->user
                        ? trim($record->user->firstname . ' ' . $record->user->surname)
                        : '—')
                    ->searchable(['firstname', 'surname']),
                Tables\Columns\TextColumn::make('position.title')
                    ->label('Position')
                    ->sortable(),
                Tables\Columns\TextColumn::make('status')
                    ->badge()
                    ->color(fn (string $state): string => match ($state) {
                        'pending' => 'warning',
                        'approved' => 'success',
                        'rejected' => 'danger',
                        'withdrawn' => 'gray',
                        'disqualified' => 'danger',
                        default => 'gray',
                    })
                    ->formatStateUsing(fn (string $state) => ElectionCandidate::STATUSES[$state] ?? ucfirst($state)),
                Tables\Columns\TextColumn::make('endorsement_count')
                    ->label('Endorsements')
                    ->sortable(),
                Tables\Columns\TextColumn::make('created_at')
                    ->label('Nominated')
                    ->dateTime('M d, Y')
                    ->sortable(),
            ])
            ->defaultSort('created_at', 'desc')
            ->filters([
                Tables\Filters\SelectFilter::make('status')
                    ->options(ElectionCandidate::STATUSES),
                Tables\Filters\SelectFilter::make('position_id')
                    ->label('Position')
                    ->relationship('position', 'title'),
            ])
            ->headerActions([
                Tables\Actions\CreateAction::make()
                    ->mutateFormDataUsing(function (array $data): array {
                        $data['association_id'] = filament()->getTenant()?->id;
                        $data['election_id'] = $this->getOwnerRecord()->id;
                        return $data;
                    }),
            ])
            ->actions([
                Tables\Actions\Action::make('approve')
                    ->label('Approve')
                    ->icon('heroicon-o-check-circle')
                    ->color('success')
                    ->requiresConfirmation()
                    ->visible(fn (ElectionCandidate $record) => $record->status === ElectionCandidate::STATUS_PENDING)
                    ->action(function (ElectionCandidate $record) {
                        $election = $this->getOwnerRecord();

                        $record->update([
                            'status' => ElectionCandidate::STATUS_APPROVED,
                            'reviewed_by' => auth()->id(),
                            'reviewed_at' => now(),
                        ]);

                        // Audit log
                        app(ElectionAuditService::class)->log(
                            $election,
                            ElectionAuditLog::EVENT_CANDIDATE_ACTION,
                            [
                                'action' => 'approve',
                                'candidate_id' => $record->id,
                                'user_id' => $record->user_id,
                            ],
                            auth()->id(),
                            request()->ip(),
                        );

                        // Send notification email
                        CandidateApproved::dispatch($record, $election);

                        Notification::make()->title('Candidate approved')->success()->send();
                    }),
                Tables\Actions\Action::make('reject')
                    ->label('Reject')
                    ->icon('heroicon-o-x-circle')
                    ->color('danger')
                    ->form([
                        Forms\Components\Textarea::make('rejection_reason')
                            ->required()
                            ->maxLength(1000),
                    ])
                    ->visible(fn (ElectionCandidate $record) => $record->status === ElectionCandidate::STATUS_PENDING)
                    ->action(function (ElectionCandidate $record, array $data) {
                        $election = $this->getOwnerRecord();

                        $record->update([
                            'status' => ElectionCandidate::STATUS_REJECTED,
                            'rejection_reason' => $data['rejection_reason'],
                            'reviewed_by' => auth()->id(),
                            'reviewed_at' => now(),
                        ]);

                        // Audit log
                        app(ElectionAuditService::class)->log(
                            $election,
                            ElectionAuditLog::EVENT_CANDIDATE_ACTION,
                            [
                                'action' => 'reject',
                                'candidate_id' => $record->id,
                                'user_id' => $record->user_id,
                                'reason' => $data['rejection_reason'],
                            ],
                            auth()->id(),
                            request()->ip(),
                        );

                        // Send notification email
                        CandidateRejected::dispatch($record, $election);

                        Notification::make()->title('Candidate rejected')->danger()->send();
                    }),
                Tables\Actions\Action::make('disqualify')
                    ->label('Disqualify')
                    ->icon('heroicon-o-no-symbol')
                    ->color('danger')
                    ->form([
                        Forms\Components\Textarea::make('rejection_reason')
                            ->label('Reason for disqualification')
                            ->required()
                            ->maxLength(1000),
                    ])
                    ->visible(fn (ElectionCandidate $record) => $record->status === ElectionCandidate::STATUS_APPROVED)
                    ->action(function (ElectionCandidate $record, array $data) {
                        $election = $this->getOwnerRecord();

                        $record->update([
                            'status' => ElectionCandidate::STATUS_DISQUALIFIED,
                            'rejection_reason' => $data['rejection_reason'],
                            'reviewed_by' => auth()->id(),
                            'reviewed_at' => now(),
                        ]);

                        // Audit log
                        app(ElectionAuditService::class)->log(
                            $election,
                            ElectionAuditLog::EVENT_CANDIDATE_ACTION,
                            [
                                'action' => 'disqualify',
                                'candidate_id' => $record->id,
                                'user_id' => $record->user_id,
                                'reason' => $data['rejection_reason'],
                            ],
                            auth()->id(),
                            request()->ip(),
                        );

                        Notification::make()->title('Candidate disqualified')->danger()->send();
                    }),
                Tables\Actions\EditAction::make(),
            ])
            ->bulkActions([
                Tables\Actions\BulkActionGroup::make([
                    Tables\Actions\DeleteBulkAction::make(),
                ]),
            ]);
    }
}
