<?php

namespace App\Http\Livewire\Mailings;

use App\Http\Livewire\Traits\RequiresAdminAuthorization;
use App\Models\Mailing;
use App\Models\Post;
use Illuminate\Support\Facades\Auth;
use Livewire\Attributes\On;
use Livewire\Component;
use Livewire\WithPagination;
use WireUi\Traits\WireUiActions;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;

class Manage extends Component
{
    use WithPagination, WireUiActions, RequiresAdminAuthorization;

    // Search and filtering
    public $search = '';
    public $typeFilter = '';
    public $statusFilter = '';
    public $sortField = 'created_at';
    public $sortDirection = 'desc';

    // Bulk selection
    public $bulkSelected = [];
    public $bulkDisabled = true;

    // Modal controls
    public $showCreateModal = false;
    public $showEditModal = false;
    public $showPreviewModal = false;
    public $showTestMailModal = false;
    public $showTestEmailSelectionModal = false;
    public $showBulkDeleteModal = false;
    public $showSendConfirmModal = false;
    public $editingMailing = null;
    public $testMailMessage = '';
    public $mailingToSend = null;
    public $mailingForTest = null;

    // Test email selection properties
    public $sendToAuthUser = false;
    public $sendToActiveProfile = false;
    public $customTestEmail = '';
    public $availableTestEmails = [];

    // Form data
    public $title = '';
    public $type = '';
    public $subjects = []; // Multilingual subjects array
    public $selectedPosts = [];
    public $scheduledAt = null;
    public $availableLocales = [];

    // Profile type filtering
    public $filterByProfileType = false;
    public $selectedProfileTypes = [];

    // Location filtering
    public $filterByLocation = false;
    public $selectedCountryIds = [];
    public $selectedDivisionIds = [];
    public $selectedCityIds = [];
    public $selectedDistrictIds = [];
    public $estimatedRecipientCount = 0;

    // Post selection
    public $showPostSelector = false;
    public $postSearch = '';
    public $selectedPostIds = [];


    protected $rules = [
        'title' => 'required|string|max:255',
        'type' => 'required|in:local_newsletter,general_newsletter,system_message',
        'subjects' => 'required|array|min:1',
        'subjects.*' => 'required|string|max:255',
        'selectedPosts' => 'array',
        'scheduledAt' => 'nullable|date|after:now',
        'filterByProfileType' => 'boolean',
        'selectedProfileTypes' => 'array',
        'selectedProfileTypes.*' => 'string|in:User,Organization,Bank,Admin',
        'filterByLocation' => 'boolean',
        'selectedCountryIds' => 'array',
        'selectedCountryIds.*' => 'integer|exists:countries,id',
        'selectedDivisionIds' => 'array',
        'selectedDivisionIds.*' => 'integer|exists:divisions,id',
        'selectedCityIds' => 'array',
        'selectedCityIds.*' => 'integer|exists:cities,id',
        'selectedDistrictIds' => 'array',
        'selectedDistrictIds.*' => 'integer|exists:districts,id',
        'customTestEmail' => 'nullable|email',
    ];

    public function mount()
    {
        // Admin Authorization - Prevent IDOR attacks and cross-guard access
        $activeProfileType = session('activeProfileType');
        $activeProfileId = session('activeProfileId');

        if (!$activeProfileType || !$activeProfileId) {
            abort(403, __('No active profile selected'));
        }

        $profile = $activeProfileType::find($activeProfileId);

        if (!$profile) {
            abort(403, __('Active profile not found'));
        }

        // Validate profile ownership using ProfileAuthorizationHelper (prevents cross-guard attacks)
        \App\Helpers\ProfileAuthorizationHelper::authorize($profile);

        // Verify admin or central bank permissions
        if ($profile instanceof \App\Models\Admin) {
            // Admin access OK
        } elseif ($profile instanceof \App\Models\Bank) {
            // Only central bank (level 0) can access mailing management
            if ($profile->level !== 0) {
                abort(403, __('Central bank access required for mailing management'));
            }
        } else {
            abort(403, __('Admin or central bank access required'));
        }

        // Log admin access for security monitoring
        \Log::info('Mailings management access', [
            'component' => 'Mailings\\Manage',
            'profile_id' => $profile->id,
            'profile_type' => get_class($profile),
            'authenticated_guard' => \Auth::getDefaultDriver(),
            'ip_address' => request()->ip(),
        ]);

        // Initialize estimated recipient count to 0 since no type is selected initially
        $this->estimatedRecipientCount = 0;
    }

    public function updatedPage()
    {
        $this->dispatch('scroll-to-top');
    }

    public function render()
    {
        $mailingsQuery = Mailing::with(['updatedByUser:id,name,full_name,profile_photo_path'])
            ->when($this->search, function ($query) {
                $query->where(function ($q) {
                    $q->where('title', 'like', '%' . $this->search . '%')
                        ->orWhere('subject', 'like', '%' . $this->search . '%');
                });
            })
            ->when($this->typeFilter, function ($query) {
                $query->where('type', $this->typeFilter);
            })
            ->when($this->statusFilter, function ($query) {
                $query->where('status', $this->statusFilter);
            })
            ->orderBy($this->sortField, $this->sortDirection);

        $mailings = $mailingsQuery->paginate(15);

        return view('livewire.mailings.manage', [
            'mailings' => $mailings,
            'availablePosts' => $this->getAvailablePosts(),
        ]);
    }

    public function updatedSearch()
    {
        $this->resetPage();
    }

    public function updatedTypeFilter()
    {
        $this->resetPage();
    }

    public function updatedStatusFilter()
    {
        $this->resetPage();
    }

    public function sortBy($field)
    {
        if ($this->sortField === $field) {
            $this->sortDirection = $this->sortDirection === 'asc' ? 'desc' : 'asc';
        } else {
            $this->sortDirection = 'asc';
        }

        $this->sortField = $field;
    }

    public function openCreateModal()
    {
        $this->resetForm();
        $this->updateAvailableLocales(); // Initialize with base language
        $this->showCreateModal = true;
    }

    public function openEditModal($mailingId)
    {
        $this->editingMailing = Mailing::findOrFail($mailingId);

        // Can only edit drafts
        if (!$this->editingMailing->canBeScheduled()) {
            $this->notification([
                'title' => __('Error'),
                'description' => __('Only draft mailings can be edited.'),
                'icon' => 'error'
            ]);
            return;
        }

        $this->title = $this->editingMailing->title;
        $this->type = $this->editingMailing->type;
        $this->subjects = $this->editingMailing->getAllSubjects();

        // Load content blocks and enrich with post titles
        $this->selectedPosts = $this->loadContentBlocksWithTitles($this->editingMailing->content_blocks ?? []);

        // Load profile type filter settings
        $this->filterByProfileType = $this->editingMailing->filter_by_profile_type ?? false;
        $this->selectedProfileTypes = $this->editingMailing->selected_profile_types ?? [];

        // Load location filter settings
        $this->filterByLocation = $this->editingMailing->filter_by_location ?? false;

        // Convert single IDs to arrays for multiple selection support
        $this->selectedCountryIds = $this->editingMailing->location_country_id ? [$this->editingMailing->location_country_id] : [];
        $this->selectedDivisionIds = $this->editingMailing->location_division_id ? [$this->editingMailing->location_division_id] : [];
        $this->selectedCityIds = $this->editingMailing->location_city_id ? [$this->editingMailing->location_city_id] : [];
        $this->selectedDistrictIds = $this->editingMailing->location_district_id ? [$this->editingMailing->location_district_id] : [];

        // Load available locales from posts
        $this->updateAvailableLocales();

        $this->scheduledAt = $this->editingMailing->scheduled_at?->format('Y-m-d\TH:i');

        // Send location data to LocationFilter component
        if ($this->filterByLocation) {
            $this->dispatch('loadLocationFilterData', [
                'countries' => $this->selectedCountryIds,
                'divisions' => $this->selectedDivisionIds,
                'cities' => $this->selectedCityIds,
                'districts' => $this->selectedDistrictIds,
            ]);
        }

        $this->showEditModal = true;
    }

    public function closeModals()
    {
        $this->showCreateModal = false;
        $this->showEditModal = false;
        $this->showPreviewModal = false;
        $this->showTestMailModal = false;
        $this->showTestEmailSelectionModal = false;
        $this->showBulkDeleteModal = false;
        $this->showSendConfirmModal = false;
        $this->showPostSelector = false;
        $this->resetForm();
    }

    public function resetForm()
    {
        $this->title = '';
        $this->type = '';
        $this->subjects = [];
        $this->selectedPosts = [];
        $this->scheduledAt = null;
        $this->editingMailing = null;
        $this->selectedPostIds = [];
        $this->availableLocales = [];
        $this->filterByProfileType = false;
        $this->selectedProfileTypes = [];
        $this->filterByLocation = false;
        $this->selectedCountryIds = [];
        $this->selectedDivisionIds = [];
        $this->selectedCityIds = [];
        $this->selectedDistrictIds = [];
        $this->estimatedRecipientCount = 0;

        // Reset test email selection properties
        $this->sendToAuthUser = false;
        $this->sendToActiveProfile = false;
        $this->customTestEmail = '';
        $this->mailingForTest = null;
        $this->availableTestEmails = [];

        $this->resetValidation();
    }

    public function clearProfileTypes()
    {
        $this->selectedProfileTypes = [];
        $this->updateEstimatedRecipients();
    }

    public function updateEstimatedRecipients()
    {
        // If no type is selected, set count to 0
        if (empty($this->type)) {
            $this->estimatedRecipientCount = 0;
            return;
        }

        // Create a temporary mailing instance with current form data
        $tempMailing = new \App\Models\Mailing();
        $tempMailing->type = $this->type;
        $tempMailing->filter_by_profile_type = $this->filterByProfileType;
        $tempMailing->selected_profile_types = $this->selectedProfileTypes;
        $tempMailing->filter_by_location = $this->filterByLocation;
        $tempMailing->location_country_id = !empty($this->selectedCountryIds) ? $this->selectedCountryIds[0] : null;
        $tempMailing->location_division_id = !empty($this->selectedDivisionIds) ? $this->selectedDivisionIds[0] : null;
        $tempMailing->location_city_id = !empty($this->selectedCityIds) ? $this->selectedCityIds[0] : null;
        $tempMailing->location_district_id = !empty($this->selectedDistrictIds) ? $this->selectedDistrictIds[0] : null;

        $this->estimatedRecipientCount = $tempMailing->getRecipientsQuery()->count();
    }

    // Reactive property updates
    public function updatedFilterByProfileType()
    {
        $this->updateEstimatedRecipients();
    }

    public function updatedSelectedProfileTypes()
    {
        $this->updateEstimatedRecipients();
    }

    // Location filtering event listeners
    #[On('locationFilterUpdated')]
    public function handleLocationFilterUpdate($locationData)
    {
        // Store the data without triggering re-renders
        $this->selectedCountryIds = $locationData['countries'] ?? [];
        $this->selectedDivisionIds = $locationData['divisions'] ?? [];
        $this->selectedCityIds = $locationData['cities'] ?? [];
        $this->selectedDistrictIds = $locationData['districts'] ?? [];
        $this->updateRecipientCount();

        // Don't emit any events that would cause the LocationFilter to re-render
    }

    public function updatedFilterByLocation()
    {
        if (!$this->filterByLocation) {
            $this->selectedCountryIds = [];
            $this->selectedDivisionIds = [];
            $this->selectedCityIds = [];
            $this->selectedDistrictIds = [];

            // Reset the LocationFilter component
            $this->dispatch('resetLocationFilter');
        }
        $this->updateRecipientCount();
    }

    public function updatedType()
    {
        $this->updateEstimatedRecipients();
    }

    public function updateRecipientCount()
    {
        $tempMailing = new Mailing();
        $tempMailing->type = $this->type;

        // Apply location filtering
        $query = $this->getFilteredRecipientsQuery($tempMailing);
        $this->estimatedRecipientCount = $query->count();
    }

    private function getFilteredRecipientsQuery($mailing)
    {
        $baseQuery = $mailing->getRecipientsQuery();

        if (!$this->filterByLocation) {
            return $baseQuery;
        }

        // Apply location filtering based on selected locations
        return $baseQuery->whereHas('locations', function ($query) {
            if (!empty($this->selectedDistrictIds)) {
                $query->whereIn('district_id', $this->selectedDistrictIds);
            } elseif (!empty($this->selectedCityIds)) {
                $query->whereIn('city_id', $this->selectedCityIds);
            } elseif (!empty($this->selectedDivisionIds)) {
                $query->whereIn('division_id', $this->selectedDivisionIds);
            } elseif (!empty($this->selectedCountryIds)) {
                $query->whereIn('country_id', $this->selectedCountryIds);
            }
        });
    }

    public function updateAvailableLocales()
    {
        if (!empty($this->selectedPosts)) {
            // Create a temporary mailing object to get available locales
            $tempMailing = new \App\Models\Mailing();
            $tempMailing->content_blocks = $this->prepareContentBlocks();
            $this->availableLocales = $tempMailing->getAvailablePostLocales();
        } else {
            // If no posts selected, show base language
            $this->availableLocales = [timebank_config('base_language', 'en')];
        }

        // Ensure subjects array has all available locales
        foreach ($this->availableLocales as $locale) {
            if (!isset($this->subjects[$locale])) {
                $this->subjects[$locale] = '';
            }
        }
    }

    /**
     * Get current recipient counts by locale based on form state
     */
    public function getCurrentRecipientCountsByLocale()
    {
        // If no type is selected, return empty array
        if (empty($this->type)) {
            return [];
        }

        // Create a temporary mailing object with current form state
        $tempMailing = new \App\Models\Mailing();
        $tempMailing->type = $this->type;
        $tempMailing->filter_by_profile_type = $this->filterByProfileType;
        $tempMailing->selected_profile_types = $this->selectedProfileTypes;
        $tempMailing->filter_by_location = $this->filterByLocation;
        $tempMailing->content_blocks = $this->prepareContentBlocks();

        // Apply location filtering if enabled
        if ($this->filterByLocation) {
            // Use the first selected ID for compatibility with existing model logic
            $tempMailing->location_country_id = !empty($this->selectedCountryIds) ? $this->selectedCountryIds[0] : null;
            $tempMailing->location_division_id = !empty($this->selectedDivisionIds) ? $this->selectedDivisionIds[0] : null;
            $tempMailing->location_city_id = !empty($this->selectedCityIds) ? $this->selectedCityIds[0] : null;
            $tempMailing->location_district_id = !empty($this->selectedDistrictIds) ? $this->selectedDistrictIds[0] : null;
        }

        return $tempMailing->getRecipientCountsByLocale();
    }

    public function saveMailing()
    {
        // CRITICAL: Authorize admin access for saving mailing
        $this->authorizeAdminAccess();

        // Conditional validation: selectedPosts required if scheduling
        $rules = $this->rules;
        if ($this->scheduledAt) {
            $rules['selectedPosts'] = 'required|array|min:1';
        }

        $this->validate($rules);

        $data = [
            'title' => $this->title,
            'type' => $this->type,
            'subject' => $this->subjects,
            'content_blocks' => $this->prepareContentBlocks(),
            'scheduled_at' => $this->scheduledAt ? \Carbon\Carbon::parse($this->scheduledAt) : null,
            'filter_by_profile_type' => $this->filterByProfileType,
            'selected_profile_types' => $this->selectedProfileTypes,
            'filter_by_location' => $this->filterByLocation,
            // For now, save the first selected ID to maintain compatibility with existing DB schema
            'location_country_id' => !empty($this->selectedCountryIds) ? $this->selectedCountryIds[0] : null,
            'location_division_id' => !empty($this->selectedDivisionIds) ? $this->selectedDivisionIds[0] : null,
            'location_city_id' => !empty($this->selectedCityIds) ? $this->selectedCityIds[0] : null,
            'location_district_id' => !empty($this->selectedDistrictIds) ? $this->selectedDistrictIds[0] : null,
            'updated_by_user_id' => Auth::guard('web')->id(),
        ];

        try {
            if ($this->editingMailing) {
                // Update existing mailing
                $data['status'] = $data['scheduled_at'] ? 'scheduled' : 'draft';
                $this->editingMailing->update($data);
                $this->editingMailing->recipients_count = $this->editingMailing->getRecipientsQuery()->count();
                $this->editingMailing->save();

                $this->notification([
                    'title' => __('Success'),
                    'description' => __('Mailing updated successfully.'),
                    'icon' => 'success'
                ]);
            } else {
                // Create new mailing
                $data['status'] = $data['scheduled_at'] ? 'scheduled' : 'draft';

                $mailing = Mailing::create($data);
                $mailing->recipients_count = $mailing->getRecipientsQuery()->count();
                $mailing->save();

                $this->notification([
                    'title' => __('Success'),
                    'description' => __('Mailing created successfully.'),
                    'icon' => 'success'
                ]);
            }

            $this->closeModals();
            $this->dispatch('mailingCreated');

        } catch (\Exception $e) {
            $this->notification([
                'title' => __('Error'),
                'description' => __('Failed to save mailing: :error', ['error' => $e->getMessage()]),
                'icon' => 'error'
            ]);
        }
    }

    public function deleteMailing($mailingId)
    {
        // CRITICAL: Authorize admin access for deleting mailing
        $this->authorizeAdminAccess();

        $mailing = Mailing::findOrFail($mailingId);

        if (!in_array($mailing->status, ['draft', 'scheduled'])) {
            $this->notification([
                'title' => __('Error'),
                'description' => __('Cannot delete sent or sending mailings.'),
                'icon' => 'error'
            ]);
            return;
        }

        $mailing->delete();

        $this->notification([
            'title' => __('Success'),
            'description' => __('Mailing deleted successfully.'),
            'icon' => 'success'
        ]);

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

    public function openSendConfirmModal($mailingId)
    {
        $this->mailingToSend = Mailing::findOrFail($mailingId);

        if (!$this->mailingToSend->canBeSent()) {
            $this->notification([
                'title' => __('Error'),
                'description' => __('Mailing cannot be sent in its current status.'),
                'icon' => 'error'
            ]);
            return;
        }

        // Note: getEffectiveRecipientsCount() now correctly applies location filtering

        $this->showSendConfirmModal = true;
    }

    public function sendMailing()
    {
        // CRITICAL: Authorize admin access for sending mailing
        $this->authorizeAdminAccess();

        if (!$this->mailingToSend) {
            return;
        }

        $this->mailingToSend->update([
            'status' => 'sending',
            'updated_by_user_id' => Auth::guard('web')->id(),
        ]);

        // Dispatch locale-specific email jobs
        $this->mailingToSend->dispatchLocaleSpecificJobs();

        // TODO: Replace with actual job dispatch in Phase 6
        // This will dispatch separate jobs for each locale with filtered content

        $this->showSendConfirmModal = false;
        $this->mailingToSend = null;

        $this->notification([
            'title' => __('Success'),
            'description' => __('Mailing is being sent. This process may take several minutes.'),
            'icon' => 'success'
        ]);

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

    public function updatedBulkSelected()
    {
        $this->bulkDisabled = count($this->bulkSelected) === 0;
    }

    public function openBulkDeleteModal()
    {
        if (count($this->bulkSelected) === 0) {
            $this->notification([
                'title' => __('Error'),
                'description' => __('Please select mailings to delete.'),
                'icon' => 'error'
            ]);
            return;
        }
        $this->showBulkDeleteModal = true;
    }

    public function bulkDeleteMailings()
    {
        // CRITICAL: Authorize admin access for bulk deleting mailings
        $this->authorizeAdminAccess();

        $mailings = Mailing::whereIn('id', $this->bulkSelected)->get();

        $deleted = 0;
        $errors = 0;

        foreach ($mailings as $mailing) {
            if (in_array($mailing->status, ['draft', 'scheduled'])) {
                $mailing->delete();
                $deleted++;
            } else {
                $errors++;
            }
        }

        $this->showBulkDeleteModal = false;
        $this->bulkSelected = [];
        $this->bulkDisabled = true;

        if ($deleted > 0) {
            $this->notification([
                'title' => __('Success'),
                'description' => ($errors > 0 ? __(':deleted mailing(s) deleted successfully. :errors mailing(s) could not be deleted due to status restrictions.', ['deleted' => $deleted, 'errors' => $errors]) : __(':deleted mailing(s) deleted successfully.', ['deleted' => $deleted])),
                'icon' => 'success'
            ]);
        } else {
            $this->notification([
                'title' => __('Error'),
                'description' => __('No mailings could be deleted. Only draft and scheduled mailings can be deleted.'),
                'icon' => 'error'
            ]);
        }

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

    public function sendTestMail($mailingId)
    {
        // CRITICAL: Authorize admin access for sending test mail
        $this->authorizeAdminAccess();

        $mailing = Mailing::findOrFail($mailingId);

        // Test mail is allowed for draft, scheduled, and even sending mailings
        if (!in_array($mailing->status, ['draft', 'scheduled', 'sending'])) {
            $this->notification([
                'title' => __('Error'),
                'description' => __('Test mail can only be sent for draft, scheduled, or sending mailings.'),
                'icon' => 'error'
            ]);
            return;
        }

        // Check if mailing has content
        $availableLocales = collect(array_keys(config('laravellocalization.supportedLocales', [])))
            ->filter(function ($locale) use ($mailing) {
                $contentBlocks = $mailing->getContentBlocksForLocale($locale);
                return !empty($contentBlocks);
            });

        if ($availableLocales->isEmpty()) {
            $this->notification([
                'title' => __('Error'),
                'description' => __('No content available in any language for this mailing.'),
                'icon' => 'error'
            ]);
            return;
        }

        // Prepare available test emails
        $this->prepareTestEmailOptions();

        // Store mailing for test
        $this->mailingForTest = $mailing;

        // Show email selection modal
        $this->showTestEmailSelectionModal = true;
    }

    public function cancelMailing($mailingId)
    {
        $mailing = Mailing::findOrFail($mailingId);

        if (!$mailing->canBeCancelled()) {
            $this->notification([
                'title' => __('Error'),
                'description' => __('This mailing cannot be unscheduled.'),
                'icon' => 'error'
            ]);
            return;
        }

        // Remove the scheduled datetime and change status back to draft
        $mailing->update([
            'scheduled_at' => null,
            'status' => 'draft'
        ]);

        $this->notification([
            'title' => __('Success'),
            'description' => __('Mailing has been unscheduled successfully and can now be edited.'),
            'icon' => 'success'
        ]);

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

    public function openPostSelector()
    {
        $this->showPostSelector = true;
    }

    public function togglePostSelection($postId)
    {
        if (in_array($postId, $this->selectedPostIds)) {
            $this->selectedPostIds = array_filter($this->selectedPostIds, fn($id) => $id != $postId);
        } else {
            $this->selectedPostIds[] = $postId;
        }
    }

    public function addSelectedPosts()
    {
        $posts = Post::whereIn('id', $this->selectedPostIds)
            ->with('translations')
            ->get();

        foreach ($posts as $index => $post) {
            if (!collect($this->selectedPosts)->firstWhere('post_id', $post->id)) {
                $this->selectedPosts[] = [
                    'post_id' => $post->id,
                    'order' => count($this->selectedPosts) + 1,
                    'title' => $post->translations->first()->title ?? __('Untitled')
                ];
            }
        }

        $this->selectedPostIds = [];
        $this->showPostSelector = false;
        $this->postSearch = '';

        // Update available locales when posts are added
        $this->updateAvailableLocales();
    }

    public function removePost($index)
    {
        unset($this->selectedPosts[$index]);
        $this->selectedPosts = array_values($this->selectedPosts);

        // Reorder posts
        foreach ($this->selectedPosts as $i => $post) {
            $this->selectedPosts[$i]['order'] = $i + 1;
        }

        // Update available locales when posts are removed
        $this->updateAvailableLocales();
    }

    public function movePostUp($index)
    {
        if ($index > 0) {
            $temp = $this->selectedPosts[$index];
            $this->selectedPosts[$index] = $this->selectedPosts[$index - 1];
            $this->selectedPosts[$index - 1] = $temp;

            // Update order numbers
            $this->selectedPosts[$index]['order'] = $index + 1;
            $this->selectedPosts[$index - 1]['order'] = $index;

            $this->updateAvailableLocales();
        }
    }

    public function movePostDown($index)
    {
        if ($index < count($this->selectedPosts) - 1) {
            $temp = $this->selectedPosts[$index];
            $this->selectedPosts[$index] = $this->selectedPosts[$index + 1];
            $this->selectedPosts[$index + 1] = $temp;

            // Update order numbers
            $this->selectedPosts[$index]['order'] = $index + 1;
            $this->selectedPosts[$index + 1]['order'] = $index + 2;

            $this->updateAvailableLocales();
        }
    }

    private function prepareContentBlocks()
    {
        return collect($this->selectedPosts)->map(function ($post, $index) {
            return [
                'post_id' => $post['post_id'],
                'order' => $index + 1
            ];
        })->toArray();
    }

    private function getAvailablePosts()
    {
        if (!$this->showPostSelector) {
            return collect();
        }

        return Post::with(['translations', 'category.translations'])
            ->whereHas('translations', function ($query) {
                $query->where('status', 1) // Status 1 = published
                    ->where('from', '<=', now())
                    ->where(function ($q) {
                        $q->whereNull('till')
                            ->orWhere('till', '>=', now());
                    });
                if ($this->postSearch) {
                    $query->where('title', 'like', '%' . $this->postSearch . '%');
                }
            })
            ->orderBy('updated_at', 'desc')
            ->limit(20)
            ->get();
    }

    #[On('mailingCreated')]
    #[On('mailingUpdated')]
    #[On('mailingDeleted')]
    public function refreshMailings()
    {
        // This method will be called by listeners to refresh the mailings list
        // In Livewire 3, we don't need to call render() explicitly
    }

    /**
     * Load content blocks and enrich with post titles for editing
     */
    private function loadContentBlocksWithTitles($contentBlocks)
    {
        if (empty($contentBlocks)) {
            return [];
        }

        $postIds = collect($contentBlocks)->pluck('post_id');
        $posts = Post::whereIn('id', $postIds)
            ->with('translations')
            ->get()
            ->keyBy('id');

        return collect($contentBlocks)->map(function ($block) use ($posts) {
            $post = $posts->get($block['post_id']);
            return [
                'post_id' => $block['post_id'],
                'order' => $block['order'],
                'title' => $post && $post->translations->first()
                    ? $post->translations->first()->title
                    : __('Post not found (ID: :id)', ['id' => $block['post_id']])
            ];
        })->toArray();
    }

    /**
     * Get published translations with their language flags for a post
     */
    public function getPublishedTranslationsWithFlags($post)
    {
        $now = now();

        return $post->translations->filter(function ($translation) use ($now) {
            return $translation->status == 1
                && $translation->from <= $now
                && ($translation->till === null || $translation->till >= $now);
        })->map(function ($translation) {
            $language = \App\Models\Language::where('lang_code', $translation->locale)->first();
            return [
                'locale' => $translation->locale,
                'flag' => $language ? $language->flag : '🏳️'
            ];
        });
    }

    /**
     * Prepare test email options for the modal
     */
    public function prepareTestEmailOptions()
    {
        $this->availableTestEmails = [];

        // Option 1: Authenticated user email (underlying web user)
        $webUser = Auth::guard('web')->user();
        if ($webUser && $webUser->email) {
            $this->availableTestEmails['auth_user'] = [
                'email' => $webUser->email,
                'label' => __('Your user profile: :email', ['email' => $webUser->email]),
                'available' => true
            ];
        }

        // Option 2: Active profile email (if different from auth user)
        $activeProfile = getActiveProfile();
        if ($activeProfile && $activeProfile->email &&
            (!isset($this->availableTestEmails['auth_user']) || $activeProfile->email !== $this->availableTestEmails['auth_user']['email'])) {
            $this->availableTestEmails['active_profile'] = [
                'email' => $activeProfile->email,
                'label' => __('Your current active profile: :email', ['email' => $activeProfile->email]),
                'available' => true
            ];
        }

        // Reset checkboxes
        $this->sendToAuthUser = false;
        $this->sendToActiveProfile = false;
        $this->customTestEmail = '';
    }

    /**
     * Send test mailing mailing to selected email addresses
     */
    public function sendTestMailToSelected()
    {
        // CRITICAL: Authorize admin access for sending test mail to selected recipients
        $this->authorizeAdminAccess();

        if (!$this->mailingForTest) {
            $this->notification([
                'title' => __('Error'),
                'description' => __('No mailing selected for testing.'),
                'icon' => 'error'
            ]);
            return;
        }

        // Collect selected emails
        $testEmails = [];

        if ($this->sendToAuthUser && isset($this->availableTestEmails['auth_user'])) {
            $testEmails[] = $this->availableTestEmails['auth_user']['email'];
        }

        if ($this->sendToActiveProfile && isset($this->availableTestEmails['active_profile'])) {
            $testEmails[] = $this->availableTestEmails['active_profile']['email'];
        }

        if (!empty($this->customTestEmail)) {
            // Validate custom email
            $this->validateOnly('customTestEmail');
            $testEmails[] = $this->customTestEmail;
        }

        // Check if at least one email is selected
        if (empty($testEmails)) {
            $this->notification([
                'title' => __('Error'),
                'description' => __('Please select at least one email address to send the test to.'),
                'icon' => 'error'
            ]);
            return;
        }

        // Remove duplicates
        $testEmails = array_unique($testEmails);

        // Get all available locales that have content
        $availableLocales = collect(array_keys(config('laravellocalization.supportedLocales', [])))
            ->filter(function ($locale) {
                $contentBlocks = $this->mailingForTest->getContentBlocksForLocale($locale);
                return !empty($contentBlocks);
            });

        if ($availableLocales->isEmpty()) {
            $this->notification([
                'title' => __('Error'),
                'description' => __('No content available in any language for this mailing.'),
                'icon' => 'error'
            ]);
            return;
        }

        try {
            // Save current locale to restore it after sending test emails
            $originalLocale = \App::getLocale();

            $totalEmailsSent = 0;

            // Send test mailing mail to each selected email in each available locale
            foreach ($testEmails as $email) {
                foreach ($availableLocales as $locale) {
                    $testMail = new \App\Mail\TestNewsletterMail($this->mailingForTest, $locale);
                    \Mail::to($email)->send($testMail);
                    $totalEmailsSent++;

                    // Add delay to avoid rate limiting (except for last email)
                    if ($email !== end($testEmails) || $locale !== $availableLocales->last()) {
                        sleep(2); // 2 second delay between emails
                    }
                }
            }

            // Restore original locale before displaying success message
            \App::setLocale($originalLocale);

            $localeCount = $availableLocales->count();
            $recipientCount = count($testEmails);

            // Close selection modal and show success modal
            $this->showTestEmailSelectionModal = false;

            // Show success modal with details
            $this->testMailMessage = __('Test emails sent successfully!') . "\n\n" .
                __('Recipients: :recipients', ['recipients' => implode(', ', $testEmails)]) . "\n\n" .
                __('Languages: :languages', ['languages' => $availableLocales->implode(', ')]) . "\n\n" .
                __('Total emails sent: :count', ['count' => $totalEmailsSent]);
            $this->showTestMailModal = true;

        } catch (\Exception $e) {
            // Restore original locale before displaying error message
            if (isset($originalLocale)) {
                \App::setLocale($originalLocale);
            }

            \Log::error('sendTestMailToSelected exception: ' . $e->getMessage());
            \Log::error('Exception trace: ' . $e->getTraceAsString());

            // Close selection modal and show error modal
            $this->showTestEmailSelectionModal = false;

            $this->testMailMessage = __('Test Email Error') . "\n\n" .
                __('Recipients: :recipients', ['recipients' => implode(', ', $testEmails)]) . "\n\n" .
                __('Error: :error', ['error' => $e->getMessage()]);
            $this->showTestMailModal = true;
        }
    }

    /**
     * Cancel test email selection and close modal
     */
    public function cancelTestEmailSelection()
    {
        $this->showTestEmailSelectionModal = false;
        $this->mailingForTest = null;
        $this->sendToAuthUser = false;
        $this->sendToActiveProfile = false;
        $this->customTestEmail = '';
        $this->availableTestEmails = [];
        $this->resetValidation(['customTestEmail']);
    }

    /**
     * Generate HTML preview of the mailing
     */
    public function getMailingPreviewHtml()
    {
        if (!$this->mailingForTest) {
            return '<p class="text-sm text-gray-500">' . __('No mailing selected') . '</p>';
        }

        // Get the base language for preview
        $locale = timebank_config('base_language', 'en');

        // Generate content blocks for preview
        $contentBlocks = [];
        foreach ($this->mailingForTest->getContentBlocksForLocale($locale) as $block) {
            $post = \App\Models\Post::with(['translations', 'category'])->find($block['post_id']);

            if (!$post) {
                continue;
            }

            // Get translation for the locale
            $translation = $this->mailingForTest->getPostTranslationForLocale($post->id, $locale);

            if (!$translation) {
                continue;
            }

            // Determine post type
            $postType = $this->determinePostType($post);

            // Prepare post data
            $postData = $this->preparePostDataForPreview($post, $translation, $locale);

            $contentBlocks[] = [
                'type' => $postType,
                'data' => $postData,
                'template' => timebank_config("mailing.templates.{$postType}_block")
            ];
        }

        // Render the email view
        return view('emails.newsletter.wrapper', [
            'subject' => $this->mailingForTest->getSubjectForLocale($locale),
            'mailingTitle' => $this->mailingForTest->title,
            'locale' => $locale,
            'contentBlocks' => $contentBlocks,
            'unsubscribeUrl' => '#preview-unsubscribe',
            'isTestMail' => false,
        ])->render();
    }

    /**
     * Determine post type for preview
     */
    private function determinePostType($post)
    {
        // Check for ImagePost category type first
        if ($post->category && $post->category->type && str_starts_with($post->category->type, 'App\\Models\\ImagePost')) {
            return 'image';
        }

        if ($post->category && $post->category->id) {
            $categoryMappings = [
                4 => 'event',     // The Hague events
                5 => 'event',     // South-Holland events
                6 => 'event',     // The Netherlands events
                7 => 'news',      // The Hague news
                8 => 'news',      // General news
                113 => 'article', // Article
            ];

            return $categoryMappings[$post->category->id] ?? 'news';
        }

        if ($post->meeting || (isset($post->from) && $post->from)) {
            return 'event';
        }

        return 'news';
    }

    /**
     * Prepare post data for preview
     */
    private function preparePostDataForPreview($post, $translation, $locale)
    {
        // Generate fully localized URL with translated route path for the preview locale
        $url = LaravelLocalization::getURLFromRouteNameTranslated(
            $locale,
            'routes.post.show_by_slug',
            ['slug' => $translation->slug]
        );

        $data = [
            'title' => $translation->title,
            'excerpt' => $translation->excerpt,
            'content' => $translation->content,
            'url' => $url,
            'date' => $post->updated_at->locale($locale)->translatedFormat('M j, Y'),
            'author' => $post->author ? $post->author->name : null,
        ];

        // Add category information
        if ($post->category) {
            $categoryTranslation = $post->category->translations()->where('locale', $locale)->first();
            $data['category'] = $categoryTranslation ? $categoryTranslation->name : $post->category->translations()->first()->name;
        }

        // Add location prefix
        if ($post->category && $post->category->categoryable && $post->category->categoryable->translations) {
            $locationTranslation = $post->category->categoryable->translations->where('locale', $locale)->first();
            if ($locationTranslation && $locationTranslation->name) {
                $data['location_prefix'] = strtoupper($locationTranslation->name);
            }
        }

        // Add event-specific data
        if ($post->meeting) {
            $data['venue'] = $post->meeting->venue;
            $data['address'] = $post->meeting->address;
        }

        // Add event date/time
        if ($translation->from) {
            $eventDate = \Carbon\Carbon::parse($translation->from);
            $data['event_date'] = $eventDate->locale($locale)->translatedFormat('F j');
            $data['event_time'] = $eventDate->locale($locale)->translatedFormat('H:i');
        }

        // Add image - use email conversion (resized without cropping)
        if ($post->getFirstMediaUrl('posts')) {
            $data['image'] = $post->getFirstMediaUrl('posts', 'email');

            // Add media caption and owner for image posts
            $media = $post->getFirstMedia('posts');
            if ($media) {
                $captionKey = 'caption-' . $locale;
                $data['media_caption'] = $media->getCustomProperty($captionKey, '');
                $data['media_owner'] = $media->getCustomProperty('owner', '');
            }
        }

        return $data;
    }
}