<?php

namespace App\Services;

use App\Models\Contact;
use App\Models\Event;
use App\Models\Note;
use App\Models\Task;
use App\Models\User;
use Carbon\Carbon;

/**
 * Einzige Quelle für den "KALENDER & DATEN"-Block, den Aria im System-Prompt
 * bekommt. Web (Livewire) und API (Controller) rufen denselben Service,
 * damit die AI auf beiden Plattformen identischen Kontext sieht.
 */
class AgentContextService
{
    public function build(User $user): string
    {
        $tz = $user->timezone ?? 'Europe/Berlin';
        $now = Carbon::now($tz);
        $todayStartLocal = $now->copy()->startOfDay();
        $weekEndLocal = $now->copy()->addDays(7)->endOfDay();
        $todayStartUtc = $todayStartLocal->copy()->utc();
        $weekEndUtc = $weekEndLocal->copy()->utc();

        $dayNames = ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'];

        $lines = [];

        // Tagesreferenz (AI ordnet Wochentage korrekt zu)
        $lines[] = 'TAGE:';
        for ($i = 0; $i < 7; $i++) {
            $day = $now->copy()->addDays($i);
            $label = match ($i) {
                0 => ' (heute)',
                1 => ' (morgen)',
                default => '',
            };
            $lines[] = "- {$dayNames[$day->dayOfWeek]} = {$day->format('d.m.Y')}{$label}";
        }

        // Termine: laufend/kommend innerhalb 7 Tage
        $events = Event::where('user_id', $user->id)
            ->where(function ($q) use ($todayStartUtc, $weekEndUtc) {
                $q->whereBetween('starts_at', [$todayStartUtc, $weekEndUtc])
                  ->orWhere(function ($q2) use ($todayStartUtc) {
                      $q2->where('starts_at', '<', $todayStartUtc)
                         ->where('ends_at', '>=', $todayStartUtc);
                  });
            })
            ->orderBy('starts_at')
            ->limit(30)
            ->get();

        if ($events->isNotEmpty()) {
            $lines[] = "\nTERMINE (heute + 7 Tage):";
            foreach ($events as $e) {
                $start = $e->starts_at->copy()->setTimezone($tz);
                $end = $e->ends_at?->copy()->setTimezone($tz);
                $isMultiDay = $end && $start->toDateString() !== $end->toDateString();

                if ($isMultiDay) {
                    $totalDays = $start->copy()->startOfDay()->diffInDays($end->copy()->startOfDay()) + 1;
                    $cursor = $start->copy()->startOfDay();
                    $dayNum = 1;
                    while ($cursor->lte($end->copy()->startOfDay())) {
                        if ($cursor->gte($todayStartLocal) && $cursor->lte($weekEndLocal)) {
                            $dn = $dayNames[$cursor->dayOfWeek] ?? '';
                            if ($e->is_all_day) {
                                $timeInfo = 'Ganztägig';
                            } elseif ($dayNum === 1) {
                                $timeInfo = "ab {$start->format('H:i')}";
                            } elseif ($dayNum === $totalDays) {
                                $timeInfo = "bis {$end->format('H:i')}";
                            } else {
                                $timeInfo = 'ganztägig';
                            }
                            $lines[] = "- [{$e->id}] {$dn} {$cursor->format('d.m.')} {$timeInfo} {$e->title} (Tag {$dayNum} von {$totalDays})";
                        }
                        $cursor->addDay();
                        $dayNum++;
                    }
                } else {
                    $lines[] = '- ' . $this->formatEvent($e, $tz, $dayNames);
                }
            }
        } else {
            $lines[] = "\nTERMINE: Keine Termine.";
        }

        // Notizen
        $notes = Note::where('user_id', $user->id)
            ->latest()
            ->limit(5)
            ->get();

        if ($notes->isNotEmpty()) {
            $lines[] = "\nNOTIZEN:";
            foreach ($notes as $n) {
                $label = $n->title ?: mb_substr($n->content, 0, 50);
                $lines[] = "- [{$n->id}] {$label}";
            }
        }

        // Offene Aufgaben
        $tasks = Task::where('user_id', $user->id)
            ->whereNull('completed_at')
            ->orderBy('due_at')
            ->limit(8)
            ->get();

        if ($tasks->isNotEmpty()) {
            $lines[] = "\nOFFENE AUFGABEN:";
            foreach ($tasks as $t) {
                $lines[] = "- [{$t->id}] {$t->title}";
            }
        }

        // Kontakte
        $contacts = Contact::where('user_id', $user->id)
            ->orderBy('name')
            ->limit(50)
            ->get();

        if ($contacts->isNotEmpty()) {
            $lines[] = "\nKONTAKTE:";
            foreach ($contacts as $c) {
                $email = $c->email ? " ({$c->email})" : '';
                $lines[] = "- [{$c->id}] {$c->name}{$email}";
            }
        } else {
            $lines[] = "\nKONTAKTE: Keine Kontakte vorhanden.";
        }

        return implode("\n", $lines);
    }

    private function formatEvent(Event $e, string $tz, array $dayNames): string
    {
        $start = $e->starts_at->setTimezone($tz);
        $end = $e->ends_at?->setTimezone($tz);
        $dayName = $dayNames[$start->dayOfWeek] ?? '';

        if ($e->is_all_day) {
            return "[{$e->id}] {$dayName} {$start->format('d.m.')} Ganztägig {$e->title}";
        }

        $time = $end ? "{$start->format('H:i')}-{$end->format('H:i')}" : $start->format('H:i');
        return "[{$e->id}] {$dayName} {$start->format('d.m.')} {$time} {$e->title}";
    }
}
