<?php

namespace App\Services;

use App\Models\Activity;
use App\Models\Contact;
use App\Models\Event;
use App\Models\Note;
use App\Models\Task;
use App\Models\User;
use Carbon\Carbon;
use App\Services\EventPlannerService;
use App\Services\MailService;

class AgentActionService
{
    public static function handle(User $user, array $parsed): array
    {
        return match ($parsed['type']) {
            'event' => self::handleEvent($user, $parsed['data']),
            'event_update' => self::handleEventUpdate($user, $parsed['data']),
            'note' => self::handleNote($user, $parsed['data']),
            'note_update' => self::handleNoteUpdate($user, $parsed['data']),
            'task' => self::handleTask($user, $parsed['data']),
            'task_update' => self::handleTaskUpdate($user, $parsed['data']),
            'contact' => self::handleContact($user, $parsed['data']),
            'email' => self::handleEmail($user, $parsed['data']),
            default => self::handleUnknown($parsed),
        };
    }


    protected static function handleEvent(User $user, array $data): array
    {
        $planner = app(EventPlannerService::class);

        /*
        |--------------------------------------------------------------------------
        | 🔥 1. ZEITRAUM (AI hat start + end geliefert)
        |--------------------------------------------------------------------------
        */

        if (!empty($data['start']) && empty($data['end']) && ($data['is_all_day'] ?? false)) {

            if (!empty($data['range_end'])) {
                $data['end'] = $data['range_end'];
            }
        }

        if (!empty($data['start']) && !empty($data['end'])) {
            $title    = $data['title'] ?? 'Termin';
            $dateStr  = Carbon::parse($data['start'])->toDateString();
            $force    = !empty($data['force']);
            if (!$force && Event::where('user_id', $user->id)->where('title', $title)->whereDate('starts_at', $dateStr)->exists()) {
                return ['status' => 'failed', 'message' => "Termin \"{$title}\" existiert an diesem Tag bereits.", 'meta' => []];
            }

            return $planner->plan($user, array_merge($data, [
                'title' => $title,
                'start' => $data['start'],
                'end' => $data['end'],
                'duration_minutes' => Carbon::parse($data['start'])
                    ->diffInMinutes(Carbon::parse($data['end'])),
                'is_all_day' => $data['is_all_day'] ?? false,
                'exceptions' => $data['exceptions'] ?? null,
            ]));
        }

        /*
        |--------------------------------------------------------------------------
        | 🔥 2. NORMALER TERMIN (datetime)
        |--------------------------------------------------------------------------
        */

        if (!empty($data['datetime'])) {
            $title   = $data['title'] ?? 'Termin';
            $dateStr = Carbon::parse($data['datetime'])->toDateString();
            $force   = !empty($data['force']);
            if (!$force && Event::where('user_id', $user->id)->where('title', $title)->whereDate('starts_at', $dateStr)->exists()) {
                return ['status' => 'failed', 'message' => "Termin \"{$title}\" existiert an diesem Tag bereits.", 'meta' => []];
            }

            return $planner->plan($user, array_merge($data, [
                'title' => $title,
                'start' => $data['datetime'],
                'duration_minutes' => $data['duration_minutes'] ?? null,
                'ai_duration' => $data['ai_duration'] ?? null,
            ]));
        }

        /*
        |--------------------------------------------------------------------------
        | ❌ FALLBACK
        |--------------------------------------------------------------------------
        */

        return [
            'status' => 'failed',
            'message' => 'Keine Zeit erkannt',
            'meta' => []
        ];
    }


    protected static function handleNote(User $user, array $data): array
    {
        $content = $data['content'] ?? $data['text'] ?? '';
        if ($content && Note::where('user_id', $user->id)->where('content', $content)->whereDate('created_at', today())->exists()) {
            return ['status' => 'failed', 'message' => 'Diese Notiz wurde heute bereits angelegt.', 'meta' => []];
        }

        $note = Note::create([
            'user_id' => $user->id,
            'title'   => $data['title'] ?? null,
            'content' => $data['content'] ?? $data['text'] ?? '',
            'color'   => $data['color'] ?? 'yellow',
        ]);

        Activity::log(
            $user->id,
            Activity::TYPE_NOTE_CREATED,
            Activity::localizedTitle('note_created_assistant', $user->locale ?? 'de'),
            $note->title,
        );

        // Verifikation
        $verified = Note::find($note->id);
        if (! $verified) {
            \Log::error('Action verify failed: note not found after create', ['note_id' => $note->id]);
            return ['status' => 'error', 'message' => 'Notiz konnte nicht erstellt werden. Bitte nochmal versuchen.', 'meta' => []];
        }

        \Log::info('Action verified', ['type' => 'note', 'note_id' => $verified->id, 'verified' => true]);

        return [
            'status'  => 'success',
            'verified' => true,
            'message' => "Notiert! \"{$verified->title}\"",
            'meta'    => ['title' => $verified->title, 'content' => $verified->content],
        ];
    }

    protected static function handleTask(User $user, array $data): array
    {
        $title = $data['title'] ?? $data['description'] ?? 'Aufgabe';

        if (Task::where('user_id', $user->id)->where('title', $title)->whereDate('created_at', today())->exists()) {
            return ['status' => 'failed', 'message' => "Aufgabe \"{$title}\" wurde heute bereits angelegt.", 'meta' => []];
        }

        // due_at: AI schickt due_at, due_date oder datetime
        $dueAt = null;
        if (!empty($data['due_at'])) {
            try { $dueAt = Carbon::parse($data['due_at'])->utc(); } catch (\Throwable) {}
        } elseif (!empty($data['due_date'])) {
            try { $dueAt = Carbon::parse($data['due_date'], $user->timezone); } catch (\Throwable) {}
        } elseif (!empty($data['datetime'])) {
            try { $dueAt = Carbon::parse($data['datetime'], $user->timezone)->startOfDay(); } catch (\Throwable) {}
        }

        // reminder_at: direkt aus AI-Response (UTC)
        $reminderAt = null;
        if (!empty($data['reminder_at'])) {
            try { $reminderAt = Carbon::parse($data['reminder_at'])->utc(); } catch (\Throwable) {}
        }

        $task = Task::create([
            'user_id'       => $user->id,
            'title'         => $title,
            'description'   => $data['description'] ?? null,
            'priority'      => $data['priority'] ?? Task::PRIORITY_MEDIUM,
            'status'        => Task::STATUS_PENDING,
            'due_at'        => $dueAt,
            'reminder_at'   => $reminderAt,
            'reminder_sent' => false,
        ]);

        Activity::log(
            $user->id,
            Activity::TYPE_TASK_CREATED,
            Activity::localizedTitle('task_created_assistant', $user->locale ?? 'de'),
            $task->title,
            meta: ['priority' => $task->priority]
        );

        // Verifikation
        $verified = Task::find($task->id);
        if (! $verified) {
            \Log::error('Action verify failed: task not found after create', ['task_id' => $task->id]);
            return ['status' => 'error', 'message' => 'Aufgabe konnte nicht erstellt werden. Bitte nochmal versuchen.', 'meta' => []];
        }

        \Log::info('Action verified', ['type' => 'task', 'task_id' => $verified->id, 'verified' => true]);

        $tz          = $user->timezone ?? 'Europe/Vienna';
        $dueText     = $dueAt ? ' (fällig: ' . $dueAt->setTimezone($tz)->format('d.m.Y') . ')' : '';
        $reminderText = $reminderAt ? ' Erinnerung: ' . $reminderAt->setTimezone($tz)->format('H:i') . ' Uhr.' : '';

        return [
            'status'   => 'success',
            'verified' => true,
            'message'  => "Erledigt! Aufgabe \"{$verified->title}\" erstellt{$dueText}.{$reminderText}",
            'meta'     => [
                'title'       => $verified->title,
                'priority'    => $verified->priorityLabel(),
                'due_at'      => $dueAt?->setTimezone($tz)->format('d.m.Y'),
                'reminder_at' => $reminderAt?->setTimezone($tz)->format('H:i'),
            ],
        ];
    }

    protected static function handleEventUpdate(User $user, array $data): array
    {
        $search = $data['search'] ?? '';

        if (!$search) {
            return ['status' => 'failed', 'message' => 'Kein Termin angegeben', 'meta' => []];
        }

        $tz = $user->timezone ?? 'Europe/Vienna';

        // Diagnose-Log: wie viele Kandidaten existieren, welcher wird gewählt?
        $candidates = Event::where('user_id', $user->id)
            ->where('title', 'like', '%' . $search . '%')
            ->where('starts_at', '>=', now()->subDays(7))
            ->orderBy('starts_at')
            ->get(['id', 'title', 'starts_at']);

        \Log::info('EventUpdate: Kandidatensuche', [
            'user_id' => $user->id,
            'search' => $search,
            'candidate_count' => $candidates->count(),
            'candidates' => $candidates->map(fn($c) => [
                'id' => $c->id,
                'title' => $c->title,
                'starts_at' => $c->starts_at?->toIso8601String(),
            ])->all(),
            'incoming_data' => $data,
        ]);

        // Kein Kandidat → neues Event erstellen falls Zeitangabe vorhanden
        if ($candidates->isEmpty()) {
            if (!empty($data['datetime']) || !empty($data['start'])) {
                \Log::info('EventUpdate: Kein Kandidat gefunden → erstelle neues Event', ['search' => $search]);
                $createData = array_merge($data, [
                    'title' => $data['title'] ?? $data['search'] ?? $search,
                ]);
                return self::handleEvent($user, $createData);
            }
            return ['status' => 'failed', 'message' => "Kein Termin mit \"{$search}\" gefunden", 'meta' => ['search' => $search]];
        }

        $event = Event::find($candidates->first()->id);

        \Log::info('EventUpdate: Ausgewählter Termin (vor Änderung)', [
            'event_id' => $event->id,
            'title' => $event->title,
            'starts_at_utc' => $event->starts_at?->toIso8601String(),
            'starts_at_local' => $event->starts_at?->copy()->setTimezone($tz)->toIso8601String(),
            'ends_at_utc' => $event->ends_at?->toIso8601String(),
        ]);

        $changes = [];
        $expectedStart = null;

        // Notiz hinzufügen
        if (!empty($data['notes'])) {
            $event->notes = $event->notes
                ? $event->notes . "\n" . $data['notes']
                : $data['notes'];
            $changes[] = 'Notiz hinzugefügt';
        }

        // Verschieben (neues Datum/Uhrzeit)
        if (!empty($data['datetime'])) {
            $newStart = Carbon::parse($data['datetime'], $tz)->utc();
            $duration = $event->ends_at ? $event->starts_at->diffInMinutes($event->ends_at) : 60;
            $event->starts_at = $newStart;
            $event->ends_at = $newStart->copy()->addMinutes($duration);
            $expectedStart = $newStart;
            $changes[] = 'verschoben';
        }

        // Nur Startzeit ändern
        if (!empty($data['start'])) {
            $newStart = Carbon::parse($data['start'], $tz)->utc();
            $duration = $event->ends_at ? $event->starts_at->diffInMinutes($event->ends_at) : 60;
            $event->starts_at = $newStart;
            $event->ends_at = $newStart->copy()->addMinutes($duration);
            $expectedStart = $newStart;
            $changes[] = 'Start geändert';
        }

        // Endzeit / Dauer ändern
        if (!empty($data['end'])) {
            $event->ends_at = Carbon::parse($data['end'], $tz)->utc();
            $changes[] = 'Ende geändert';
        }
        if (!empty($data['duration_minutes'])) {
            $event->ends_at = $event->starts_at->copy()->addMinutes((int) $data['duration_minutes']);
            $changes[] = 'Dauer geändert';
        }

        // Titel ändern
        if (!empty($data['title'])) {
            $event->title = $data['title'];
            $changes[] = 'Titel geändert';
        }

        // Reminder setzen
        if (isset($data['reminders']) && is_array($data['reminders'])) {
            $event->reminders = $data['reminders'];
            $count = count($data['reminders']);
            $changes[] = $count === 1 ? '1 Erinnerung gesetzt' : "{$count} Erinnerungen gesetzt";
        }

        \Log::info('EventUpdate: vor save()', [
            'event_id' => $event->id,
            'expected_start_utc' => $expectedStart?->toIso8601String(),
            'expected_start_local' => $expectedStart?->copy()->setTimezone($tz)->toIso8601String(),
            'new_starts_at_utc' => $event->starts_at?->toIso8601String(),
            'changes' => $changes,
        ]);

        $event->save();

        // ── Verifikation ──
        $verified = Event::find($event->id);

        \Log::info('EventUpdate: nach save() (DB-Stand)', [
            'event_id' => $verified?->id,
            'actual_start_utc' => $verified?->starts_at?->toIso8601String(),
            'actual_start_local' => $verified?->starts_at?->copy()->setTimezone($tz)->toIso8601String(),
        ]);

        if (! $verified) {
            \Log::error('Action verify failed: event not found after save', ['event_id' => $event->id]);
            return ['status' => 'error', 'message' => 'Der Termin wurde nicht gespeichert. Bitte nochmal versuchen.', 'verified' => false, 'meta' => []];
        }

        if ($expectedStart) {
            $verifiedStart = $verified->starts_at->setTimezone($tz);
            $expectedDate = $expectedStart->copy()->setTimezone($tz)->format('Y-m-d');
            $actualDate = $verifiedStart->format('Y-m-d');

            if ($expectedDate !== $actualDate) {
                // Nochmals direkt updaten
                $verified->update([
                    'starts_at' => $expectedStart,
                    'ends_at' => $expectedStart->copy()->addMinutes(
                        $verified->ends_at ? $verified->starts_at->diffInMinutes($verified->ends_at) : 60
                    ),
                ]);
                $verified->refresh();
                $verifiedStart = $verified->starts_at->setTimezone($tz);

                if ($verifiedStart->format('Y-m-d') !== $expectedDate) {
                    \Log::error('Action verify failed: event date mismatch after retry', [
                        'event_id' => $event->id,
                        'expected' => $expectedDate,
                        'actual' => $verifiedStart->format('Y-m-d'),
                    ]);
                    return ['status' => 'error', 'message' => 'Das Verschieben hat nicht funktioniert. Bitte nochmal versuchen.', 'verified' => false, 'meta' => []];
                }
            }

            \Log::info('Action verified', [
                'type' => 'event_update',
                'event_id' => $verified->id,
                'verified' => true,
                'date' => $verifiedStart->format('d.m.Y H:i'),
            ]);

            return [
                'status' => 'success',
                'verified' => true,
                'message' => "Erledigt! {$verified->title} ist jetzt am {$verifiedStart->format('d.m.Y')} um {$verifiedStart->format('H:i')} Uhr.",
                'meta' => ['title' => $verified->title, 'notes' => $verified->notes],
            ];
        }

        $summary = implode(', ', $changes) ?: 'aktualisiert';

        \Log::info('Action verified', [
            'type' => 'event_update',
            'event_id' => $verified->id,
            'verified' => true,
            'changes' => $summary,
        ]);

        return [
            'status' => 'success',
            'verified' => true,
            'message' => "Erledigt! \"{$verified->title}\" wurde {$summary}.",
            'meta' => ['title' => $verified->title, 'notes' => $verified->notes],
        ];
    }

    protected static function handleNoteUpdate(User $user, array $data): array
    {
        $search = $data['search'] ?? '';

        if (!$search) {
            return ['status' => 'failed', 'message' => 'Keine Notiz angegeben', 'meta' => []];
        }

        $note = Note::where('user_id', $user->id)
            ->where(function ($q) use ($search) {
                $q->where('title', 'like', '%' . $search . '%')
                  ->orWhere('content', 'like', '%' . $search . '%');
            })
            ->latest()
            ->first();

        if (!$note) {
            return ['status' => 'failed', 'message' => "Keine Notiz mit \"{$search}\" gefunden", 'meta' => ['search' => $search]];
        }

        if (!empty($data['content'])) {
            $note->content = $note->content
                ? $note->content . "\n" . $data['content']
                : $data['content'];
        }

        if (!empty($data['title'])) {
            $note->title = $data['title'];
        }

        $note->save();

        // Verifikation
        $verified = Note::find($note->id);
        if (! $verified) {
            \Log::error('Action verify failed: note not found after update', ['note_id' => $note->id]);
            return ['status' => 'error', 'message' => 'Notiz konnte nicht aktualisiert werden.', 'meta' => []];
        }

        \Log::info('Action verified', ['type' => 'note_update', 'note_id' => $verified->id, 'verified' => true]);

        return [
            'status' => 'success',
            'verified' => true,
            'message' => "Erledigt! Notiz \"{$verified->title}\" wurde aktualisiert.",
            'meta' => ['title' => $verified->title, 'content' => $verified->content],
        ];
    }

    protected static function handleTaskUpdate(User $user, array $data): array
    {
        $search = $data['search'] ?? '';

        if (!$search) {
            return ['status' => 'failed', 'message' => 'Keine Aufgabe angegeben', 'meta' => []];
        }

        $task = Task::where('user_id', $user->id)
            ->where('title', 'like', '%' . $search . '%')
            ->whereNull('completed_at')
            ->latest()
            ->first();

        if (!$task) {
            return ['status' => 'failed', 'message' => "Keine Aufgabe mit \"{$search}\" gefunden", 'meta' => ['search' => $search]];
        }

        if (!empty($data['title'])) {
            $task->title = $data['title'];
        }

        if (!empty($data['description'])) {
            $task->description = $task->description
                ? $task->description . "\n" . $data['description']
                : $data['description'];
        }

        if (!empty($data['status'])) {
            $task->status = $data['status'];
            if ($data['status'] === 'done') {
                $task->completed_at = now();
            }
        }

        if (!empty($data['priority'])) {
            $task->priority = $data['priority'];
        }

        $expectedStatus = $data['status'] ?? null;
        $task->save();

        // Verifikation
        $verified = Task::find($task->id);
        if (! $verified) {
            \Log::error('Action verify failed: task not found after update', ['task_id' => $task->id]);
            return ['status' => 'error', 'message' => 'Aufgabe konnte nicht aktualisiert werden.', 'meta' => []];
        }

        if ($expectedStatus && $verified->status !== $expectedStatus) {
            \Log::error('Action verify failed: task status mismatch', [
                'task_id' => $task->id,
                'expected' => $expectedStatus,
                'actual' => $verified->status,
            ]);
            return ['status' => 'error', 'message' => 'Aufgabe konnte nicht aktualisiert werden.', 'meta' => []];
        }

        $statusText = $expectedStatus === 'done' ? 'als erledigt markiert' : 'aktualisiert';

        \Log::info('Action verified', ['type' => 'task_update', 'task_id' => $verified->id, 'verified' => true]);

        return [
            'status' => 'success',
            'verified' => true,
            'message' => "Erledigt! \"{$verified->title}\" wurde {$statusText}.",
            'meta' => ['title' => $verified->title],
        ];
    }

    protected static function handleContact(User $user, array $data): array
    {
        $name = $data['name'] ?? null;

        if (!$name) {
            return ['status' => 'failed', 'message' => 'Kein Name angegeben', 'meta' => []];
        }

        $type = $data['type'] ?? 'sonstiges';
        if (!in_array($type, Contact::TYPES)) {
            $type = 'sonstiges';
        }

        $contact = Contact::create([
            'user_id' => $user->id,
            'name'    => $name,
            'email'   => $data['email'] ?? null,
            'phone'   => $data['phone'] ?? null,
            'type'    => $type,
            'notes'   => $data['notes'] ?? null,
        ]);

        Activity::log(
            $user->id,
            Activity::TYPE_CONTACT_CREATED,
            Activity::localizedTitle('contact_created_assistant', $user->locale ?? 'de'),
            $contact->name,
        );

        // Verifikation
        $verified = Contact::find($contact->id);
        if (! $verified) {
            \Log::error('Action verify failed: contact not found after create', ['contact_id' => $contact->id]);
            return ['status' => 'error', 'message' => 'Kontakt konnte nicht erstellt werden. Bitte nochmal versuchen.', 'meta' => []];
        }

        \Log::info('Action verified', ['type' => 'contact', 'contact_id' => $verified->id, 'verified' => true]);

        return [
            'status' => 'success',
            'verified' => true,
            'message' => "Erledigt! Kontakt \"{$verified->name}\" wurde angelegt.",
            'meta' => [
                'title' => $verified->name,
                'type' => $verified->typeLabel(),
                'phone' => $verified->phone,
                'email' => $verified->email,
            ],
        ];
    }

    /**
     * Kontakt suchen (fuzzy).
     * Gibt zurück: Contact | null | array von Contacts (bei Mehrdeutigkeit)
     */
    protected static function findContact(User $user, string $search): Contact|array|null
    {
        if (!$search) return null;

        $search = trim($search);
        $allContacts = Contact::where('user_id', $user->id)->get();

        if ($allContacts->isEmpty()) return null;

        $searchLower = mb_strtolower($search);
        $searchWords = preg_split('/\s+/', $searchLower);

        // Matching-Funktion: sammelt alle passenden Kontakte einer Stufe
        $matchMany = function ($allContacts, callable $matcher) {
            $matches = $allContacts->filter($matcher)->values();
            return $matches->isEmpty() ? null : $matches;
        };

        // 1. Exakter Wort-Match (Suchwort stimmt mit einem Namens-Teil exakt überein)
        $matches = $matchMany($allContacts, function ($c) use ($searchWords) {
            $nameParts = preg_split('/\s+/', mb_strtolower($c->name));
            foreach ($searchWords as $word) {
                if (in_array($word, $nameParts, true)) return true;
            }
            return false;
        });
        if ($matches && $matches->count() === 1) return $matches->first();
        if ($matches && $matches->count() > 1) return $matches->all();

        // 2. Voller Suchstring als Substring im Namen
        $matches = $matchMany($allContacts, fn($c) =>
            str_contains(mb_strtolower($c->name), $searchLower)
            || ($c->email && str_contains(mb_strtolower($c->email), $searchLower))
        );
        if ($matches && $matches->count() === 1) return $matches->first();
        if ($matches && $matches->count() > 1) return $matches->all();

        // 3. Wort-basiert
        $matches = $matchMany($allContacts, function ($c) use ($searchWords) {
            $name = mb_strtolower($c->name);
            foreach ($searchWords as $word) {
                if (mb_strlen($word) >= 2 && str_contains($name, $word)) return true;
            }
            return false;
        });
        if ($matches && $matches->count() === 1) return $matches->first();
        if ($matches && $matches->count() > 1) return $matches->all();

        // 4. Progressiv kürzen
        for ($cut = 1; $cut <= 3; $cut++) {
            $shortened = mb_substr($searchLower, 0, -$cut);
            if (mb_strlen($shortened) < 2) break;

            $matches = $matchMany($allContacts, fn($c) =>
                str_contains(mb_strtolower($c->name), $shortened)
            );
            if ($matches && $matches->count() === 1) return $matches->first();
            if ($matches && $matches->count() > 1) return $matches->all();
        }

        // 5. SOUNDEX
        $matches = $matchMany($allContacts, function ($c) use ($searchWords) {
            $nameParts = preg_split('/\s+/', $c->name);
            foreach ($searchWords as $word) {
                if (mb_strlen($word) < 2) continue;
                $sx = soundex($word);
                foreach ($nameParts as $part) {
                    if (soundex($part) === $sx) return true;
                }
            }
            return false;
        });
        if ($matches && $matches->count() === 1) return $matches->first();
        if ($matches && $matches->count() > 1) return $matches->all();

        // 6. Levenshtein
        $scored = [];
        foreach ($allContacts as $c) {
            $nameParts = preg_split('/\s+/', mb_strtolower($c->name));
            foreach ($nameParts as $part) {
                foreach ($searchWords as $word) {
                    $dist = levenshtein($word, $part);
                    $threshold = max(1, (int) floor(mb_strlen($word) * 0.4));
                    if ($dist <= $threshold) {
                        $scored[$c->id] = ['contact' => $c, 'dist' => $dist];
                    }
                }
            }
        }

        if (count($scored) === 1) return array_values($scored)[0]['contact'];
        if (count($scored) > 1) return array_map(fn($s) => $s['contact'], array_values($scored));

        return null;
    }

    protected static function handleEmail(User $user, array $data): array
    {
        $contactSearch = $data['contact'] ?? '';
        $eventSearch = $data['event'] ?? '';
        $subject = $data['subject'] ?? null;
        $message = $data['message'] ?? '';

        // Kontakt suchen (fuzzy)
        $result = self::findContact($user, $contactSearch);

        // Mehrdeutig: mehrere Treffer → nachfragen
        if (is_array($result)) {
            $names = array_map(fn($c) => $c->name, $result);
            return [
                'status' => 'ambiguous',
                'message' => 'Ich habe mehrere Kontakte gefunden: ' . implode(', ', $names) . '. Welchen meinst du?',
                'meta' => ['candidates' => $names],
            ];
        }

        $contact = $result;
        $toEmail = $contact?->email ?? ($data['email'] ?? null);
        $toName = $contact?->name ?? ($data['name'] ?? 'Empfänger');

        if (!$toEmail) {
            return [
                'status' => 'failed',
                'message' => $contact
                    ? "Kontakt \"{$contact->name}\" hat keine E-Mail-Adresse"
                    : "Kein Kontakt mit \"{$contactSearch}\" gefunden",
                'meta' => [],
            ];
        }

        // Event suchen (optional, für Terminerinnerung)
        $event = null;
        if ($eventSearch) {
            $event = Event::where('user_id', $user->id)
                ->where('title', 'like', '%' . $eventSearch . '%')
                ->where('starts_at', '>=', now()->subDay())
                ->orderBy('starts_at')
                ->first();
        }

        $tz = $user->timezone ?? 'UTC';

        // Meta für Template
        $meta = [
            'sender_name' => $user->name,
            'recipient_name' => $toName,
            'message' => $message,
        ];

        if ($event) {
            $meta['event_title'] = $event->title;
            $meta['event_date'] = $event->starts_at->setTimezone($tz)->format('d.m.Y');
            $meta['event_time'] = $event->starts_at->setTimezone($tz)->format('H:i');
            $meta['event_end'] = $event->ends_at?->setTimezone($tz)->format('H:i');
            $meta['event_notes'] = $event->notes;
            $subject = $subject ?? "Terminerinnerung: {$event->title}";
        }

        $template = $event ? 'agent.reminder' : 'agent.message';
        $subject = $subject ?? 'Nachricht von ' . $user->name;

        MailService::queue(
            to: $toEmail,
            template: $template,
            meta: $meta,
            subject: $subject,
            userId: $user->id,
        );

        return [
            'status' => 'success',
            'message' => "E-Mail an {$toName} gesendet",
            'meta' => [
                'title' => "E-Mail an {$toName}",
                'to' => $toEmail,
                'subject' => $subject,
            ],
        ];
    }

    protected static function handleUnknown(array $parsed): array
    {
        return [
            'status' => 'failed',
            'message' => 'Nicht verstanden',
            'meta' => $parsed,
        ];
    }
}
