<?php
/**
 * سودانا — Cache Layer v21
 * يمنع AI calls المتكررة — يوفر ~55% من التكاليف
 */
class CacheLayer {

    private static function normalize(string $q): string {
        $q = mb_strtolower(trim($q));
        // M2 FIX: Remove Arabic diacritics (tashkeel) for better cache hits
        $q = preg_replace('/[\x{064B}-\x{065F}]/u', '', $q) ?? $q;
        $map = ['عايز'=>'أريد','ابغى'=>'أريد','ولدي'=>'طفلي','ابني'=>'طفلي',
                'بنتي'=>'طفلتي','شنو'=>'ما','وين'=>'أين','زول'=>'شخص',
                'ياخي'=>'يا أخي','منو'=>'من'];
        foreach ($map as $d=>$s) $q = str_replace($d, $s, $q);
        $q = preg_replace('/[^\p{Arabic}\p{L}\d\s]/u', ' ', $q);
        return preg_replace('/\s+/', ' ', trim($q));
    }

    public static function makeKey(string $q, string $service = 'general', string $lang = 'ar'): string {
        $normalized = self::normalize($q);
        return hash('sha256', $normalized . '|' . $service . '|' . $lang);
    }

    public static function read(string $q, string $service = 'general'): ?string {
        try {
            $key = self::makeKey($q, $service);
            $st = db()->prepare(
                'SELECT response FROM ai_cache
                 WHERE cache_key = ? AND expires_at > NOW() AND is_valid = 1
                 LIMIT 1'
            );
            $st->execute([$key]);
            $row = $st->fetch();
            if ($row) {
                // Increment hits asynchronously
                try {
                    db()->prepare('UPDATE ai_cache SET hits=hits+1, last_hit_at=NOW() WHERE cache_key=?')
                        ->execute([$key]);
                } catch (Throwable $ignored) {}
                return $row['response'];
            }
        } catch (Throwable $e) {
            error_log('[CacheLayer::read] ' . $e->getMessage());
        }
        return null;
    }

    public static function write(string $q, string $response, string $service, string $model = 'gemini'): bool {
        if (!self::isCacheable($q, $service)) return false;
        try {
            $key = self::makeKey($q, $service);
            $semanticKey = self::makeSemanticKey($q);
            $ttl = self::getTTL($service);
            $expires = date('Y-m-d H:i:s', time() + $ttl);
            db()->prepare(
                'INSERT INTO ai_cache (cache_key, semantic_key, service, response, response_source, expires_at)
                 VALUES (?, ?, ?, ?, ?, ?)
                 ON DUPLICATE KEY UPDATE
                   response=VALUES(response), expires_at=VALUES(expires_at),
                   hits=hits+1, last_hit_at=NOW()'
            )->execute([$key, $semanticKey, $service, $response, $model, $expires]);
            return true;
        } catch (Throwable $e) {
            error_log('[CacheLayer::write] ' . $e->getMessage());
            return false;
        }
    }

    private static function isCacheable(string $q, string $service): bool {
        // Time-sensitive: never cache
        if (preg_match('/اليوم|الآن|هذه الساعة|الساعة الحالية/ui', $q)) return false;
        // Location-specific with "near me"
        if (preg_match('/قريب.*مني|قريبة|بالقرب/ui', $q) && $service === 'pharmacy') return false;
        // Emergency
        if (preg_match('/طوارئ|999|نزيف|تشنج/ui', $q)) return false;
        // Events (dynamic)
        if ($service === 'events') return false;
        // Live community feed
        if ($service === 'community' && preg_match('/منشور|بوست/ui', $q)) return false;
        return true;
    }

    private static function makeSemanticKey(string $q): string {
        $q = self::normalize($q);
        // Remove stop words
        $stopWords = ['في','من','على','هو','هي','أن','إن','كان','يكون','مع','إلى','عن','كيف','ما','هل','هذا'];
        $words = explode(' ', $q);
        $keywords = array_filter($words, fn($w) => mb_strlen($w) > 2 && !in_array($w, $stopWords));
        sort($keywords);
        return mb_substr(implode('_', array_slice($keywords, 0, 5)), 0, 150);
    }

    private static function getTTL(string $service): int {
        return match($service) {
            'academy'      => 86400 * 30,   // 30 days
            'legal'        => 86400 * 30,
            'business'     => 86400 * 14,   // 14 days
            'productivity' => 86400 * 14,
            'medical'      => 86400 * 7,    // 7 days
            'tech'         => 86400 * 7,
            default        => 86400 * 7,
        };
    }

    public static function cleanup(): void {
        try { db()->exec('DELETE FROM ai_cache WHERE expires_at < NOW()'); }
        catch (Throwable $ignored) {}
    }
}
