<?php
/**
 * سودانا — IntentDecomposer v1 (Phase 1 Orchestrator)
 *
 * Detects up to 2 intents in a single query.
 * Routes each to its domain independently.
 * Merges responses into unified output.
 *
 * Design constraints:
 *  - No new DB tables
 *  - No external calls
 *  - Single file, zero dependencies beyond existing engines
 *  - Activated by Gateway only when confidence < 0.85 (ambiguous queries)
 *
 * Integration point in Gateway::handle():
 *   After IE returns null or low confidence, BEFORE the AI call.
 */
class IntentDecomposer {

    // Minimum IE confidence to accept an intent as valid
    const MIN_CONFIDENCE = 0.45;

    // Separator patterns that signal multi-intent (Arabic + English)
    private static array $MULTI_INTENT_SIGNALS = [
        '/(?:و|وأيضاً|وكمان|وبعدين|بالإضافة)\s+(?:أريد|أبغى|عايز|كيف|ما|هل)/ui',
        '/(?:first|also|and also|plus)\s+(?:i want|how|what|is)/ui',
        // Price + service pattern (most common: "كم تكلفة + ما الإجراءات")
        '/(?:كم.*تكلف|ما.*سعر|كم.*يكلف).{5,50}(?:وكيف|وماذا|وما)/ui',
        // Medical + financial (second most common)
        '/(?:أعراض|ألم|مرض).{5,80}(?:تكلف|سعر|دفع|فلوس)/ui',
        '/(?:تكلف|سعر|دفع).{5,80}(?:أعراض|ألم|مرض|طبيب)/ui',
    ];

    /**
     * Attempt to decompose query into 2 intents.
     * Returns null if query is single-intent (caller should proceed normally).
     *
     * @return array|null {intents: [{sector, answer, confidence}], merged: string} or null
     */
    public static function decompose(string $q, array $ctx = []): ?array {
        // Step 1: Check if this looks multi-intent
        if (!self::isMultiIntent($q)) {
            return null;
        }

        // Step 2: Split into candidate sub-queries
        $parts = self::splitIntents($q);
        if (count($parts) < 2) {
            return null;
        }

        // Step 3: Run IE on each part independently
        $intents = [];
        foreach ($parts as $part) {
            $part = trim($part);
            if (mb_strlen($part) < 4) continue;

            $ie = InferenceEngine::infer($part, $ctx);
            if ($ie && $ie['confidence'] >= self::MIN_CONFIDENCE) {
                $intents[] = [
                    'query'      => $part,
                    'sector'     => $ie['sector'] ?? 'general',
                    'answer'     => $ie['answer'] ?? '',
                    'confidence' => $ie['confidence'],
                    'layer'      => $ie['layer'] ?? 'L2',
                ];
            }
        }

        // Step 4: Need at least 2 valid intents with DIFFERENT sectors to merge
        if (count($intents) < 2) {
            return null;
        }

        // Deduplicate by sector — keep highest confidence per sector
        $bySector = [];
        foreach ($intents as $intent) {
            $s = $intent['sector'];
            if (!isset($bySector[$s]) || $intent['confidence'] > $bySector[$s]['confidence']) {
                $bySector[$s] = $intent;
            }
        }

        if (count($bySector) < 2) {
            return null; // Same sector twice — not a real multi-intent
        }

        // Cap at 2 intents: take top 2 by confidence
        usort($bySector, fn($a, $b) => $b['confidence'] <=> $a['confidence']);
        $topTwo = array_slice(array_values($bySector), 0, 2);

        // Step 5: Build merged response
        $merged = self::mergeResponses($topTwo, $q);

        return [
            'multi_intent' => true,
            'intents'      => $topTwo,
            'merged'       => $merged,
            'sectors'      => array_column($topTwo, 'sector'),
        ];
    }

    /**
     * Split query into intent fragments using conjunction patterns.
     */
    private static function splitIntents(string $q): array {
        // Split on Arabic conjunctions that signal new intent
        $split = preg_split(
            '/(?:\s+(?:و|وأيضاً|وكمان|وبعدين|بالإضافة لذلك|also|and also)\s+)/ui',
            $q,
            2 // max 2 parts — we handle max 2 intents
        );

        if (!$split || count($split) < 2) {
            // Try splitting on question marks (two questions in one)
            $split = preg_split('/[؟?](?!\s*$)/u', $q, 2);
            if ($split) {
                $split = array_filter($split, fn($s) => mb_strlen(trim($s)) > 3);
                $split = array_values($split);
            }
        }

        return $split ?: [$q];
    }

    /**
     * Heuristic check: is this likely a multi-intent query?
     */
    private static function isMultiIntent(string $q): bool {
        // Too short to be multi-intent
        if (mb_strlen($q) < 20) return false;

        foreach (self::MULTI_INTENT_SIGNALS as $pattern) {
            if (preg_match($pattern, $q)) return true;
        }

        // Two question marks = two questions
        if (preg_match_all('/[؟?]/u', $q) >= 2) return true;

        return false;
    }

    /**
     * Merge two intent answers into a single coherent response.
     * Uses section headers to separate answers by domain.
     */
    private static function mergeResponses(array $intents, string $originalQ): string {
        if (count($intents) === 0) return '';
        if (count($intents) === 1) return $intents[0]['answer'];

        $a = $intents[0];
        $b = $intents[1];

        // Domain display names (Arabic)
        $domainNames = [
            'medical'     => '🏥 الإجابة الطبية',
            'finance'     => '💰 الإجابة المالية',
            'legal'       => '⚖️ الإجابة القانونية',
            'education'   => '📚 الإجابة التعليمية',
            'agriculture' => '🌾 الإجابة الزراعية',
            'career'      => '💼 الإجابة المهنية',
            'business'    => '📊 الإجابة التجارية',
            'platform'    => '📱 معلومات المنصة',
            'general'     => '💬 الإجابة',
        ];

        $aLabel = $domainNames[$a['sector']] ?? ('💬 ' . $a['sector']);
        $bLabel = $domainNames[$b['sector']] ?? ('💬 ' . $b['sector']);

        return "{$aLabel}:\n{$a['answer']}\n\n{$bLabel}:\n{$b['answer']}";
    }
}
