<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use PhpMqtt\Client\MqttClient;
use Illuminate\Support\Facades\DB;
use App\Models\IotMode;

class MqttListen extends Command
{
    protected $signature = 'mqtt:listen';
    protected $description = 'Nawasena MQTT Backbone - Integrated Hardware, UI & Admin Registration with State Lock';

    public function handle()
    {
        // Hubungkan ke broker
        $mqtt = new MqttClient('127.0.0.1', 1883, 'laravel-backbone-' . uniqid());
        
        try {
            $mqtt->connect(null, false, 60);
            $this->info("🚀 NAWASENA MQTT BACKBONE STARTED");

            // Subscribe ke semua topik rfid
            $mqtt->subscribe('rfid/#', function ($topic, $message) use ($mqtt) {
                $this->info("📥 Inbound [$topic]: $message");

                // --- TAMBAHAN: LOGIKA STATUS HARDWARE ---
                if ($topic === 'rfid/device/status') {
                    $this->handleDeviceStatus($message);
                    return; // Keluar dari callback agar tidak masuk ke pemrosesan JSON di bawah
                }

                $data = json_decode($message, true);
                if (!is_array($data)) {
                    $data = ['raw' => $message, 'uid' => $message, 'barcode' => $message];
                }

                // 1. ALUR SCAN BARCODE BUKU
                if ($topic === 'rfid/book') {
                    $this->handleBookScan($mqtt, $data);
                }

                // 2. ALUR SCAN KARTU ANGGOTA (RFID)
                if ($topic === 'rfid/scan' || $topic === 'rfid/scan/member') {
                    $this->handleUserScan($mqtt, $data);
                }

                // 3. ALUR PENDAFTARAN KARTU BARU (ADMIN MODE)
                if ($topic === 'rfid/scan/admin') {
                    $this->handleAdminScan($mqtt, $data);
                }

                // 4. EKSEKUSI FINAL (DARI TOMBOL UI ATAU HARDWARE)
                if ($topic === 'rfid/confirm' && $message === 'execute') {
                    $this->executeFinalTransaction($mqtt);
                }
                
                if ($topic === 'rfid/confirm/return' && $message === 'execute') {
                    $this->executeReturnTransaction($mqtt);
                }

                // 5. BATALKAN TRANSAKSI (DARI TOMBOL UI)
                if ($topic === 'rfid/cancel' && $message === 'reset') {
                    $this->handleCancelTransaction($mqtt);
                }

            }, 0);

            $mqtt->loop(true);

        } catch (\Exception $e) {
            $this->error("❌ MQTT ERROR: " . $e->getMessage());
            $this->info("Mencoba menyambung ulang dalam 5 detik...");
            sleep(5);
            $this->handle(); 
        }
    }

    /* ================= HANDLER STATUS DEVICE ================= */
    private function handleDeviceStatus($message)
    {
        if ($message === 'online') {
            $this->info("🟢 DEVICE STATUS: Hardware is Online");
        } else {
            $this->warn("🔴 DEVICE STATUS: Hardware is Offline");
        }
    }

    /* ================= HANDLER BATALKAN TRANSAKSI ================= */
    private function handleCancelTransaction($mqtt)
    {
        DB::table('iot_modes')->where('id', 1)->update([
            'mode' => 'standby',
            'user_id' => null,
            'book_id' => null
        ]);

        $this->publish($mqtt, 'rfid/mode', 'standby');
        $this->publish($mqtt, 'rfid/status', 'idle');
        $this->info("🔄 System Reset to Standby by User Request");
    }

    /* ================= HANDLER PENDAFTARAN ANGGOTA (BARU) ================= */
    private function handleAdminScan($mqtt, $data)
    {
        $uid = $this->cleanData($data['uid'] ?? $data['raw'] ?? '');
        if (!$uid) return;

        $iot = DB::table('iot_modes')->where('id', 1)->first();

        if ($iot && $iot->mode === 'admin' && $iot->user_id) {
            try {
                DB::table('anggota')->where('id', $iot->user_id)->update([
                    'uid' => $uid,
                    'uid_clean' => $uid,
                    'status' => 'disetujui',
                    'updated_at' => now()
                ]);

                DB::table('iot_modes')->where('id', 1)->update([
                    'mode' => 'standby',
                    'user_id' => null,
                    'book_id' => null
                ]);

                $this->publish($mqtt, 'rfid/status', 'registered'); 
                $this->publish($mqtt, 'rfid/mode', 'standby');
                
                $this->publish($mqtt, 'rfid/ui/admin', [
                    'status' => 'registered',
                    'uid' => $uid,
                    'message' => 'Kartu Berhasil Ditautkan'
                ]);

                $this->info("✅ SUCCESS: UID $uid registered to Member ID {$iot->user_id}");
            } catch (\Exception $e) {
                $this->error("❌ Admin Scan Failed: " . $e->getMessage());
                $this->publish($mqtt, 'rfid/status', 'error');
            }
        }
    }

    /* ================= HANDLER PEMINJAMAN / PENGEMBALIAN ================= */
    private function handleBookScan($mqtt, $data)
    {
        $barcode = $this->cleanData($data['barcode'] ?? $data['raw'] ?? '');
        if (!$barcode) return;

        $buku = DB::table('koleksis')
            ->where('barcode', $barcode)
            ->orWhere('kode_eksemplar', $barcode)
            ->first();

        if (!$buku) {
            $this->publish($mqtt, 'rfid/status', 'error');
            $this->publish($mqtt, 'rfid/ui/detail', ['status' => 'tidak_ditemukan']);
            return;
        }

        $trx = DB::table('borrow_transactions')
            ->where('koleksi_id', $buku->biblio_id)
            ->where('status', 'dipinjam')
            ->first();

        if ($trx) {
            $anggota = DB::table('anggota')->where('id', $trx->anggota_id)->first();
            IotMode::query()->where('id', 1)->update([
                'mode' => 'return_confirm', 
                'book_id' => $buku->biblio_id,
                'user_id' => $trx->anggota_id 
            ]);

            $this->publish($mqtt, 'rfid/ui/redirect_return', [
                'status' => 'konfirmasi_kembali',
                'judul' => $buku->judul_koleksi ?? $buku->title,
                'nama' => $anggota->nama ?? 'Anggota',
                'barcode' => $barcode,
                'tanggal_pinjam' => $trx->tanggal_pinjam
            ]);
        } else {
            IotMode::query()->where('id', 1)->update([
                'mode' => 'wait', 
                'book_id' => $buku->biblio_id, 
                'user_id' => null
            ]);

            $this->publish($mqtt, 'rfid/mode', 'wait');
            $this->publish($mqtt, 'rfid/ui/detail', [
                'status' => 'ok',
                'judul' => $buku->judul_koleksi ?? $buku->title,
                'barcode' => $barcode
            ]);
        }
    }

    private function handleUserScan($mqtt, $data)
    {
        $uid = $this->cleanData($data['uid'] ?? $data['raw'] ?? '');
        if (!$uid) return;

        $iot = DB::table('iot_modes')->where('id', 1)->first();
        
        if ($iot && $iot->mode === 'admin') {
            $this->info("🔄 Redirecting scan to Admin Handler...");
            $this->handleAdminScan($mqtt, $data);
            return;
        }

        if (!$iot || !in_array($iot->mode, ['wait', 'user', 'identified'])) {
            $this->warn("⚠️ Scan ignored: Mode is {$iot->mode}");
            return;
        }

        if ($iot->book_id) {
            $anggota = DB::table('anggota')->where('uid', $uid)->orWhere('uid_clean', $uid)->first();
            
            if ($anggota) {
                DB::table('iot_modes')->where('id', 1)->update([
                    'mode' => 'identified', 
                    'user_id' => $anggota->id
                ]);

                $this->publish($mqtt, 'rfid/status', 'valid');
                $this->publish($mqtt, 'rfid/ui/member', [
                    'status' => 'valid',
                    'nama' => $anggota->nama,
                    'uid' => $uid
                ]);
           } else {

    // Mode tetap wait, tidak perlu diubah ke failed
    $this->publish($mqtt, 'rfid/status', 'failed');

    $this->publish($mqtt, 'rfid/ui/member', [
        'status' => 'invalid'
    ]);

    $this->info("❌ Invalid Card: $uid");
            }
        }
    }

    private function executeReturnTransaction($mqtt)
    {
        $iot = DB::table('iot_modes')->where('id', 1)->first();

        if ($iot && $iot->mode === 'return_confirm' && $iot->book_id) {
            try {
                // Ambil data buku untuk keperluan pesan UI web user
                $book = DB::table('koleksis')->where('biblio_id', $iot->book_id)->first();
                $judulBuku = $book ? ($book->judul_koleksi ?? $book->title) : 'Buku';
                $targetUserId = $iot->user_id;

                $affected = DB::table('borrow_transactions')
                    ->where('koleksi_id', $iot->book_id)
                    ->where('status', 'dipinjam')
                    ->update([
                        'status' => 'kembali',
                        'updated_at' => now()
                    ]);

                if ($affected) {
                    DB::table('iot_modes')->where('id', 1)->update(['mode' => 'success_return']);
                    $this->publish($mqtt, 'rfid/status', 'finish'); 
                    $this->info("✅ SUCCESS: Book returned");

                    // 🔥 BROADCAST AUTO-REFRESH USER WEB (PENGEMBALIAN SUKSES)
                    if ($targetUserId) {
                        $this->publish($mqtt, 'peminjaman/user/' . $targetUserId, [
                            'status' => 'dikembalikan',
                            'message' => "Pengembalian Sukses! Buku [{$judulBuku}] telah terdata kembali."
                        ]);
                    }
                }
            } catch (\Exception $e) {
                $this->error("❌ Return Update Failed: " . $e->getMessage());
                $this->publish($mqtt, 'rfid/status', 'error');
            }
        }
    }

    private function executeFinalTransaction($mqtt)
    {
        $iot = DB::table('iot_modes')->where('id', 1)->first();

        if ($iot && $iot->mode === 'identified' && $iot->book_id && $iot->user_id) {
            try {
                // Ambil data buku untuk keperluan pesan UI web user
                $book = DB::table('koleksis')->where('biblio_id', $iot->book_id)->first();
                $judulBuku = $book ? ($book->judul_koleksi ?? $book->title) : 'Buku';

                DB::table('borrow_transactions')->insert([
                    'anggota_id'      => $iot->user_id,
                    'koleksi_id'      => $iot->book_id,
                    'tanggal_pinjam'  => now(),
                    'tanggal_kembali' => now()->addDays(7),
                    'status'          => 'dipinjam',
                    'created_at'      => now(),
                    'updated_at'      => now()
                ]);

                DB::table('iot_modes')->where('id', 1)->update(['mode' => 'success_loan']);
                $this->publish($mqtt, 'rfid/status', 'finish'); 
                $this->info("✅ SUCCESS: Loan completed");

                // 🔥 BROADCAST AUTO-REFRESH USER WEB (PEMINJAMAN SUKSES)
                $this->publish($mqtt, 'peminjaman/user/' . $iot->user_id, [
                    'status' => 'dipinjam',
                    'message' => "Peminjaman Sukses! Buku [{$judulBuku}] masuk ke riwayat akun Anda."
                ]);

            } catch (\Exception $e) {
                $this->error("❌ DB Insert Failed: " . $e->getMessage());
                $this->publish($mqtt, 'rfid/status', 'error');
            }
        }
    }

    private function publish($mqtt, $topic, $data) {
        $payload = is_array($data) ? json_encode($data) : (string)$data;
        $mqtt->publish($topic, $payload, 0);
    }

    private function cleanData($data) { 
        return strtoupper(str_replace(' ', '', trim($data))); 
    }
}

