<?php
// models/Users.php

require_once dirname(__DIR__) . '/models/BaseModel.php';

class Users extends BaseModel {
    protected $table = 'users';

    /**
     * Mengambil semua data pengguna dari database.
     * Hanya untuk admin.
     *
     * @return array Array asosiatif berisi semua data pengguna.
     */
    public function getAllUsers() {
        $sql = "SELECT * FROM {$this->table} ORDER BY fullname ASC";
        $result = $this->conn->query($sql);
        $users = [];
        if ($result && $result->num_rows > 0) {
            while ($row = $result->fetch_assoc()) {
                $users[] = $row;
            }
        }
        return $users;
    }

    /**
     * Mengambil data pengguna berdasarkan ID.
     *
     * @param int $id ID pengguna.
     * @return array|null Array asosiatif data pengguna jika ditemukan, null jika tidak.
     */
    public function getUserById($id) {
        $stmt = $this->conn->prepare("SELECT * FROM {$this->table} WHERE id = ?");
        $stmt->bind_param("i", $id);
        $stmt->execute();
        $result = $stmt->get_result();
        return $result->fetch_assoc();
    }

    /**
     * Mengambil data pengguna berdasarkan username.
     * Digunakan untuk proses login.
     *
     * @param string $username Username pengguna.
     * @return array|null Array asosiatif data pengguna jika ditemukan, null jika tidak.
     */
    public function getUserByUsername($username) {
        $stmt = $this->conn->prepare("SELECT * FROM {$this->table} WHERE username = ?");
        $stmt->bind_param("s", $username);
        $stmt->execute();
        $result = $stmt->get_result();
        return $result->fetch_assoc();
    }

    /**
     * Mengambil data pengguna berdasarkan email.
     * Digunakan untuk fitur lupa sandi.
     *
     * @param string $email Email pengguna.
     * @return array|null Array asosiatif data pengguna jika ditemukan, null jika tidak.
     */
    public function getUserByEmail($email) {
        $stmt = $this->conn->prepare("SELECT * FROM {$this->table} WHERE email = ?");
        $stmt->bind_param("s", $email);
        $stmt->execute();
        $result = $stmt->get_result();
        return $result->fetch_assoc();
    }

    /**
     * Menambahkan pengguna baru ke database (Registrasi).
     * Password akan di-hash sebelum disimpan.
     *
     * @param string $fullname Nama lengkap pengguna.
     * @param string $jenis_kelamin Jenis kelamin ('L' atau 'P').
     * @param string $email Alamat email pengguna.
     * @param string $username Username pengguna.
     * @param string $password Password pengguna (plaintext).
     * @param string|null $no_hp Nomor telepon pengguna.
     * @param string $role Peran pengguna ('user' atau 'admin').
     * @param string|null $foto Path foto profil.
     * @return bool True jika berhasil, false jika gagal (misal: username/email sudah ada).
     */
    public function addUser($fullname, $jenis_kelamin, $email, $username, $password, $no_hp = null, $role = 'user', $foto = null) {
        // Hash password sebelum disimpan
        $hashed_password = password_hash($password, PASSWORD_BCRYPT);

        $stmt = $this->conn->prepare("INSERT INTO {$this->table} (fullname, jenis_kelamin, email, username, password, no_hp, role, foto) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
        $stmt->bind_param("ssssssss", $fullname, $jenis_kelamin, $email, $username, $hashed_password, $no_hp, $role, $foto);
        
        try {
            return $stmt->execute();
        } catch (mysqli_sql_exception $e) {
            // Tangani error duplikat entry (misal username/email sudah ada)
            if ($e->getCode() == 1062) { // MySQL error code for Duplicate entry
                return false; // Mengindikasikan gagal karena duplikasi
            }
            throw $e; // Re-throw error jika bukan duplikasi
        }
    }

    /**
     * Memperbarui data pengguna yang sudah ada di database.
     *
     * @param int $id ID pengguna yang akan diperbarui.
     * @param string $fullname Nama lengkap pengguna.
     * @param string $jenis_kelamin Jenis kelamin ('L' atau 'P').
     * @param string $email Alamat email pengguna.
     * @param string $username Username pengguna.
     * @param string|null $password Password baru (plaintext), biarkan null jika tidak ingin mengubah.
     * @param string|null $no_hp Nomor telepon pengguna.
     * @param string $role Peran pengguna ('user' atau 'admin').
     * @param string|null $foto Path foto profil.
     * @return bool True jika berhasil, false jika gagal.
     */
    public function updateUser($id, $fullname, $jenis_kelamin, $email, $username, $password = null, $no_hp = null, $role = 'user', $foto = null) {
        $sql = "UPDATE {$this->table} SET fullname = ?, jenis_kelamin = ?, email = ?, username = ?, no_hp = ?, role = ?, foto = ?";
        $params = [$fullname, $jenis_kelamin, $email, $username, $no_hp, $role, $foto];
        $types = "sssssss";

        if ($password !== null && !empty($password)) {
            $hashed_password = password_hash($password, PASSWORD_BCRYPT);
            $sql .= ", password = ?";
            $params[] = $hashed_password;
            $types .= "s";
        }

        $sql .= " WHERE id = ?";
        $params[] = $id;
        $types .= "i";

        $stmt = $this->conn->prepare($sql);
        $stmt->bind_param($types, ...$params); // Menggunakan spread operator untuk bind_param
        
        try {
            return $stmt->execute();
        } catch (mysqli_sql_exception $e) {
            if ($e->getCode() == 1062) { // Duplicate entry for username/email
                return false;
            }
            throw $e;
        }
    }

    /**
     * Menghapus pengguna dari database berdasarkan ID.
     * Perhatikan FOREIGN KEY CONSTRAINTS. Jika ada pemesanan terkait pengguna ini,
     * penghapusan mungkin akan diblokir.
     *
     * @param int $id ID pengguna yang akan dihapus.
     * @return bool True jika berhasil, false jika gagal.
     */
    public function deleteUser($id) {
        $stmt = $this->conn->prepare("DELETE FROM {$this->table} WHERE id = ?");
        $stmt->bind_param("i", $id);
        return $stmt->execute();
    }

    /**
     * Menyimpan token reset password baru untuk email tertentu.
     * Menghapus token lama jika ada.
     *
     * @param string $email Email pengguna.
     * @param string $token Token reset password.
     * @return bool True jika berhasil, false jika gagal.
     */
    public function createPasswordResetToken($email, $token) {
        // Hapus token lama untuk email yang sama
        $stmt_delete = $this->conn->prepare("DELETE FROM password_resets WHERE email = ?");
        $stmt_delete->bind_param("s", $email);
        $stmt_delete->execute();

        // Masukkan token baru
        $stmt_insert = $this->conn->prepare("INSERT INTO password_resets (email, token) VALUES (?, ?)");
        $stmt_insert->bind_param("ss", $email, $token);
        return $stmt_insert->execute();
    }

    /**
     * Memverifikasi token reset password dan mengambil email terkait.
     * Token dianggap valid jika ditemukan dan belum kadaluarsa (misal: 1 jam).
     *
     * @param string $token Token reset password.
     * @return string|null Email jika token valid, null jika tidak valid/kadaluarsa.
     */
    public function verifyPasswordResetToken($token) {
        $stmt = $this->conn->prepare("SELECT email, created_at FROM password_resets WHERE token = ?");
        $stmt->bind_param("s", $token);
        $stmt->execute();
        $result = $stmt->get_result();
        $row = $result->fetch_assoc();

        if ($row) {
            // FIX: Menggunakan perbandingan timestamp untuk validasi kadaluarsa
            $created_at_timestamp = strtotime($row['created_at']); // Konversi created_at ke Unix timestamp
            $current_timestamp = time(); // Dapatkan Unix timestamp saat ini

            $expiration_time_seconds = 3600; // 1 jam dalam detik

            // Jika selisih waktu saat ini dengan waktu pembuatan kurang dari atau sama dengan 1 jam
            if (($current_timestamp - $created_at_timestamp) <= $expiration_time_seconds) {
                return $row['email']; // Token valid, kembalikan email
            }
        }
        return null; // Token tidak valid atau kadaluarsa
    }

    /**
     * Menghapus token reset password setelah digunakan.
     *
     * @param string $token Token reset password.
     * @return bool True jika berhasil, false jika gagal.
     */
    public function deletePasswordResetToken($token) {
        $stmt = $this->conn->prepare("DELETE FROM password_resets WHERE token = ?");
        $stmt->bind_param("s", $token);
        return $stmt->execute();
    }

    /**
     * Memperbarui password pengguna berdasarkan email.
     *
     * @param string $email Email pengguna.
     * @param string $new_password Password baru (plaintext).
     * @return bool True jika berhasil, false jika gagal.
     */
    public function updatePasswordByEmail($email, $new_password) {
        $hashed_password = password_hash($new_password, PASSWORD_BCRYPT);
        $stmt = $this->conn->prepare("UPDATE {$this->table} SET password = ? WHERE email = ?");
        $stmt->bind_param("ss", $hashed_password, $email);
        return $stmt->execute();
    }
    /**
     * Menghitung total jumlah baris di tabel users.
     * @return int Jumlah total user.
     */
    public function countAll() {
        $result = $this->conn->query("SELECT COUNT(*) FROM {$this->table}");
        if (!$result) {
            error_log("SQL Error in Users::countAll: " . $this->conn->error);
            return 0;
        }
        $row = $result->fetch_row();
        return $row[0];
    }
}
