<?php

namespace App\Services;

use App\Models\EventDurationStat;
use App\Models\EventKeyword;

class DurationLearningService
{
    protected array $keywordCache = [];

    /*
    |--------------------------------------------------------------------------
    | LEARN
    |--------------------------------------------------------------------------
    */

    public function learn(string $userId, string $title, int $duration): void
    {
        $keyword = $this->resolveKeyword($title, $userId);

        // 👉 Schutz gegen Müll
        if (
            !$keyword ||
            in_array($keyword, ['termin', 'machen', 'gehen']) ||
            $duration < 5 ||
            $duration > 600
        ) {
            return;
        }

        $stat = EventDurationStat::firstOrNew([
            'user_id' => $userId,
            'keyword' => $keyword,
        ]);

        if (!$stat->exists) {
            $stat->avg_duration = $duration;
            $stat->count = 1;
            $stat->save();
            return;
        }

        // 👉 stabiler Durchschnitt
        $stat->avg_duration = round(
            ($stat->avg_duration * 0.7) + ($duration * 0.3)
        );

        $stat->count += 1;
        $stat->save();
    }

    /*
    |--------------------------------------------------------------------------
    | GET
    |--------------------------------------------------------------------------
    */

    public function get(string $userId, string $title): ?int
    {
        $keyword = $this->resolveKeyword($title, $userId);
        if (!$keyword) return null;

        return EventDurationStat::where('user_id', $userId)
            ->where('keyword', $keyword)
            ->where(function ($q) {
                $q->where('count', '>=', 2)
                    ->orWhere('avg_duration', '<=', 30);
            })
            ->value('avg_duration');
    }

    /*
    |--------------------------------------------------------------------------
    | KEYWORD RESOLUTION
    |--------------------------------------------------------------------------
    */

    protected function resolveKeyword(string $title, string $userId): ?string
    {
        $normalized = $this->normalize($title);

        $cacheKey = $userId . ':' . $normalized;

        if (isset($this->keywordCache[$cacheKey])) {
            return $this->keywordCache[$cacheKey];
        }

        // 👉 DB Lookup
        $existing = EventKeyword::where('user_id', $userId)
            ->where('original', $normalized)
            ->first();

        if ($existing) {
            return $this->keywordCache[$cacheKey] = $existing->keyword;
        }

        // 👉 Local Extraction
        $keyword = $this->extractKeyword($normalized);

        // 👉 AI fallback (kontrolliert)
        if ((!$keyword || strlen($keyword) < 4) && str_word_count($title) > 2) {
            $keyword = $this->askAIForKeyword($title);
        }

        // 👉 sanitize
        $keyword = $this->sanitizeKeyword($keyword);

        // 👉 speichern
        if ($keyword && strlen($keyword) >= 3) {
            EventKeyword::updateOrCreate(
                [
                    'user_id' => $userId,
                    'original' => $normalized,
                ],
                [
                    'keyword' => $keyword,
                ]
            );
        }

        return $this->keywordCache[$cacheKey] = $keyword;
    }

    /*
    |--------------------------------------------------------------------------
    | NORMALIZE
    |--------------------------------------------------------------------------
    */

    protected function normalize(string $text): string
    {
        $text = strtolower($text);

        $text = preg_replace('/[^a-z0-9äöüß\s]/u', '', $text);
        $text = preg_replace('/\s+/', ' ', $text);

        return trim($text);
    }

    /*
    |--------------------------------------------------------------------------
    | EXTRACT KEYWORD (LOCAL)
    |--------------------------------------------------------------------------
    */

    protected function extractKeyword(string $text): ?string
    {
        $words = explode(' ', $text);

        $stopwords = [
            'der','die','das','und','oder','von','im','am','um','zu',
            'ein','eine','einen','mit','für','den','dem'
        ];

        $blacklist = ['gehen','machen','holen','fahren'];

        $filtered = array_filter($words, function ($word) use ($stopwords, $blacklist) {
            return strlen($word) > 3
                && !in_array($word, $stopwords)
                && !in_array($word, $blacklist);
        });

        if (empty($filtered)) {
            return null;
        }

        $filtered = array_values($filtered);

        // 👉 priorisierte Begriffe
        $priority = ['paket','arzt','friseur','meeting','lieferung','termin'];

        foreach ($priority as $p) {
            if (in_array($p, $filtered)) {
                return $p;
            }
        }

        return $filtered[0] ?? null;
    }

    /*
    |--------------------------------------------------------------------------
    | AI FALLBACK
    |--------------------------------------------------------------------------
    */

    protected function askAIForKeyword(string $title): string
    {
        try {
            $response = app(OpenAIService::class)->chat([
                [
                    'role' => 'system',
                    'content' => 'Extrahiere EIN generisches Keyword für diesen Termin (z.B. "friseur", "paket", "arzt"). Nur ein Wort.'
                ],
                [
                    'role' => 'user',
                    'content' => $title
                ]
            ]);

            return $this->sanitizeKeyword($response);

        } catch (\Throwable $e) {
            return $this->extractKeyword($this->normalize($title)) ?? 'termin';
        }
    }

    /*
    |--------------------------------------------------------------------------
    | SANITIZE
    |--------------------------------------------------------------------------
    */

    protected function sanitizeKeyword(?string $text): string
    {
        if (!$text) return 'termin';

        $text = strtolower(trim($text));

        $text = explode(' ', $text)[0];
        $text = preg_replace('/[^a-z0-9äöüß]/u', '', $text);

        return (strlen($text) >= 3) ? $text : 'termin';
    }
}
