<?php

namespace App\Http\Controllers;

use App\Concerns\HasWorkspaceScope;
use App\Enums\DeclarationStatus;
use App\Http\Requests\BulkNotifyRequest;
use App\Mail\DeclarationFileRequestMail;
use App\Models\Declaration;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;

class BulkNotificationController extends Controller
{
    use HasWorkspaceScope;

    public function store(BulkNotifyRequest $request): RedirectResponse
    {
        $workspace = $this->currentWorkspace();
        $user = $request->user();
        $workspaceUser = $user->currentWorkspaceUser();

        $declarations = Declaration::where('workspace_id', $workspace->id)
            ->forUser($user, $workspaceUser)
            ->where('status', DeclarationStatus::EnAttenteClient)
            ->whereIn('id', $request->validated('declaration_ids'))
            ->with('client')
            ->get()
            ->filter(fn (Declaration $d) => $d->client !== null);

        if ($declarations->isEmpty()) {
            return back()->with('flash', [
                'type' => 'warning',
                'message' => 'Aucune déclaration éligible trouvée.',
            ]);
        }

        // DB transaction for invitation creation/update, collect mail data for queuing after commit
        $mailJobs = DB::transaction(function () use ($declarations) {
            $jobs = [];

            foreach ($declarations as $declaration) {
                $clientEmail = $declaration->client->contact_email;

                $invitation = $declaration->invitations()
                    ->whereNull('used_at')
                    ->latest()
                    ->first();

                if ($invitation && $invitation->isValid()) {
                    if ($invitation->email !== $clientEmail) {
                        $invitation->update(['email' => $clientEmail]);
                        $invitation->refresh();
                    }
                } elseif ($invitation && ! $invitation->isValid()) {
                    $invitation->update([
                        'email' => $clientEmail,
                        'expires_at' => now()->addDays(30),
                    ]);
                    $invitation->refresh();
                } else {
                    $invitation = $declaration->invitations()->create([
                        'email' => $clientEmail,
                        'expires_at' => now()->addDays(30),
                    ]);
                }

                $body = 'Nous vous invitons à déposer les documents complémentaires pour votre déclaration "'
                    . $declaration->title . '".';

                $jobs[] = [
                    'email' => $declaration->client->contact_email,
                    'mailable' => new DeclarationFileRequestMail($declaration, $invitation, $body),
                ];
            }

            return $jobs;
        });

        // Queue emails outside transaction (Redis is not transactional with MySQL)
        foreach ($mailJobs as $job) {
            Mail::to($job['email'])->queue($job['mailable']);
        }

        activity()
            ->performedOn($workspace)
            ->causedBy($user)
            ->withProperties([
                'count' => $declarations->count(),
                'declaration_ids' => $declarations->pluck('id')->all(),
            ])
            ->log('bulk_client_notification');

        // Invalidate notification caches for workspace users
        $workspace->users->each(function ($wsUser) use ($workspace) {
            Cache::forget("user:{$wsUser->id}:workspace:{$workspace->id}:unread_notifications");
        });

        return back()->with('flash', [
            'type' => 'success',
            'message' => $declarations->count() . ' notifications envoyées',
        ]);
    }
}
