<?php
/**
 * api/gemini.php - Master AI (COMMANDER EDITION)
 * * LOG FIX:
 * 1. [AGRESIVITAS IOT] Menambahkan instruksi agar kata 'bisa', 'tolong', 'coba' dianggap PERINTAH MUTLAK.
 * 2. [FUZZY MATCH] AI diperintahkan mencocokkan kata 'lampu' dengan ID perangkat yang paling mirip.
 * 3. [MEMORY & SECURITY] Fitur ingatan dan keamanan tetap aktif.
 */

session_start();
include '../config/database.php';
include '../llm/api/koneksi_gemini.php'; 

header('Content-Type: application/json');
error_reporting(0);

// --- [SECURITY CHECK & GUEST LIMITER] ---
$is_guest = false;
$user_id = 0;

if (!isset($_SESSION['user_id'])) {
    $is_guest = true;
    
    if (!isset($_SESSION['guest_count'])) {
        $_SESSION['guest_count'] = 0;
    }
    
    if ($_SESSION['guest_count'] >= 5) {
        http_response_code(403);
        echo json_encode(['error' => 'Limit trial habis. Silakan registrasi untuk melanjutkan.']);
        exit;
    }
    
    // Tambah hitungan setiap kali tamu mengirim pesan
    $_SESSION['guest_count']++;
} else {
    $user_id = $_SESSION['user_id'];
}

// --- [RATE LIMITING] ---
$limit_time = 60; // Batas waktu 1 menit
$max_requests = 15; // Maksimal 15 request per menit per user

if (!isset($_SESSION['rate_limit'])) {
    $_SESSION['rate_limit'] = ['count' => 1, 'start_time' => time()];
} else {
    if (time() - $_SESSION['rate_limit']['start_time'] < $limit_time) {
        if ($_SESSION['rate_limit']['count'] >= $max_requests) {
            http_response_code(429);
            echo json_encode(['error' => 'Sistem mendeteksi aktivitas tidak wajar. Harap tunggu 1 menit.']);
            exit;
        }
        $_SESSION['rate_limit']['count']++;
    } else {
        // Reset sesi jika sudah lewat 1 menit
        $_SESSION['rate_limit'] = ['count' => 1, 'start_time' => time()];
    }
}

// 1. CONFIG LOAD

$res      = mysqli_query($conn, "SELECT * FROM settings WHERE id = 1");
$cfg      = mysqli_fetch_assoc($res);
$g_model  = $cfg['gemini_model'] ?? 'gemini-1.5-flash';
$nama_app = $cfg['nama_aplikasi'] ?? 'AI Assistant';

// 2. INPUT HANDLER
$user_input = $_POST['pesan'] ?? '';
$mode       = $_POST['mode'] ?? 'cepat';
$session_id = $_POST['session_id'] ?? 'default_session'; // <--- Tangkap Session ID
$user_location = $_POST['user_location'] ?? ''; // <--- Tangkap GPS/Lokasi

date_default_timezone_set('Asia/Jakarta'); 
$waktu_sekarang = date('l, d F Y H:i:s T'); 

// --- [CHARACTER PERSONA HANDLER] ---
$char_key = $_POST['char_key'] ?? null;
$persona_prompt = "";
if ($char_key) {
    $q_char = mysqli_query($conn, "SELECT * FROM live_characters WHERE char_key = '$char_key'");
    if ($char_data = mysqli_fetch_assoc($q_char)) {
        $nama_app = $char_data['name'];
        $style = $char_data['speech_style'];
        
        $persona_prompt = "\n\nINSTRUKSI KEPRIBADIAN KHUSUS (WAJIB):";
        $persona_prompt .= "\n- Nama Anda sekarang adalah: $nama_app.";
        
        if ($style == 'manja') {
            $persona_prompt .= "\n- GAYA BICARA: MANJA & GEMAS. Gunakan bahasa yang imut, seperti adik atau pasangan yang manja.";
            $persona_prompt .= "\n- FILLER: Sering gunakan kata 'Waw', 'Oiya kak', 'Waduh', 'Ih gemes deh'.";
            $persona_prompt .= "\n- SIKAP: Sangat interaktif, sering memuji user, dan menawarkan bantuan dengan nada manja.";
        } elseif ($style == 'ramah') {
            $persona_prompt .= "\n- GAYA BICARA: RAMAH & SOPAN. Sangat menghargai user.";
            $persona_prompt .= "\n- FILLER: Gunakan kata 'Betul sekali kak', 'Oiya kak', 'Tentu kak'.";
            $persona_prompt .= "\n- SIKAP: Selalu menawarkan bantuan tambahan dan sangat solutif.";
        } elseif ($style == 'humoris') {
            $persona_prompt .= "\n- GAYA BICARA: HUMORIS & SANTAI. Suka bercanda dan tidak kaku.";
            $persona_prompt .= "\n- FILLER: Gunakan kata 'Waduh', 'Betul sekali kak', 'Hahaha, oiya kak'.";
            $persona_prompt .= "\n- SIKAP: Menyelipkan humor dalam jawaban, interaktif, dan asik diajak mengobrol.";
        } elseif ($style == 'formal') {
            $persona_prompt .= "\n- GAYA BICARA: FORMAL & BIJAK. Tenang, dewasa, dan terstruktur.";
            $persona_prompt .= "\n- FILLER: Gunakan kata 'Benar sekali', 'Sangat menarik', 'Izinkan saya membantu'.";
            $persona_prompt .= "\n- SIKAP: Memberikan saran yang bijaksana dan mendalam.";
        }
        
        $persona_prompt .= "\n- INTERAKTIF: Selalu akhiri jawaban dengan menawarkan bantuan lain atau bertanya hal yang relevan untuk memancing obrolan lebih lanjut (seperti Gemini Live).";
        
        // Tambahan Vision Context
        if ($gambar_live) {
            $persona_prompt .= "\n\nKONTEKS PENGLIHATAN (VISION):";
            $persona_prompt .= "\n- Anda sedang melihat feed kamera LIVE dari user.";
            $persona_prompt .= "\n- Jika user bertanya 'Apa yang kamu lihat?', 'Siapa saya?', atau hal lain terkait visual, deskripsikan dengan detail namun natural sesuai gaya bicara $style Bapak.";
            $persona_prompt .= "\n- Berikan komentar spontan tentang apa yang Anda lihat untuk membuat suasana lebih hidup.";
        }
    }
}

// --- [INTERCEPTOR: TUGAS BROADCAST (PROMPT STATIK)] ---
$clean_input_for_trigger = strtolower(trim($user_input));
if (!empty($clean_input_for_trigger)) {
    // Cari di database apakah user mengetikkan "trigger_prompt" dari guru
    $stmt_share = $conn->prepare("SELECT deskripsi_tugas FROM share_tugas WHERE trigger_prompt = ? LIMIT 1");
    if ($stmt_share) {
        $stmt_share->bind_param("s", $clean_input_for_trigger);
        $stmt_share->execute();
        $res_share = $stmt_share->get_result();
        
        if ($res_share->num_rows > 0) {
            // MANTAP! Ini adalah pemicu broadcast tugas.
            $data_share = $res_share->fetch_assoc();
            $ai_reply_tugas = $data_share['deskripsi_tugas'];
            $stmt_share->close();

            // Beri log riwayat chat ke tabel seperti biasa agar muncul di obrolan
            if (!$is_guest) {
                $stmt_log = $conn->prepare("INSERT INTO chat_history (user_id, session_id, user_message, ai_response) VALUES (?, ?, ?, ?)");
                if ($stmt_log) {
                    $stmt_log->bind_param("isss", $user_id, $session_id, $user_input, $ai_reply_tugas);
                    $stmt_log->execute();
                    $stmt_log->close();
                }
            }
            // Langsung keluarkan output tanpa memanggil LLM (Menghemat Token 100%)
            echo json_encode(['jawaban' => trim($ai_reply_tugas)]);
            exit;
        }
        $stmt_share->close();
    }
}

// --- [HELPER: SECURE FILE PARSER] ---
function extractTextFromFile($filePath, $mimeType, $originalName) {
    $ext = strtolower(pathinfo($originalName, PATHINFO_EXTENSION));
    $text = "";

    // File Teks Biasa
    if (in_array($ext, ['txt', 'csv', 'php', 'json', 'html', 'js', 'css', 'md'])) {
        return file_get_contents($filePath);
    }

    // File Word (.docx)
    if ($ext === 'docx') {
        $zip = new ZipArchive;
        // --- DI SINI PERUBAHANNYA ---
        if ($zip->open($filePath) === TRUE) {
            if (($index = $zip->locateName('word/document.xml')) !== false) {
                $xmlData = $zip->getFromIndex($index);
                $dom = new DOMDocument;
                
                if (\PHP_VERSION_ID < 80000) { $libxml_before = libxml_disable_entity_loader(true); }
                $dom->loadXML($xmlData, LIBXML_NOERROR | LIBXML_NOWARNING);
                if (\PHP_VERSION_ID < 80000) { libxml_disable_entity_loader($libxml_before); }
                
                $text = strip_tags($dom->saveXML());
            }
            $zip->close(); // Wajib ditutup setelah dibuka
        }
        return $text;
    }

    // File Excel (.xlsx)
    if ($ext === 'xlsx') {
        $zip = new ZipArchive;
        // --- DI SINI JUGA PERLU DITAMBAHKAN ---
        if ($zip->open($filePath) === TRUE) {
            // Excel menyimpan data teks di sharedStrings.xml
            if (($index = $zip->locateName('xl/sharedStrings.xml')) !== false) {
                $xmlData = $zip->getFromIndex($index);
                $text = strip_tags($xmlData);
            }
            $zip->close();
        }
        return $text;
    }
    
    return null; 
}


// --- [HELPER: WEB SCRAPER] ---
function scrapeUrlContent($target_url) {
    // Setting context agar tidak hang jika website down (timeout 7 detik)
    $ctx = stream_context_create(array(
        'http' => array(
            'timeout' => 7,
            'user_agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
        ),
        'ssl' => array(
            'verify_peer' => false,
            'verify_peer_name' => false
        )
    ));
    
    // Coba fetch isi URL secara aman
    $html_content = @file_get_contents($target_url, false, $ctx);
    
    if ($html_content !== false) {
        // Hapus tag script, style, head, dan navigasi agar konten lebih bersih
        $html_content = preg_replace('#<script(.*?)>(.*?)</script>#is', '', $html_content);
        $html_content = preg_replace('#<style(.*?)>(.*?)</style>#is', '', $html_content);
        $html_content = preg_replace('#<nav(.*?)>(.*?)</nav>#is', '', $html_content);
        $html_content = preg_replace('#<footer(.*?)>(.*?)</footer>#is', '', $html_content);
        
        // Ambil teks murni dan rapikan spasi
        $clean_web_text = strip_tags($html_content);
        $clean_web_text = preg_replace('/\s+/', ' ', $clean_web_text);
        
        // Batasi teks maksimal 15.000 karakter agar tidak overload token
        return substr(trim($clean_web_text), 0, 15000);
    }
    return null;
}

// 3. FILE HANDLER
$file_part = null; 
$file_text_context = ""; 

if (isset($_FILES['gambar'])) {
    $file_parts_array = [];
    $is_multi = is_array($_FILES['gambar']['name']);
    $count = $is_multi ? count($_FILES['gambar']['name']) : 1;
    
    if ($count > 10) {
        echo json_encode(['error' => 'Maksimal 10 file yang dapat diunggah sekaligus.']);
        exit;
    }
    
    // [TAMBAHAN KEAMANAN]: Validasi Ukuran Maksimal 25MB di Backend
    $total_size = 0;
    for ($i = 0; $i < $count; $i++) {
        $f_error = $is_multi ? $_FILES['gambar']['error'][$i] : $_FILES['gambar']['error'];
        if ($f_error !== UPLOAD_ERR_OK) continue;
        
        $f_size = $is_multi ? $_FILES['gambar']['size'][$i] : $_FILES['gambar']['size'];
        $total_size += $f_size;
    }
    
    if ($total_size > 25 * 1024 * 1024) {
        echo json_encode(['error' => 'Gagal diproses. Total ukuran file melebihi batas 25MB di server.']);
        exit;
    }

    for ($i = 0; $i < $count; $i++) {
        $f_error = $is_multi ? $_FILES['gambar']['error'][$i] : $_FILES['gambar']['error'];
        if ($f_error !== UPLOAD_ERR_OK) continue;
        
        $f_path = $is_multi ? $_FILES['gambar']['tmp_name'][$i] : $_FILES['gambar']['tmp_name'];
        $f_type = $is_multi ? $_FILES['gambar']['type'][$i] : $_FILES['gambar']['type'];
        $f_name = $is_multi ? $_FILES['gambar']['name'][$i] : $_FILES['gambar']['name'];
        
        $extracted_text = extractTextFromFile($f_path, $f_type, $f_name);

        if ($extracted_text) {
            $file_text_context .= "\n[ISI FILE: $f_name]:\n" . substr($extracted_text, 0, 30000) . "\n[AKHIR FILE]\n";
        } else {
            $data = file_get_contents($f_path);
            $base64 = base64_encode($data);
            $file_parts_array[] = ["inlineData" => ["mimeType" => $f_type, "data" => $base64]];
            if (strpos($f_type, 'pdf') !== false) {
                $file_text_context .= "\n[INFO]: User melampirkan file PDF ($f_name).\n";
            }
        }
    }
    
    if (count($file_parts_array) > 0) {
        $file_part = $file_parts_array; 
    }
}

// --- [LIVE VISION HANDLER] ---
$gambar_live = $_POST['gambar_live'] ?? null;
if ($gambar_live) {
    if (!$file_part) $file_part = [];
    $file_part[] = ["inlineData" => ["mimeType" => "image/jpeg", "data" => $gambar_live]];
}

// --- [SMART URL SCRAPER / SUMMARIZER] ---

// A. Scrape URLs provided by user in message
if (preg_match('/(https?:\/\/[^\s]+)/', $user_input, $url_matches)) {
    $target_url = $url_matches[1];
    $clean_web_text = scrapeUrlContent($target_url);
    if (!empty($clean_web_text)) {
        $file_text_context .= "\n\n[KONTEKS URL USER ($target_url)]:\n" . $clean_web_text . "\n[AKHIR KONTEN]\n\n";
    }
}

// B. Scrape Target URLs from Admin (Dynamic Reference)
if ($mode !== 'cepat') {
    $q_targets = mysqli_query($conn, "SELECT * FROM target_urls");
if ($q_targets && mysqli_num_rows($q_targets) > 0) {
    $user_q_low = strtolower($user_input);
    while ($t_url = mysqli_fetch_assoc($q_targets)) {
        $topic_low = strtolower($t_url['nama_url']);
        
        // Trigger: Jika nama topik disebut user ATAU user tanya 'trending/berita' dan topik mengandung kata tsb
        $is_match = (strpos($user_q_low, $topic_low) !== false);
        $is_general_trigger = (
            (strpos($user_q_low, 'trending') !== false && strpos($topic_low, 'trending') !== false) ||
            (strpos($user_q_low, 'berita') !== false && strpos($topic_low, 'berita') !== false) ||
            (strpos($user_q_low, 'update') !== false && strpos($topic_low, 'update') !== false) ||
            (strpos($user_q_low, 'informasi') !== false && strpos($topic_low, 'informasi') !== false) ||
            (strpos($user_q_low, 'presiden') !== false && strpos($topic_low, 'presiden') !== false) ||
            (strpos($user_q_low, 'negara') !== false && strpos($topic_low, 'negara') !== false)
        );

        if ($is_match || $is_general_trigger) {
            $web_text = scrapeUrlContent($t_url['alamat_url']);
            if (!empty($web_text)) {
                $file_text_context .= "\n\n[REFERENSI OTOMATIS: {$t_url['nama_url']} | SOURCE_URL: {$t_url['alamat_url']}]:\n" . $web_text . "\n[AKHIR REFERENSI]\n\n";
            }
        }
    }
}
}


// --- [SMART IOT CONTEXT - LOAD DEVICES DYNAMICALLY] ---
$list_perangkat_str = "TIDAK ADA PERANGKAT TERHUBUNG.";
$is_iot_intent = preg_match('/(nyala|mati|hidup|lampu|kipas|tv|ac|suhu|kunci|buka|tutup|perangkat)/i', $user_input);

if (!$is_guest && $is_iot_intent) {
    $stmt_iot = $conn->prepare("SELECT device_id, label, status, last_value FROM iot_devices WHERE user_id = ?");
    $stmt_iot->bind_param("i", $user_id);
    $stmt_iot->execute();
    $res_iot = $stmt_iot->get_result();

    if ($res_iot->num_rows > 0) {
        $devices_array = [];
        while ($row = $res_iot->fetch_assoc()) {
            $kondisi = ($row['last_value'] != '0' && $row['last_value'] != '') ? "Data: {$row['last_value']}" : (($row['status'] == 1) ? "STATUS: NYALA" : "STATUS: MATI");
            $devices_array[] = "- NAMA ALAT: '{$row['label']}' | ID_SISTEM: '{$row['device_id']}' | {$kondisi}";
        }
        $list_perangkat_str = implode("\n", $devices_array);
    }
    $stmt_iot->close();
}

// --- [HISTORY BUILDER] ---
$hist_ctx = "";
$chats = []; // <--- Inisialisasi kosong dulu di luar IF agar aman bagi TAMU

if (!$is_guest) { 
    $stmt_mem = $conn->prepare("SELECT user_message, ai_response FROM chat_history WHERE user_id = ? AND session_id = ? ORDER BY id DESC LIMIT 4");
    $stmt_mem->bind_param("is", $user_id, $session_id); // Gunakan "is" karena user_id adalah Integer
    $stmt_mem->execute();
    $res_mem = $stmt_mem->get_result();

    while($r = $res_mem->fetch_assoc()) {
        $chats[] = $r;
    }
    $stmt_mem->close();

    $current_chars = 0;
    $max_context_chars = 1200; // Dikurangi dari 2000 → hemat ~40% input token

    foreach(array_reverse($chats) as $c) {
        $clean_response = preg_replace('/<iot>.*?<\/iot>/', '', $c['ai_response']);
        $turn = "User: " . substr($c['user_message'], 0, 300) . "\nAI: " . substr($clean_response, 0, 400) . "\n---\n";
        
        if (($current_chars + strlen($turn)) < $max_context_chars) {
            $hist_ctx .= $turn;
            $current_chars += strlen($turn);
        } else { break; }
    }
}

// 4. PROMPT ENGINEERING (AGRESSIVE COMMANDER MODE)

$sys_prompt = "
PERAN:
Anda adalah $nama_app, AI cerdas.

IDENTITAS & BATASAN:
- Developer: Sikawarsito, S.Kom (Sebutkan hanya jika ditanya).
- Identitas: Sistem AI internal yang cerdas, empatik, dan solutif.
- Pantangan: JANGAN PERNAH menyebut diri Anda buatan Google/Meta/OpenAI/XIEQA LLM.

FORMATTING & VISUALISASI (PENTING):
Agar jawaban Anda mudah dibaca dan profesional seperti AI kelas dunia:
1. Gunakan **Bold** untuk poin penting.
2. Gunakan LIST (bullet points) untuk langkah-langkah.
3. Gunakan `Code Block` dengan syntax highlighting untuk koding.
4. Gunakan TABLE Markdown untuk data perbandingan.
5. Gunakan Header (###) untuk memisahkan topik panjang.

KONTEKS REAL-TIME:
- Waktu: $waktu_sekarang
- Lokasi Pengguna Saat Ini: " . ($user_location ?: "Tidak diketahui (Browser belum mengizinkan akses lokasi)") . "

GAYA KOMUNIKASI:
Gunakan Bahasa Indonesia yang luwes, tidak kaku, namun tetap profesional. Sesuaikan nada bicara dengan input user (jika user santai, ikut santai. Jika user formal, ikut formal).

DOKUMEN & TABEL (SANGAT PENTING):
- Jika Anda membuat sebuah tabel data, materi pelajaran, artikel, naskah, atau teks panjang yang terstruktur, Anda WAJIB menawarkan di akhir pesan: \"Apakah Anda ingin saya buatkan versi file (Excel/Word/PDF) untuk data ini agar bisa langsung diunduh?\"
- Jika User meminta \"buatkan excelnya\", \"buatkan pdfnya\", atau \"buatkan wordnya\" (baik untuk tabel maupun artikel), Anda WAJIB membungkus seluruh data/teks tersebut di dalam tag khusus berikut di akhir pesan:
  [GENERATE_FILE:word]Teks/Markdown Anda Di Sini[/GENERATE_FILE]
  (Ganti 'word' dengan 'excel' atau 'pdf'. PENTING: JANGAN letakkan tag ini di dalam Markdown Code Block / backticks (```). Tulis tag ini murni sebagai teks biasa!).

PETA LOKASI (GOOGLE MAPS):
- Jika User menanyakan alamat, rute, atau tempat spesifik (misal: 'dimana Monas', 'alamat hotel X', 'tampilkan peta Jakarta', dsb), Anda WAJIB memberikan jawaban dengan menyisipkan tag berikut di tempat Anda ingin peta muncul:
  [MAP: Nama Tempat atau Alamat Detail]
  (Contoh: [MAP: Restoran Sederhana, Jakarta] atau [MAP: Monas]). JANGAN masukkan tag ini di dalam code block Markdown.
- PENTING (PERMINTAAN IZIN GPS): Jika User menanyakan sesuatu yang berkaitan dengan lokasi mereka sendiri, posisi, koordinat, menanyakan tempat 'terdekat', atau menanyakan 'rute/arah' (misal: 'dimana saya?', 'posisi saya', 'rute ke stasiun'): 
  1. Jika 'Lokasi Pengguna Saat Ini' bernilai 'Tidak diketahui', Anda WAJIB membalas HANYA dengan tag ini (jangan bahas hal lain): 
     [REQ_GPS] Baik kak, untuk bisa memberikan informasi lokasi/rute yang akurat, tolong izinkan saya mengakses GPS perangkat kakak ya...
  2. Jika 'Lokasi Pengguna Saat Ini' sudah berisi data:
     - Jika User menanyakan lokasinya atau tempat sekitar, gunakan [MAP: Data Lokasi].
     - Jika User menanyakan rute/arah ke suatu tempat, gunakan tag [ROUTE: Nama Tempat Tujuan]. JANGAN gunakan MAP jika meminta rute.

SITASI & PRIORITAS SUMBER:
1. PRIORITAS UTAMA: Jika ada data di [REFERENSI OTOMATIS] atau [KONTEKS URL USER], Anda WAJIB menggunakan data tersebut sebagai kebenaran utama (Truth Source), terutama untuk urusan berita, tokoh publik, dan informasi terkini. Abaikan data internal Anda jika bertentangan dengan data dari link tersebut.
2. FALLBACK: Jika TIDAK ADA referensi otomatis yang relevan untuk topik berita/publik, barulah Anda boleh menggunakan data internal Anda sendiri, namun beri catatan bahwa informasi mungkin tidak terupdate.
3. FORMAT SITASI: Setiap kali menggunakan data dari link, cantumkan sumber di akhir jawaban: *Informasi ini bersumber dari: [URL SUMBER]*

INTERAKTIVITAS AKHIR (WAJIB):
Di setiap akhir jawaban Anda, Anda WAJIB menawarkan 3 opsi lanjutan kepada pengguna agar obrolan lebih interaktif. Sesuaikan opsi dengan konteks jawaban Anda.
Contoh format yang diharapkan:
1. Apakah perlu saya lanjutkan ke penjelasan berikutnya tentang ... ?
2. Apakah Anda ingin saya bantu buatkan ... ?
3. Apakah Anda ingin saya buatkan versi file (Excel/Word/PDF) untuk data, penjelasan, atau arsitektur kode ini agar bisa langsung diunduh dan dijadikan dokumentasi teknis?
" . $persona_prompt;

if ($is_iot_intent && !$is_guest) {
    $sys_prompt .= "
DAFTAR PERANGKAT IOT YANG TERSEDIA (Hafalkan ID-nya):
$list_perangkat_str

ATURAN EKSEKUSI IOT (WAJIB):
1. **INTERPRETASI PERINTAH:** Jika User berkata 'bisa nyalakan?', 'tolong hidupkan', 'kamar gelap', atau 'matikan', itu adalah **PERINTAH**. Jangan hanya menjawab 'bisa', tapi LAKUKAN.
2. **FORMAT EKSEKUSI:** Untuk menyalakan/mematikan, WAJIB outputkan kode rahasia di akhir jawaban: 
   - Nyalakan: <iot>ID_SISTEM|1</iot>
   - Matikan: <iot>ID_SISTEM|0</iot>
3. **PENCARIAN NAMA:** Jika user bilang 'Lampu', cari perangkat di daftar yang mengandung kata 'Lampu' (misal 'Lampu Kamar' atau 'Lampu Teras'). Pilih yang paling relevan.
4. **JANGAN MEMBANTAH:** Jika user minta nyalakan, langsung outputkan tag <iot> meskipun statusnya sudah nyala (untuk memastikan).

CONTOH KASUS:
User: 'Bisa nyalakan lampu kamar?'
Output Anda: 'Oke bos, lampu kamar saya nyalakan. <iot>lampu_kamar|1</iot>'

User: 'Matikan semua'
Output Anda: 'Siap, mematikan semua alat. <iot>lampu_kamar|0</iot> <iot>kipas|0</iot>'
";
}

// Mode Instruction — OPTIMIZED VERSION (hemat token, tapi Pro tetap berkelas)
switch ($mode) {

    case 'cepat':
        $mode_instr = "MODE: FAST RESPONDER. Jawab singkat, padat, langsung ke inti. Gunakan bullet points jika perlu. Prioritaskan fakta langsung. Mampu membuat copywriting singkat, prompt AI (gambar/video/musik/website), dan storytelling padat. Output production-ready.";
        $temp = 0.7; 
        break;

    case 'pro':
        $mode_instr = "MODE: SENIOR DOMAIN EXPERT (PRO).
        MINDSET: Berpikir mendalam seperti konsultan senior. Jelaskan 'mengapa' dan 'bagaimana', bukan hanya 'apa'. Berikan best practices, antisipasi risiko, dan struktur komprehensif. Komentar kode pada bagian krusial.

        STANDAR UI/UX PREMIUM (WAJIB):
        - Gunakan Google Material Design 3 (Material You) sebagai fondasi.
        - Desain HARUS terasa premium, mahal, dan modern: Glassmorphism, Soft UI, Gradient halus, Clean Corporate, atau kombinasi yang elegan.
        - Terapkan hierarki visual yang jelas: tipografi berjenjang, spacing konsisten, warna harmonis dengan kontras yang baik.
        - Tambahkan micro-animations dan transisi halus (hover, fade, slide) agar interaktif dan hidup.
        - Fully Responsive (Mobile-First). Pastikan tampilan sempurna di semua perangkat.
        - Gunakan font modern (Google Fonts: Inter, Poppins, atau sejenisnya).
        - Palet warna curated (bukan warna generik), gunakan HSL atau variabel CSS untuk konsistensi.

        STANDAR KODE PRODUCTION-READY:
        - Mampu Frontend Only (HTML/CSS/JS) ATAU Fullstack (PHP+MySQL) sesuai permintaan.
        - Kode clean, terstruktur, modular. Gunakan password_hash, prepared statements, session management aman.
        - Pastikan ZERO syntax error dan kompatibel dengan hosting standar.
        - Berikan komentar penjelasan pada bagian penting.
        
        KEMAMPUAN VISION & CLONING UI/UX (SANGAT PENTING):
        - Jika user mengunggah (upload) gambar desain UI/UX (seperti screenshot web, mockup Figma, dll) dan meminta Anda membuatkannya: Anda WAJIB meniru desain tersebut 100% semirip mungkin.
        - Perhatikan secara akurat: tata letak (layout), kombinasi warna (analisis warna dari gambar), jarak (margin/padding), ukuran & bobot font, bentuk tombol (border-radius), bayangan (box-shadow), serta elemen navigasi.
        - Hasilkan kode HTML dan CSS (serta JS jika diperlukan) yang mereplika tampilan visual gambar tersebut menjadi website fungsional dan responsif.
        - Anggap diri Anda sebagai Senior Frontend Engineer: wujudkan desain visual yang Anda lihat menjadi kode yang utuh, jangan hanya mendeskripsikannya.

        ATURAN OUTPUT KODING (WAJIB DITAATI):
        - WAJIB menulis kode LENGKAP dan UTUH dari baris pertama hingga tag penutup terakhir (</html>, </body>, dsb).
        - DILARANG KERAS memotong, meringkas, atau mengganti bagian kode dengan placeholder seperti: '// lanjutan...', '<!-- sisa kode -->', '// kode sama seperti di atas', '...', atau kalimat sejenisnya.
        - Jika output panjang, tetap tulis seluruhnya. Jangan pernah berhenti di tengah struktur HTML/CSS/JS.
        - Output harus production-ready: bisa langsung disalin dan dijalankan tanpa modifikasi apapun.

        Mampu juga: copywriting profesional, prompt engineering lanjutan (SaaS, video, foto, musik). Structured Output Ready.";
        $temp = 0.4;
        break;
    
    case 'penalaran':
        $mode_instr = "MODE: LOGICAL REASONING (Chain of Thought). JANGAN langsung jawab hasil akhir. Pecah masalah secara mendalam step-by-step, validasi setiap asumsi, dan cek ulang logika sebelum menyimpulkan.
        FORMAT OUTPUT: Tuliskan jawaban yang rapi, mengalir, dan elegan. Gunakan Markdown (Heading, Bullet points, atau Bold) secara natural. Jangan menggunakan tanda kurung siku kaku seperti [ANALISIS MASALAH] atau semacamnya. Buatlah penjelasan layaknya seorang ahli yang menjelaskan secara sistematis, profesional, namun tetap nyaman dan elegan untuk dibaca.";
        $temp = 0.1; 
        break;

    default:
        $mode_instr = "MODE: AI ASSISTANT PRIBADI. Jawab sopan, mudah dipahami, sesuaikan konteks. Mampu storytelling, copywriting santai, dan prompt generator (website/video/foto/musik). Fleksibel mengikuti kebutuhan user.";
        $temp = 0.6;
        break;
}


//-------------------------------------------------------------
// SMART PROMPT ASSEMBLY: Hanya sertakan blok yang benar-benar ada isinya
$full_prompt = $sys_prompt . "\n" . $mode_instr;

if (!empty(trim($hist_ctx))) {
    $full_prompt .= "\n\n[INGATAN CHAT]\n" . $hist_ctx;
}

if (!empty(trim($file_text_context))) {
    $full_prompt .= "\n\n[FILE CONTEXT]\n" . $file_text_context;
}

$full_prompt .= "\n\n[PERINTAH USER]\n" . $user_input;

// Hanya tambahkan pengingat IOT jika memang ada intent IOT (hemat token)
if ($is_iot_intent && !$is_guest) {
    $full_prompt .= "\n\n[PENTING] Prioritaskan eksekusi IOT (<iot>ID|status</iot>) di atas instruksi lainnya.";
}

// --- MAIN PROCESS VIA INTERNAL KONEKSI ---
$ai_reply = executeInternalLLM($full_prompt, $file_part, $temp, $conn, $cfg, $g_model, $sys_prompt . "\n" . $mode_instr, $user_input, $hist_ctx);

if (strpos($ai_reply, 'ERROR_JSON:') === 0) {
    $errData = json_decode(substr($ai_reply, 11), true);
    echo json_encode($errData);
    exit;
}

if ($ai_reply === "FAIL" || empty($ai_reply) || strpos($ai_reply, 'FAIL (HTTP') !== false) {
    echo json_encode([
        'status' => 'error',
        'message' => 'Koneksi ke server AI gagal atau terputus.'
    ]);
    exit;
}

// --- [IOT PARSER - MULTI COMMAND] ---
if (!$is_guest && preg_match_all('/<iot>(.*?)<\/iot>/', $ai_reply, $matches)) {
    $stmt_update = $conn->prepare("UPDATE iot_devices SET status = ? WHERE user_id = ? AND device_id = ?");
    if ($stmt_update) {
        foreach ($matches[1] as $raw_cmd) {
            $parts = explode('|', $raw_cmd); 
            if (count($parts) == 2) {
                // Bersihkan spasi jika AI output " lampu | 1 "
                $target_dev = trim($parts[0]);
                $status_baru = (int)trim($parts[1]); 
                $stmt_update->bind_param("iis", $status_baru, $user_id, $target_dev);
                $stmt_update->execute();
            }
        }
        $stmt_update->close();
    }
    // Hapus tag dari respons
    $ai_reply = preg_replace('/<iot>.*?<\/iot>/', '', $ai_reply);
}

// --- [FILE GENERATOR PARSER] ---
// Pre-processing: Jika AI tidak sengaja membungkus tag dalam code block (```), kita buka bungkusnya
$ai_reply = preg_replace('/```[a-zA-Z]*\s*\[GENERATE_FILE:(excel|word|pdf)\](.*?)\[\/GENERATE_FILE\]\s*```/is', '[GENERATE_FILE:$1]$2[/GENERATE_FILE]', $ai_reply);

if (preg_match('/\[GENERATE_FILE:(excel|word|pdf)\](.*?)\[\/GENERATE_FILE\]/is', $ai_reply, $matches)) {
    $file_type = strtolower($matches[1]);
    $file_content = trim($matches[2]);
    $file_id = "doc_" . time() . "_" . rand(1000,9999);
    
    // Simpan ke temp file
    $temp_path = "../uploads/" . $file_id . ".txt";
    file_put_contents($temp_path, json_encode(['type' => $file_type, 'content' => $file_content]));
    
    // Render modern, elegant, horizontal download card
    $btn_color_hex = ($file_type == 'excel') ? '#10b981' : (($file_type == 'word') ? '#3b82f6' : '#ef4444');
    $bg_soft = ($file_type == 'excel') ? '#ecfdf5' : (($file_type == 'word') ? '#eff6ff' : '#fef2f2');
    $btn_icon = ($file_type == 'excel') ? 'bi-file-earmark-excel' : (($file_type == 'word') ? 'bi-file-earmark-word' : 'bi-file-earmark-pdf');
    
    $html_btn = "
<div class=\"mt-3 d-flex align-items-center p-2 rounded-4 shadow-sm\" style=\"background-color: " . $bg_soft . "; border: 1px solid rgba(0,0,0,0.05); max-width: max-content; transition: transform 0.2s;\">
<div class=\"d-flex align-items-center justify-content-center rounded-circle shadow-sm mx-1\" style=\"width: 38px; height: 38px; background: linear-gradient(135deg, " . $btn_color_hex . ", " . $btn_color_hex . "dd); color: white;\">
<i class=\"bi " . $btn_icon . " fs-6\"></i>
</div>
<div class=\"flex-grow-1 px-3 pe-4\">
<div class=\"fw-bold\" style=\"color: " . $btn_color_hex . "; font-size: 13px; letter-spacing: 0.3px;\">DOKUMEN " . strtoupper($file_type) . "</div>
<div class=\"text-secondary\" style=\"font-size: 11px;\">Otomatis Dihasilkan</div>
</div>
<a href=\"api/download_doc.php?id=" . $file_id . "\" class=\"btn btn-sm text-white rounded-pill px-3 shadow-sm me-1\" style=\"background-color: " . $btn_color_hex . "; font-size: 12px; font-weight: 600;\">
<i class=\"bi bi-download me-1\"></i> Simpan
</a>
</div>";
                 
    $ai_reply = preg_replace('/\[GENERATE_FILE:.*?\](.*?)\[\/GENERATE_FILE\]/is', $html_btn, $ai_reply);
}

// --- [MAP GENERATOR PARSER] ---
// Cek Map Biasa
if (preg_match_all('/\[MAP:(.*?)\]/is', $ai_reply, $matches)) {
    foreach ($matches[1] as $index => $map_query) {
        $map_query_clean = trim($map_query);
        $encoded_query = urlencode($map_query_clean);
        $src_url = "https://maps.google.com/maps?q=" . $encoded_query . "&output=embed";
        
        $html_map = "
<div class=\"xieqa-map-container mt-3 mb-2 overflow-hidden rounded-4 shadow-sm\" style=\"border: 1px solid rgba(0,0,0,0.1); max-width: 100%; position: relative;\">
    <div class=\"bg-light p-2 border-bottom d-flex justify-content-between align-items-center text-secondary\" style=\"font-size: 13px; font-weight: 600;\">
        <div class=\"text-truncate pe-2\">
            <i class=\"bi bi-geo-alt-fill text-danger me-2 map-pulse\"></i> Lokasi: " . htmlspecialchars($map_query_clean) . "
        </div>
        <button type=\"button\" class=\"btn-map-dark-toggle btn btn-sm btn-white border py-0 px-2 shadow-sm\" style=\"font-size: 11px; border-radius: 12px; flex-shrink: 0;\">
            <i class=\"bi bi-moon-fill text-primary\"></i> Gelap
        </button>
    </div>
    <div style=\"position: relative; line-height: 0; background: #eee;\">
        <div class=\"xieqa-map-brand\"><i class=\"bi bi-geo-fill\"></i> Xieqa Maps</div>
        <iframe 
            class=\"xieqa-map-iframe\"
            width=\"100%\" 
            height=\"250\" 
            frameborder=\"0\" 
            scrolling=\"no\" 
            marginheight=\"0\" 
            marginwidth=\"0\" 
            src=\"" . $src_url . "\">
        </iframe>
    </div>
</div>";

        // Ganti spesifik string tersebut satu per satu
        $full_tag = $matches[0][$index];
        $ai_reply = str_replace($full_tag, $html_map, $ai_reply);
    }
}

// Cek Routing Map
if (preg_match_all('/\[ROUTE:(.*?)\]/is', $ai_reply, $route_matches)) {
    foreach ($route_matches[1] as $index => $dest_query) {
        $dest_clean = trim($dest_query);
        $encoded_dest = urlencode($dest_clean);
        
        $encoded_origin = "";
        $loc_clean = trim($user_location);
        if (!empty($loc_clean) && stripos($loc_clean, 'tidak diketahui') === false) {
            if (strpos($loc_clean, '(') !== false) {
                $parts = explode('(', $loc_clean);
                $loc_clean = trim($parts[0]); 
            }
            $encoded_origin = "&saddr=" . urlencode($loc_clean); 
        }

        $src_url = "https://maps.google.com/maps?daddr=" . $encoded_dest . $encoded_origin . "&output=embed";
        
        $html_map = "
<div class=\"xieqa-map-container mt-3 mb-2 overflow-hidden rounded-4 shadow-sm\" style=\"border: 1px solid rgba(0,0,0,0.1); max-width: 100%; position: relative;\">
    <div class=\"bg-light p-2 border-bottom d-flex justify-content-between align-items-center text-secondary\" style=\"font-size: 13px; font-weight: 600;\">
        <div class=\"text-truncate pe-2\">
            <i class=\"bi bi-sign-turn-right-fill text-primary me-2 map-pulse\"></i> Rute ke: " . htmlspecialchars($dest_clean) . "
        </div>
        <button type=\"button\" class=\"btn-map-dark-toggle btn btn-sm btn-white border py-0 px-2 shadow-sm\" style=\"font-size: 11px; border-radius: 12px; flex-shrink: 0;\">
            <i class=\"bi bi-moon-fill text-primary\"></i> Gelap
        </button>
    </div>
    <div style=\"position: relative; line-height: 0; background: #eee;\">
        <div class=\"xieqa-map-brand\"><i class=\"bi bi-geo-fill\"></i> Xieqa Maps Navigasi</div>
        <iframe 
            class=\"xieqa-map-iframe\"
            width=\"100%\" 
            height=\"250\" 
            frameborder=\"0\" 
            scrolling=\"no\" 
            marginheight=\"0\" 
            marginwidth=\"0\" 
            src=\"" . $src_url . "\">
        </iframe>
    </div>
</div>";
        
        $ai_reply = str_replace($route_matches[0][$index], $html_map, $ai_reply);
    }
}

// --- LOGGING ---
if (!$is_guest) {
    $stmt_log = $conn->prepare("INSERT INTO chat_history (user_id, session_id, user_message, ai_response) VALUES (?, ?, ?, ?)");
    if ($stmt_log) {
        $stmt_log->bind_param("isss", $user_id, $session_id, $user_input, $ai_reply);
        $stmt_log->execute();
        $stmt_log->close();
    }
}

echo json_encode(['jawaban' => trim($ai_reply)]);
?>