<?php

namespace App\Filament\Resources\AdoptionApplications\Widgets;

use App\Mail\NoteAlertMail;
use App\Models\AdoptionApplication;
use App\Models\AdoptionApplicationNote;
use App\Models\User;
use Filament\Actions\Action;
use Filament\Actions\Concerns\InteractsWithActions;
use Filament\Actions\Contracts\HasActions;
use Filament\Forms\Components\Checkbox;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Notifications\Notification;
use Filament\Widgets\Widget;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Mail;
use Livewire\Attributes\Computed;

class NotesWidget extends Widget implements HasActions, HasForms
{
    use InteractsWithActions;
    use InteractsWithForms;

    protected string $view = 'filament.resources.adoption-applications.widgets.notes-widget';

    protected int|string|array $columnSpan = 'full';

    public ?AdoptionApplication $record = null;

    public function addNoteAction(): Action
    {
        return Action::make('addNote')
            ->label('Add Note')
            ->visible(fn () => $this->record->status !== 'archived')
            ->form([
                Textarea::make('note')
                    ->label('Note')
                    ->required()
                    ->rows(3)
                    ->placeholder('Enter your note here...'),
                Checkbox::make('notify_other_admins')
                    ->label('Notify other admins')
                    ->default(true),
            ])
            ->action(function (array $data): void {
                AdoptionApplicationNote::create([
                    'adoption_application_id' => $this->record->id,
                    'note' => $data['note'],
                    'created_by' => Auth::id(),
                ]);

                if ($data['notify_other_admins'] ?? true) {
                    $otherAdmins = User::where('is_admin', true)
                        ->where('receive_note_alerts', true)
                        ->where('id', '!=', Auth::id())
                        ->get();

                    $adminUrl = route('filament.admin.resources.adoption-applications.edit', $this->record->id);

                    foreach ($otherAdmins as $admin) {
                        $preference = $admin->note_alert_preference ?? 'both';

                        if (in_array($preference, ['filament', 'both'])) {
                            $admin->notify(
                                Notification::make()
                                    ->title('New note added to adoption application')
                                    ->body(Auth::user()->name.' added a note to adoption application #'.$this->record->id)
                                    ->actions([
                                        Action::make('view')
                                            ->button()
                                            ->markAsRead()
                                            ->url($adminUrl),
                                    ])
                                    ->persistent()
                                    ->toDatabase()
                            );
                        }

                        if (in_array($preference, ['email', 'both'])) {
                            Mail::to($admin->email)->send(new NoteAlertMail(
                                author: Auth::user(),
                                applicationType: 'adoption',
                                applicationId: $this->record->id,
                                noteContent: $data['note'],
                                adminUrl: $adminUrl,
                            ));
                        }
                    }
                }

                Notification::make()
                    ->success()
                    ->title('Note added successfully')
                    ->send();

                $this->dispatch('$refresh');
            });
    }

    /**
     * @return Collection<int, AdoptionApplicationNote>
     */
    #[Computed]
    public function notes(): Collection
    {
        return $this->record
            ->notes()
            ->with('createdBy')
            ->orderBy('created_at', 'desc')
            ->get();
    }
}
