<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\DB;
use App\Models\BorrowTransaction;
use App\Models\IotMode;
use PhpMqtt\Client\MqttClient;
use App\Http\Controllers\Admin\PeminjamanController;
use App\Http\Controllers\User\UserPeminjamanController;
use App\Jobs\ProcessPeminjamanJob;
use App\Jobs\ProcessPengembalianJob;

/*
|--------------------------------------------------------------------------
| API Routes - Nawasena IoT Library System (Synchronized)
|--------------------------------------------------------------------------
*/

/* ================= HELPERS ================= */

if (!function_exists('cleanData')) {
    function cleanData($data) {
        return strtoupper(str_replace(' ', '', trim($data)));
    }
}

if (!function_exists('mqttPublish')) {
    function mqttPublish($topic, $message) {
        try {
            // Menggunakan Unique Client ID untuk menghindari konflik koneksi
            $mqtt = new MqttClient('127.0.0.1', 1883, 'laravel-api-pub-' . uniqid());
            $mqtt->connect(null, false);
            $payload = is_array($message) ? json_encode($message) : (string)$message;
            $mqtt->publish($topic, $payload, 0);
            $mqtt->disconnect();
        } catch (\Exception $e) {
            \Log::error("MQTT Error: " . $e->getMessage());
        }
    }
}

/* ================= 1. VERIFIKASI RFID (IDENTIFIKASI SEMENTARA) ================= */

Route::get('/esp/check-member', function (Request $request) {
    $uid = cleanData($request->query('uid'));

    if (!$uid) return response()->json(['status' => 'error', 'message' => 'UID Kosong'], 400);

    $iot = IotMode::find(1);

    // Tambahan: Cegah proses jika sistem sedang dalam state lock 'failed'
    if ($iot && $iot->mode === 'wait') {
        return response()->json(['status' => 'error', 'message' => 'Sistem terkunci sementara'], 423);
    }

    $anggota = DB::table('anggota')->where('uid', $uid)->orWhere('uid_clean', $uid)->first();

    if (!$anggota) {
        // Jika kartu salah, ubah mode jadi failed untuk mengunci scan ganda
        if ($iot) $iot->update(['mode' => 'wait']);
        
        mqttPublish('rfid/status', 'failed'); 
        mqttPublish('rfid/ui/member', ['status' => 'invalid']);
        return response()->json(['status' => 'gagal', 'message' => "Kartu $uid tidak terdaftar"], 404);
    }

    if ($iot && $iot->book_id && ($iot->mode === 'wait' || $iot->mode === 'identified')) {
        $iot->update([
            'mode' => 'identified', 
            'user_id' => $anggota->id
        ]);

        mqttPublish('rfid/status', 'valid'); 
        mqttPublish('rfid/ui/member', [
            'status' => 'valid',
            'nama' => $anggota->nama,
            'uid' => $uid
        ]);

        return response()->json([
            'status' => 'berhasil',
            'id'     => $anggota->id,
            'nama'   => $anggota->nama,
            'message'=> 'Anggota teridentifikasi, silakan klik lanjutkan di layar.'
        ], 200);
    }

    return response()->json(['status' => 'error', 'message' => 'Sistem tidak siap'], 400);
});
/* ================= 2. KONFIRMASI PEMINJAMAN REAL ================= */

Route::get('/esp/konfirmasi-pinjam', function () {

    $iot = IotMode::find(1);

    /*
    |--------------------------------------------------------------------------
    | Validasi State
    |--------------------------------------------------------------------------
    */

    if (
        !$iot ||
        !$iot->book_id ||
        !$iot->user_id
    ) {
        return response()->json([
            'status' => 'error',
            'message' => 'Data tidak lengkap'
        ], 400);
    }

    /*
    |--------------------------------------------------------------------------
    | Pastikan Mode Sudah Identified
    |--------------------------------------------------------------------------
    */

    if ($iot->mode !== 'identified') {

        return response()->json([
            'status' => 'error',
            'message' => 'Sistem belum siap'
        ], 400);
    }

    try {

        /*
        |--------------------------------------------------------------------------
        | Lock State
        |--------------------------------------------------------------------------
        */

        $iot->update([
            'mode' => 'processing'
        ]);

        /*
        |--------------------------------------------------------------------------
        | MQTT Feedback ke ESP32
        |--------------------------------------------------------------------------
        */

        mqttPublish('rfid/status', 'processing');

        /*
        |--------------------------------------------------------------------------
        | Dispatch Queue
        |--------------------------------------------------------------------------
        */

        ProcessPeminjamanJob::dispatch(
            $iot->book_id,
            $iot->user_id
        );

        /*
        |--------------------------------------------------------------------------
        | Response Cepat ke Frontend
        |--------------------------------------------------------------------------
        */

        return response()->json([
            'status' => 'queued',
            'message' => 'Peminjaman masuk queue'
        ]);

    } catch (\Throwable $e) {

        /*
        |--------------------------------------------------------------------------
        | Rollback State
        |--------------------------------------------------------------------------
        */

        $iot->update([
            'mode' => 'wait'
        ]);

        mqttPublish('rfid/status', 'failed');

        \Log::error(
            'Dispatch Queue Error: ' . $e->getMessage()
        );

        return response()->json([
            'status' => 'error',
            'message' => 'Queue gagal diproses'
        ], 500);
    }
});

/* ================= 3. SCAN BUKU (PINJAM VS KEMBALI) ================= */

Route::post('/esp/scan-buku', function (Request $request) {
    $barcode = cleanData($request->barcode);
    if (!$barcode) return response()->json(['status' => 'barcode_kosong']);

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

    if (!$book) return response()->json(['status' => 'tidak_ditemukan']);

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

    if ($isBorrowed) {
        $peminjam = DB::table('anggota')->where('id', $isBorrowed->anggota_id)->first();
        
        IotMode::updateOrCreate(['id' => 1], [
            'mode' => 'return_confirm', 
            'book_id' => $book->biblio_id,
            'user_id' => $peminjam->id 
        ]);

        return response()->json([
            'status' => 'konfirmasi_kembali', 
            'book'   => [
                'judul'   => $book->judul_koleksi ?? $book->title,
                'barcode' => $book->kode_eksemplar ?? $book->barcode,
                'peminjam_saat_ini' => $peminjam ? $peminjam->nama : 'Anggota',
                'tanggal_pinjam'    => $isBorrowed->tanggal_pinjam
            ]
        ]);
    }

    IotMode::updateOrCreate(['id' => 1], [
        'mode' => 'wait', 
        'book_id' => $book->biblio_id,
        'user_id' => null 
    ]);
    
    mqttPublish('rfid/mode', 'wait');

    return response()->json([
        'status' => 'ok', 
        'book'   => [
            'judul'   => $book->judul_koleksi ?? $book->title,
            'barcode' => $book->kode_eksemplar ?? $book->barcode
        ]
    ]);
});
/* ================= 4. PROSES PENGEMBALIAN ================= */

Route::get('/esp/proses-kembali', function () {

    $iot = IotMode::find(1);

    if (
        !$iot ||
        $iot->mode !== 'return_confirm' ||
        !$iot->book_id
    ) {
        return response()->json([
            'status' => 'error',
            'message' => 'Sistem tidak dalam mode pengembalian'
        ], 400);
    }

    try {

        // LOCK MODE
        $iot->update([
            'mode' => 'processing_return'
        ]);

        // DISPATCH JOB KE QUEUE
        ProcessPengembalianJob::dispatch([
            'book_id' => $iot->book_id,
            'user_id' => $iot->user_id
        ]);

        // MQTT FEEDBACK CEPAT KE ESP32
        mqttPublish('rfid/status', 'processing');

        return response()->json([
            'status' => 'queued',
            'message' => 'Pengembalian diproses queue'
        ]);

    } catch (\Throwable $e) {

    logger()->error($e);

    mqttPublish('rfid/status', 'error');

    return response()->json([
        'status' => 'error',
        'message' => $e->getMessage()
    ], 500);
}
});

/* ================= 5. STATE, RESET, & BATAL ================= */

Route::get('/esp/state', function () {
    $iot = IotMode::find(1);
    if (!$iot) return response()->json(['status' => 'empty', 'mode' => 'standby']);

    $book = $iot->book_id ? DB::table('koleksis')->where('biblio_id', $iot->book_id)->first() : null;
    $user = $iot->user_id ? DB::table('anggota')->where('id', $iot->user_id)->first() : null;

    return response()->json([
        'status' => 'ok', 
        'mode'   => $iot->mode, 
        'book'   => $book ? [
            'judul'   => $book->judul_koleksi ?? $book->title,
            'barcode' => $book->kode_eksemplar ?? $book->barcode
        ] : null,
        'user'   => $user ? [
            'nama'   => $user->nama
        ] : null
    ]);
});

Route::get('/esp/batalkan-transaksi', function () {
    // Reset SQL ke mode standby
    IotMode::where('id', 1)->update(['mode' => 'standby', 'book_id' => null, 'user_id' => null]);
    
    // Sinkronkan ke Hardware
    mqttPublish('rfid/mode', 'standby');
    mqttPublish('rfid/status', 'idle');
    mqttPublish('rfid/cancel', 'reset'); // Signal tambahan jika Backbone MQTT memantau topik rfid/cancel

    return response()->json(['status' => 'ok', 'message' => 'Transaksi dibatalkan']);
});

Route::get('/esp/selesai-transaksi', function() {
    IotMode::where('id', 1)->update(['mode' => 'standby', 'book_id' => null, 'user_id' => null]);
    mqttPublish('rfid/mode', 'standby');
    mqttPublish('rfid/status', 'idle');
    return response()->json(['status' => 'ok']);
});

Route::get('/esp/reset', function () {
    IotMode::where('id', 1)->update(['mode' => 'standby', 'book_id' => null, 'user_id' => null]);
    mqttPublish('rfid/mode', 'standby');
    mqttPublish('rfid/status', 'idle');
    return response()->json(['status' => 'ok']);
});

/* ================= 6. ADMIN REGISTER MODE ================= */

Route::get('/esp/start-register/{user_id}', function ($user_id) {
    try {
        IotMode::updateOrCreate(['id' => 1], [
            'mode' => 'admin',
            'user_id' => $user_id,
            'book_id' => null
        ]);

        mqttPublish('rfid/mode', 'admin');
        
        return response()->json([
            'status' => 'ready', 
            'message' => 'Alat dalam mode pendaftaran. Silakan tap kartu.'
        ]);
    } catch (\Exception $e) {
        return response()->json(['status' => 'error'], 500);
    } 
});

/* ================= 7. CONTROLLER BINDINGS ================= */

Route::get('/esp/konfirmasi-kembali/{id}', [UserPeminjamanController::class, 'kembalikan']);
Route::get('/esp/konfirmasi-kembali', [PeminjamanController::class, 'konfirmasiKembali']);

