<?php

namespace App\Controllers;

use App\Controllers\Base\SarprasPeminjamanController as BaseSarprasPeminjamanController;

class SarprasPeminjamanController extends BaseSarprasPeminjamanController
{
    protected function authorizeSarpras(string $action)
    {
        $user = \Wibiesana\Padi\Core\Auth::user();
        if (!$user) {
            throw new \Exception('Unauthorized', 401);
        }
        
        $userId = is_array($user) ? ($user['id'] ?? $user['user_id'] ?? null) : ($user->id ?? $user->user_id ?? null);
        $role = is_array($user) ? ($user['role'] ?? null) : ($user->role ?? null);

        // Admin/Superadmin has access to all actions
        if ($role === 'superadmin' || $role === 'admin') {
            return;
        }

        // Check if the user is a registered petugas sarpras
        $isPetugas = false;
        if ($userId) {
            $petugasModel = new \App\Models\SarprasPetuga();
            $isPetugas = $petugasModel->findQuery()->where(['user_id' => $userId])->count() > 0;
        }

        if ($action === 'delete') {
            // Only admin can delete
            throw new \Exception('Forbidden: Only admin can delete data', 403);
        }

        if ($isPetugas) {
            // Petugas Sarpras can access all except delete (which is handled above)
            return;
        }

        // Guru/Siswa (teacher/student)
        if ($action === 'view') {
            return;
        }

        if ($action === 'borrow' && ($role === 'teacher' || $role === 'student')) {
            return;
        }

        throw new \Exception('Forbidden: You do not have permission to perform this action', 403);
    }

    /**
     * Get all sarpras_peminjaman with eager-loaded relations
     * GET /sarpras-peminjaman
     */
    public function index()
    {
        $this->authorizeSarpras('view');

        $page = max(1, (int)$this->request->query('page', 1));
        $perPage = min(100, max(1, (int)$this->request->query('per-page', 25)));
        $search = $this->request->query('search');
        
        $sortBy = $this->request->query('sort_by');
        $order = $this->request->query('order', 'asc');
        $orderBy = null;

        if ($sortBy) {
            $direction = strtolower($order) === 'desc' ? 'DESC' : 'ASC';
            $orderBy = "{$sortBy} {$direction}";
        }

        $user = \Wibiesana\Padi\Core\Auth::user();
        $userId = is_array($user) ? ($user['id'] ?? $user['user_id'] ?? null) : ($user->id ?? $user->user_id ?? null);
        $role = is_array($user) ? ($user['role'] ?? null) : ($user->role ?? null);
        
        $isAdmin = ($role === 'superadmin' || $role === 'admin');
        $isPetugas = false;
        if ($userId) {
            $petugasModel = new \App\Models\SarprasPetuga();
            $isPetugas = $petugasModel->findQuery()->where(['user_id' => $userId])->count() > 0;
        }

        $peminjamId = null;
        if (!$isAdmin && !$isPetugas) {
            $peminjamId = $this->getPeminjamIdForUser($userId, $role, $user);
        }

        // Set eager loading relations
        $this->model->with(['item', 'peminjam', 'petugas']);

        if ($search) {
            $search = substr($search, 0, 255);
            if (!$isAdmin && !$isPetugas) {
                $keyword = "%{$search}%";
                $conditions = ['OR'];
                foreach ($this->model->getFillable() as $field) {
                    $conditions[] = ["sarpras_peminjaman.{$field}", 'LIKE', $keyword];
                }
                $conditions[] = ['sarpras_items.nama_barang', 'LIKE', $keyword];
                $conditions[] = ['sarpras_peminjam.nama_lengkap', 'LIKE', $keyword];

                $query = \Wibiesana\Padi\Core\Query::find()
                    ->select("sarpras_peminjaman.*")
                    ->from("sarpras_peminjaman")
                    ->leftJoin('sarpras_items AS sarpras_items', 'sarpras_peminjaman.item_id = sarpras_items.id')
                    ->leftJoin('sarpras_peminjam AS sarpras_peminjam', 'sarpras_peminjaman.peminjam_id = sarpras_peminjam.id')
                    ->leftJoin('sarpras_petugas AS sarpras_petugas', 'sarpras_peminjaman.petugas_id = sarpras_petugas.id')
                    ->where($conditions)
                    ->andWhere(['sarpras_peminjaman.peminjam_id' => $peminjamId]);

                if ($orderBy) {
                    $query->orderBy($orderBy);
                } else {
                    $query->orderBy("sarpras_peminjaman.id DESC");
                }

                $paginateResult = $query->paginate($perPage, $page);
                $result = [
                    'data' => $paginateResult['data'],
                    'meta' => [
                        'total' => (int)$paginateResult['total'],
                        'per_page' => $paginateResult['per_page'],
                        'current_page' => $paginateResult['current_page'],
                        'last_page' => $paginateResult['last_page'],
                        'from' => ($paginateResult['current_page'] - 1) * $paginateResult['per_page'] + 1,
                        'to' => min($paginateResult['current_page'] * $paginateResult['per_page'], $paginateResult['total'])
                    ]
                ];
            } else {
                $result = $this->model->searchPaginate($search, $page, $perPage, $orderBy);
            }
        } else {
            $where = [];
            if (!$isAdmin && !$isPetugas) {
                $where = ['peminjam_id' => $peminjamId];
            }
            $result = $this->model->paginate($page, $perPage, $where, $orderBy);
        }

        // Ensure relations are loaded
        if (!empty($result['data'])) {
            $this->model->loadRelations($result['data']);
        }

        return \App\Resources\SarprasPeminjamanResource::collection($result);
    }

    /**
     * Get single sarpras_peminjaman with eager-loaded relations
     * GET /sarpras-peminjaman/{id}
     */
    public function show()
    {
        $this->authorizeSarpras('view');

        $id = $this->request->param('id');
        $this->model->with(['item', 'peminjam', 'petugas']);
        $peminjaman = $this->model->find($id);
        
        if (!$peminjaman) {
            throw new \Exception('Transaksi peminjaman tidak ditemukan', 404);
        }

        $user = \Wibiesana\Padi\Core\Auth::user();
        $userId = is_array($user) ? ($user['id'] ?? $user['user_id'] ?? null) : ($user->id ?? $user->user_id ?? null);
        $role = is_array($user) ? ($user['role'] ?? null) : ($user->role ?? null);
        
        $isAdmin = ($role === 'superadmin' || $role === 'admin');
        $isPetugas = false;
        if ($userId) {
            $petugasModel = new \App\Models\SarprasPetuga();
            $isPetugas = $petugasModel->findQuery()->where(['user_id' => $userId])->count() > 0;
        }

        if (!$isAdmin && !$isPetugas) {
            $peminjamId = $this->getPeminjamIdForUser($userId, $role, $user);
            if ($peminjaman['peminjam_id'] != $peminjamId) {
                throw new \Exception('Forbidden: You can only view your own transactions', 403);
            }
        }
        
        return \App\Resources\SarprasPeminjamanResource::make($peminjaman);
    }

    public function all()
    {
        $this->authorizeSarpras('view');

        $user = \Wibiesana\Padi\Core\Auth::user();
        $userId = is_array($user) ? ($user['id'] ?? $user['user_id'] ?? null) : ($user->id ?? $user->user_id ?? null);
        $role = is_array($user) ? ($user['role'] ?? null) : ($user->role ?? null);
        
        $isAdmin = ($role === 'superadmin' || $role === 'admin');
        $isPetugas = false;
        if ($userId) {
            $petugasModel = new \App\Models\SarprasPetuga();
            $isPetugas = $petugasModel->findQuery()->where(['user_id' => $userId])->count() > 0;
        }

        if (!$isAdmin && !$isPetugas) {
            $peminjamId = $this->getPeminjamIdForUser($userId, $role, $user);
            $this->model->with(['item', 'peminjam', 'petugas']);
            $results = $this->model->findQuery()->where(['peminjam_id' => $peminjamId])->all();
            if (!empty($results)) {
                $this->model->loadRelations($results);
            }
            return \App\Resources\SarprasPeminjamanResource::collection($results);
        }
        
        return parent::all();
    }

    /**
     * Create new sarpras_peminjaman (Borrow Item)
     * POST /sarpras-peminjaman
     */
    public function store()
    {
        $this->authorizeSarpras('borrow');

        $user = \Wibiesana\Padi\Core\Auth::user();
        $userId = is_array($user) ? ($user['id'] ?? $user['user_id'] ?? null) : ($user->id ?? $user->user_id ?? null);
        $role = is_array($user) ? ($user['role'] ?? null) : ($user->role ?? null);
        
        $isAdmin = ($role === 'superadmin' || $role === 'admin');
        $isPetugas = false;
        if ($userId) {
            $petugasModel = new \App\Models\SarprasPetuga();
            $isPetugas = $petugasModel->findQuery()->where(['user_id' => $userId])->count() > 0;
        }

        $isStudentOrTeacher = !$isAdmin && !$isPetugas;

        $rules = [
            'item_id' => 'required|integer',
            'tanggal_pinjam' => 'required|date',
            'tanggal_rencana_kembali' => 'required|date',
            'jumlah_pinjam' => 'integer',
            'keperluan' => 'string'
        ];

        if (!$isStudentOrTeacher) {
            $rules['peminjam_id'] = 'required|integer';
            $rules['petugas_id'] = 'required|integer';
        } else {
            $rules['peminjam_id'] = 'integer'; // optional, we resolve it
            $rules['petugas_id'] = 'integer'; // optional/nullable
        }

        $validated = $this->validate($rules);

        if ($isStudentOrTeacher) {
            $peminjamId = $this->getOrCreatePeminjamIdForUser($userId, $role, $user);
            $validated['peminjam_id'] = $peminjamId;
            $validated['petugas_id'] = null;
        }

        $itemId = $validated['item_id'];
        $jumlahPinjam = $validated['jumlah_pinjam'] ?? 1;

        // Check item availability
        $itemModel = new \App\Models\SarprasItem();
        $item = $itemModel->find($itemId);
        if (!$item) {
            throw new \Exception('Barang tidak ditemukan', 404);
        }

        if ($item['stok_tersedia'] < $jumlahPinjam) {
            throw new \Exception("Stok barang tidak mencukupi. Tersedia: {$item['stok_tersedia']}", 400);
        }

        try {
            // Generate unique kode_transaksi
            $validated['kode_transaksi'] = 'TRX-' . date('Ymd') . '-' . strtoupper(bin2hex(random_bytes(3)));
            
            if ($isStudentOrTeacher) {
                $validated['status'] = 'pending';
                $validated['petugas_id'] = null;
            } else {
                $validated['status'] = 'dipinjam';
            }
            
            $validated['jumlah_pinjam'] = $jumlahPinjam;
            $validated['denda'] = 0.00;

            // Create transaction
            $id = $this->model->create($validated);

            // Update item stock only if NOT pending
            if (!$isStudentOrTeacher) {
                $newStokTersedia = $item['stok_tersedia'] - $jumlahPinjam;
                $itemStatus = $newStokTersedia <= 0 ? 'dipinjam' : $item['status'];
                $itemModel->update($itemId, [
                    'stok_tersedia' => $newStokTersedia,
                    'status' => $itemStatus
                ]);
            }

            $peminjaman = $this->model->find($id);
            $temp = [$peminjaman];
            $this->model->with(['item', 'peminjam', 'petugas'])->loadRelations($temp);
            $peminjaman = $temp[0];

            return $this->created(\App\Resources\SarprasPeminjamanResource::make($peminjaman));
        } catch (\PDOException $e) {
            $this->databaseError('Gagal memproses peminjaman', $e);
        }
    }

    /**
     * Approve borrowing request (Setujui Peminjaman)
     * POST /sarpras-peminjaman/approve/{id}
     */
    public function approve()
    {
        $this->authorizeSarpras('edit');

        $id = $this->request->param('id');
        $peminjaman = $this->model->find($id);
        if (!$peminjaman) {
            throw new \Exception('Transaksi peminjaman tidak ditemukan', 404);
        }

        if ($peminjaman['status'] !== 'pending') {
            throw new \Exception('Transaksi tidak dalam status menunggu persetujuan', 400);
        }

        // Get current logged in petugas ID
        $user = \Wibiesana\Padi\Core\Auth::user();
        $userId = is_array($user) ? ($user['id'] ?? $user['user_id'] ?? null) : ($user->id ?? $user->user_id ?? null);
        
        $petugasModel = new \App\Models\SarprasPetuga();
        $petugas = $petugasModel->findQuery()->where(['user_id' => $userId])->one();
        
        $petugasId = $petugas ? $petugas['id'] : null;
        if (!$petugasId) {
            $anyPetugas = $petugasModel->findQuery()->one();
            $petugasId = $anyPetugas ? $anyPetugas['id'] : 1;
        }

        // Check stock availability
        $itemModel = new \App\Models\SarprasItem();
        $item = $itemModel->find($peminjaman['item_id']);
        if (!$item) {
            throw new \Exception('Barang tidak ditemukan', 404);
        }

        if ($item['stok_tersedia'] < $peminjaman['jumlah_pinjam']) {
            throw new \Exception("Stok barang tidak mencukupi. Tersedia: {$item['stok_tersedia']}", 400);
        }

        try {
            // Update status to dipinjam and assign petugas_id
            $this->model->update($id, [
                'status' => 'dipinjam',
                'petugas_id' => $petugasId
            ]);

            // Deduct stock
            $newStokTersedia = $item['stok_tersedia'] - $peminjaman['jumlah_pinjam'];
            $itemStatus = $newStokTersedia <= 0 ? 'dipinjam' : $item['status'];
            $itemModel->update($peminjaman['item_id'], [
                'stok_tersedia' => $newStokTersedia,
                'status' => $itemStatus
            ]);

            $updatedPeminjaman = $this->model->find($id);
            $temp = [$updatedPeminjaman];
            $this->model->with(['item', 'peminjam', 'petugas'])->loadRelations($temp);
            $updatedPeminjaman = $temp[0];

            return \App\Resources\SarprasPeminjamanResource::make($updatedPeminjaman);
        } catch (\PDOException $e) {
            $this->databaseError('Gagal menyetujui peminjaman', $e);
        }
    }

    public function update()
    {
        $this->authorizeSarpras('edit');
        return parent::update();
    }

    public function destroy()
    {
        $this->authorizeSarpras('delete');
        return parent::destroy();
    }

    /**
     * Process return of borrowed item (Kembalikan)
     * POST /sarpras-peminjaman/kembali/{id}
     */
    public function kembalikan()
    {
        $this->authorizeSarpras('borrow');

        $id = $this->request->param('id');
        $peminjaman = $this->model->find($id);
        if (!$peminjaman) {
            throw new \Exception('Transaksi peminjaman tidak ditemukan', 404);
        }

        if ($peminjaman['status'] === 'kembali') {
            throw new \Exception('Barang sudah dikembalikan sebelumnya', 400);
        }

        $tanggalKembali = date('Y-m-d');
        $tanggalRencanaKembali = $peminjaman['tanggal_rencana_kembali'];
        
        // Calculate late return fee (Denda: Rp 5.000 / day if late)
        $denda = 0.00;
        $tglKembaliTime = strtotime($tanggalKembali);
        $tglRencanaTime = strtotime($tanggalRencanaKembali);

        if ($tglKembaliTime > $tglRencanaTime) {
            $diffSec = $tglKembaliTime - $tglRencanaTime;
            $diffDays = (int)ceil($diffSec / (60 * 60 * 24));
            $denda = $diffDays * 5000;
        }

        try {
            // Update peminjaman status
            $this->model->update($id, [
                'tanggal_kembali' => $tanggalKembali,
                'status' => 'kembali',
                'denda' => $denda
            ]);

            // Update item stock back
            $itemModel = new \App\Models\SarprasItem();
            $item = $itemModel->find($peminjaman['item_id']);
            if ($item) {
                $newStokTersedia = $item['stok_tersedia'] + $peminjaman['jumlah_pinjam'];
                $itemStatus = $item['status'] === 'dipinjam' && $newStokTersedia > 0 ? 'tersedia' : $item['status'];
                $itemModel->update($peminjaman['item_id'], [
                    'stok_tersedia' => $newStokTersedia,
                    'status' => $itemStatus
                ]);
            }

            $updatedPeminjaman = $this->model->find($id);
            $temp = [$updatedPeminjaman];
            $this->model->with(['item', 'peminjam', 'petugas'])->loadRelations($temp);
            $updatedPeminjaman = $temp[0];

            return \App\Resources\SarprasPeminjamanResource::make($updatedPeminjaman);
        } catch (\PDOException $e) {
            $this->databaseError('Gagal memproses pengembalian', $e);
        }
    }

    private function getOrCreatePeminjamIdForUser($userId, $role, $user)
    {
        $email = is_array($user) ? ($user['email'] ?? null) : ($user->email ?? null);
        
        $isStudent = $role === 'student' || (int)$role === 4;
        $isTeacher = $role === 'teacher' || (int)$role === 2;
        $idIdentitas = null;
        $namaLengkap = '';
        $tipePeminjam = '';
        $kelas = null;
        $jurusan = null;
        $noTelp = null;

        if ($isStudent) {
            $student = (new \App\Models\Student())->where(['id' => $userId]);
            if (!empty($student)) {
                $idIdentitas = $student[0]['nisn'] ?? $student[0]['nis'] ?? null;
                $namaLengkap = $student[0]['name'] ?? '';
                $tipePeminjam = 'siswa';
                $email = $student[0]['email'] ?? $email;
                $noTelp = $student[0]['no_telp'] ?? null;
                
                $classroom = \App\Models\ClassroomMember::findQuery()
                    ->select('classroom.name as class_name')
                    ->innerJoin('classroom', 'classroom_member.class_id = classroom.id')
                    ->where(['classroom_member.student_id' => $userId])
                    ->one();
                if ($classroom) {
                    $kelas = $classroom['class_name'];
                }
            }
        } else if ($isTeacher) {
            $teacher = (new \App\Models\Teacher())->where(['id' => $userId]);
            if (!empty($teacher)) {
                $idIdentitas = $teacher[0]['nip'] ?? null;
                $namaLengkap = $teacher[0]['name'] ?? '';
                $tipePeminjam = 'guru';
                $email = $teacher[0]['email'] ?? $email;
                $noTelp = $teacher[0]['phone'] ?? null;
            }
        }

        if (!$idIdentitas) {
            $idIdentitas = is_array($user) ? ($user['username'] ?? null) : ($user->username ?? null);
        }
        if (!$namaLengkap) {
            $namaLengkap = is_array($user) ? ($user['name'] ?? $user['username'] ?? '') : ($user->name ?? $user->username ?? '');
        }
        if (!$tipePeminjam) {
            $tipePeminjam = $isTeacher ? 'guru' : 'siswa';
        }

        $queryPeminjam = (new \Wibiesana\Padi\Core\Query())->from('sarpras_peminjam');
        $cond = ['OR'];
        if ($email) {
            $cond[] = ['email' => $email];
        }
        if ($idIdentitas) {
            $cond[] = ['id_identitas' => $idIdentitas];
        }
        
        $peminjam = null;
        if (count($cond) > 1) {
            $peminjam = $queryPeminjam->where($cond)->one();
        }
        
        if ($peminjam) {
            return $peminjam['id'];
        }

        // Auto-create peminjam record if not exists
        $newPeminjamData = [
            'tipe_peminjam' => $tipePeminjam,
            'id_identitas' => $idIdentitas,
            'nama_lengkap' => $namaLengkap,
            'kelas' => $kelas,
            'jurusan' => $jurusan,
            'nomor_telepon' => $noTelp,
            'email' => $email,
            'created_at' => date('Y-m-d H:i:s'),
            'updated_at' => date('Y-m-d H:i:s')
        ];
        
        $peminjamModel = new \App\Models\SarprasPeminjam();
        return $peminjamModel->create($newPeminjamData);
    }

    private function getPeminjamIdForUser($userId, $role, $user)
    {
        $email = is_array($user) ? ($user['email'] ?? null) : ($user->email ?? null);
        
        $isStudent = $role === 'student' || (int)$role === 4;
        $isTeacher = $role === 'teacher' || (int)$role === 2;
        $idIdentitas = null;

        if ($isStudent) {
            $student = (new \App\Models\Student())->where(['id' => $userId]);
            if (!empty($student)) {
                $idIdentitas = $student[0]['nisn'] ?? null;
            }
        } else if ($isTeacher) {
            $teacher = (new \App\Models\Teacher())->where(['id' => $userId]);
            if (!empty($teacher)) {
                $idIdentitas = $teacher[0]['nip'] ?? null;
            }
        }

        $queryPeminjam = (new \Wibiesana\Padi\Core\Query())->from('sarpras_peminjam');
        $cond = ['OR'];
        if ($email) {
            $cond[] = ['email' => $email];
        }
        if ($idIdentitas) {
            $cond[] = ['id_identitas' => $idIdentitas];
        }
        
        $peminjam = null;
        if (count($cond) > 1) {
            $peminjam = $queryPeminjam->where($cond)->one();
        }
        
        return $peminjam ? $peminjam['id'] : -1;
    }
}