<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Anggota;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\DB;
use SimpleSoftwareIO\QrCode\Facades\QrCode;
use App\Mail\StatusAnggotaDiperbarui;
use PhpMqtt\Client\MqttClient;
use Barryvdh\DomPDF\Facade\Pdf;

class AnggotaController extends Controller
{
    /* ================= MQTT HELPER ================= */
    private function mqttPublish($topic, $message)
    {
        try {
            // Menggunakan broker lokal (127.0.0.1) bawaan Laragon / Mosquitto
            $mqtt = new MqttClient('127.0.0.1', 1883, 'laravel-admin-' . uniqid());
            $mqtt->connect();

            $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());
        }
    }

    /* ================= MANAJEMEN ANGGOTA ================= */

    public function index(Request $request)
    {
        // Ambil input dengan nama variabel yang jelas agar tidak bentrok dengan scope Eloquent ($query)
        $searchKeyword = $request->input('search');
        $statusFilter = $request->input('status');

        // Bangun query dasar
        $query = Anggota::query();

        // Kondisi jika ada pencarian (Bungkus dalam sub-query OR agar tidak merusak filter status)
        if (!empty($searchKeyword)) {
            $query->where(function ($q) use ($searchKeyword) {
                $q->where('nama', 'like', "%{$searchKeyword}%")
                  ->orWhere('email', 'like', "%{$searchKeyword}%")
                  ->orWhere('nip_nim', 'like', "%{$searchKeyword}%") // Sinkronisasi pencarian NIP/NIM
                  ->orWhere('rfid_uid', 'like', "%{$searchKeyword}%"); // Sinkronisasi pencarian RFID UID (dari database: rfid_uid)
            });
        }

        // Kondisi jika ada filter status
        if (!empty($statusFilter)) {
            $query->where('status', $statusFilter);
        }

        // Eksekusi pagination dengan aman
        $members = $query->orderByDesc('created_at')->paginate(10)->withQueryString();

        // PROTEKSI EXTRA: Jika hasil kosong, pastikan tetap mengirim object kosong yang aman, bukan null
        if (!$members) {
            $members = new \Illuminate\Pagination\LengthAwarePaginator([], 0, 10);
        }

        return view('admin.anggota.index', compact('members'));
    }

    public function create()
    {
        return view('admin.anggota.create');
    }

    public function store(Request $request)
    {
        // 🌟 SINKRONISASI: Menambahkan nip_nim dan gender ke formulir tambah manual oleh admin
        $validatedData = $request->validate([
            'nama'    => 'required|string|max:100',
            'gender'  => 'required|in:Laki-laki,Perempuan', 
            'nip_nim' => 'required|string|max:255|unique:anggota,nip_nim',
            'email'   => 'required|email|unique:anggota,email',
            'alamat'  => 'required|string|max:255',
            'no_hp'   => 'nullable|string|max:20',
        ]);

        $validatedData['status'] = 'disetujui';
        $member = Anggota::create($validatedData);

        // MQTT: Memicu reload halaman index admin karena ada entri data fisik baru
        $this->mqttPublish('pendaftaran/refresh/admin', [
            'action' => 'created',
            'message' => 'Anggota baru telah ditambahkan oleh Admin'
        ]);

        return redirect()->route('admin.anggota.index')
            ->with('success', 'Anggota baru berhasil didaftarkan dan disetujui!');
    }

    public function edit($id)
    {
        $member = Anggota::findOrFail($id);
        return view('admin.anggota.edit', compact('member'));
    }

  public function update(Request $request, $id)
{
    $anggota = Anggota::findOrFail($id);

    // 1. Validasi Input Form
    $validatedData = $request->validate([
        'nama'      => 'required|string|max:100',
        'gender'    => 'required|in:Laki-laki,Perempuan', 
        'nik_nip'   => 'required|string|max:255|unique:anggota,nik_nip,' . $anggota->id,
        'email'     => 'required|email|unique:anggota,email,' . $anggota->id,
        'no_hp'     => 'nullable|string|max:20',
        'alamat'    => 'required|string|max:255', // Alamat lengkap gabungan dari JS Blade
        'provinsi'  => 'nullable|string',
        'kota'      => 'nullable|string',
        'kecamatan' => 'nullable|string',
        'desa'      => 'nullable|string',
    ]);

    try {
        // 2. Simpan Perubahan Utama
        $anggota->nama    = $validatedData['nama'];
        $anggota->gender  = $validatedData['gender'];
        $anggota->nik_nip = $validatedData['nik_nip'];
        $anggota->email   = $validatedData['email'];
        $anggota->no_hp   = $validatedData['no_hp'];
        $anggota->alamat  = $validatedData['alamat']; // 🌟 Ini sudah mencakup data wilayah lengkap

        // 🌟 FIXED: 4 baris pengisian wilayah dihapus karena kolomnya tidak ada di tabel database Anda
        // Data wilayah Anda sudah aman dan rapi di dalam kolom $anggota->alamat

        $anggota->save();

        // 3. MQTT Terintegrasi
        try {
            if (method_exists($this, 'mqttPublish')) {
                $this->mqttPublish('pendaftaran/refresh/admin', [
                    'action'    => 'updated',
                    'member_id' => $anggota->id 
                ]);

                if ($anggota->user_id) {
                    $this->mqttPublish('pendaftaran/status/' . $anggota->user_id, [
                        'status'  => $anggota->status,
                        'message' => 'Data pendaftaran Anda telah diperbarui oleh Admin menjadi: ' . $anggota->status
                    ]);
                }
            }
        } catch (\Exception $mqttError) {
            \Log::warning('MQTT Gagal: ' . $mqttError->getMessage());
        }

        // 4. Kembali Ke Index Sembari Membawa Toast/Alert Sukses
        return redirect()->route('admin.anggota.index')
            ->with('success', 'Data anggota berhasil diperbarui! 🎉');

    } catch (\Exception $e) {
        return redirect()->back()
            ->withInput()
            ->withErrors(['error_server' => 'Terjadi kesalahan pada server: ' . $e->getMessage()]);
    }
}


    public function destroy($id)
    {
        $member = Anggota::findOrFail($id);
        $savedUserId = $member->user_id;
        
        $member->delete();

        // MQTT: Sinyal refresh untuk admin karena ada baris data yang hilang
        $this->mqttPublish('pendaftaran/refresh/admin', [
            'action' => 'deleted'
        ]);

        // MQTT: Paksa pengguna logout atau refresh jika akunnya dihapus oleh admin
        if ($savedUserId) {
            $this->mqttPublish('pendaftaran/status/' . $savedUserId, [
                'status' => 'deleted',
                'message' => 'Data pendaftaran Anda telah dihapus oleh pihak admin.'
            ]);
        }

        return redirect()->route('admin.anggota.index')
            ->with('success', 'Anggota berhasil dihapus!');
    }

    public function cetak($id)
    {
        $member = Anggota::findOrFail($id);
        $qrCode = base64_encode(QrCode::format('svg')->size(120)->generate($member->nama));

        return view('admin.anggota.cetak', compact('member', 'qrCode'));
    }

    /* ================= INTEGRASI IOT & STATE FLOW ================= */

    public function approve($id)
    {
        $member = Anggota::findOrFail($id);

        // 1. Cek kesiapan IoT (Jangan timpa jika sedang ada transaksi berjalan)
        $current = DB::table('iot_modes')->where('id', 1)->first();
        if ($current && $current->mode !== 'standby') {
            return back()->with('warning', 'Sistem sedang sibuk. Pastikan alat dalam posisi standby.');
        }

        // 2. Update status anggota di database menjadi disetujui
        $member->update(['status' => 'disetujui']);

        // 3. Kunci State IoT ke mode 'admin' untuk User ID target
        DB::table('iot_modes')->where('id', 1)->update([
            'mode' => 'admin',
            'user_id' => $member->id,
            'updated_at' => now()
        ]);

        // 4. Perintah utama ke perangkat keras ESP32
        $this->mqttPublish('rfid/mode/set', 'admin'); 
        $this->mqttPublish('rfid/admin/request_scan', [
            'status' => 'waiting_scan',
            'nama' => $member->nama,
            'id' => $member->id
        ]);

        // 5. SINKRONISASI STATE ASINKRON: Kirim aksi 'approved' ke JavaScript panel admin.
        $this->mqttPublish('pendaftaran/refresh/admin', [
            'action' => 'approved',
            'member_id' => $member->id
        ]);

        // 6. Notifikasi real-time ke aplikasi/halaman milik user
        if ($member->user_id) {
            $this->mqttPublish('pendaftaran/status/' . $member->user_id, [
                'status' => 'disetujui',
                'message' => "Pendaftaran Anda disetujui! Alat RFID sekarang menunggu scan kartu Anda."
            ]);
        }

        // 7. Pengiriman Notifikasi via Email
        try {
            Mail::to($member->email)->send(new StatusAnggotaDiperbarui($member));
        } catch (\Exception $e) {
            \Log::error("Email Error: " . $e->getMessage());
        }

        return back()->with('success', "Anggota {$member->nama} disetujui. Perangkat RFID Nawasena siap menerima pemindaian kartu.");
    }

    public function reject($id)
    {
        $member = Anggota::findOrFail($id);
        $member->update(['status' => 'ditolak']);

        // MQTT: Beritahu halaman admin untuk memperbarui status penolakan
        $this->mqttPublish('pendaftaran/refresh/admin', [
            'action' => 'rejected',
            'member_id' => $member->id
        ]);

        // 🌟 SINKRONISASI: Sinyal 'ditolak' dikirim ke user agar di view user langsung muncul tombol pendaftaran ulang (sinkron dengan UserMemberController)
        if ($member->user_id) {
            $this->mqttPublish('pendaftaran/status/' . $member->user_id, [
                'status' => 'ditolak',
                'message' => "Pendaftaran Anda ditolak oleh admin. Silakan periksa kembali data Anda dan lakukan daftar ulang jika diperlukan."
            ]);
        }

        try {
            Mail::to($member->email)->send(new StatusAnggotaDiperbarui($member));
        } catch (\Exception $e) {
            \Log::error("Email Error: " . $e->getMessage());
        }

        return back()->with('warning', "Anggota {$member->nama} telah ditolak.");
    }

    public function receiveRfidUid(Request $request)
    {
        $uid = $request->input('uid');
        $anggotaId = $request->input('anggota_id'); 

        $member = Anggota::find($anggotaId);
        if ($member) {
            // 1. Simpan string UID fisik kartu ke data anggota
            $member->update(['rfid_uid' => $uid]);

            // 2. Kembalikan state mesin IoT ke mode 'standby' agar siap digunakan kembali
            DB::table('iot_modes')->where('id', 1)->update([
                'mode' => 'standby',
                'user_id' => null,
                'updated_at' => now()
            ]);

            $this->mqttPublish('pendaftaran/refresh/admin', [
                'action' => 'uid_saved',
                'member_id' => $member->id,
                'rfid_uid' => $uid 
            ]);

            // 4. Perintahkan sistem user untuk mengalihkan view ke halaman dashboard utama library
            if ($member->user_id) {
                $this->mqttPublish('pendaftaran/status/' . $member->user_id, [
                    'status' => 'uid_ready',
                    'message' => 'Kartu RFID Anda berhasil diregistrasikan!'
                ]);
            }

            return response()->json(['status' => 'success', 'message' => 'UID Berhasil disimpan dan disinkronkan ke Web-Admin via MQTT.']);
        }

        return response()->json(['status' => 'error', 'message' => 'Data Anggota tidak ditemukan.'], 404);
    }

    public function print($id)
    {
        $member = Anggota::findOrFail($id);

        // Load view kartu yang sudah rapi
        $pdf = Pdf::loadView('admin.anggota.print', compact('member'));
        
        // Atur ukuran kertas kustom atau default (misal A4 atau ukuran kartu)
        $pdf->setPaper('a4', 'portrait'); 

        // Menggunakan STREAM agar PDF terbuka langsung di PDF Viewer browser (persis seperti contoh gambar)
        return $pdf->stream('Kartu Anggota ' . $member->nama . '.pdf');
    }
}