<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class User_model extends CI_Model
{
    const TABLE = 'tb_users';
    const TABLE_ATTEMPTS = 'tb_login_attempts';

    // Maksimum percobaan dalam window waktu
    const MAX_ATTEMPTS = 5;
    const LOCKOUT_WINDOW_MINUTES = 15;

    public function get_by_username($username)
    {
        return $this->db
            ->where('username', $username)
            ->where('is_active', 1)
            ->get(self::TABLE)
            ->row();
    }

    public function update_last_login($id_user)
    {
        $this->db->where('id_user', $id_user)
                 ->update(self::TABLE, ['last_login' => date('Y-m-d H:i:s')]);
    }

    // -------------------------------------------------------
    // Rate limiting / brute force protection
    // -------------------------------------------------------

    public function count_recent_attempts($identifier, $ip_address)
    {
        $window = date('Y-m-d H:i:s', strtotime('-' . self::LOCKOUT_WINDOW_MINUTES . ' minutes'));

        return $this->db
            ->where('attempt_at >=', $window)
            ->group_start()
                ->where('identifier', $identifier)
                ->or_where('ip_address', $ip_address)
            ->group_end()
            ->count_all_results(self::TABLE_ATTEMPTS);
    }

    public function record_attempt($identifier, $ip_address)
    {
        $this->db->insert(self::TABLE_ATTEMPTS, [
            'identifier' => $identifier,
            'ip_address' => $ip_address,
            'attempt_at' => date('Y-m-d H:i:s'),
        ]);
    }

    public function clear_attempts($identifier)
    {
        $this->db->where('identifier', $identifier)
                 ->delete(self::TABLE_ATTEMPTS);
    }

    public function is_locked_out($identifier, $ip_address)
    {
        return $this->count_recent_attempts($identifier, $ip_address) >= self::MAX_ATTEMPTS;
    }

    // -------------------------------------------------------
    // CRUD (untuk modul manajemen pengguna Fase selanjutnya)
    // -------------------------------------------------------

    public function get_all()
    {
        return $this->db->order_by('nama_lengkap', 'ASC')->get(self::TABLE)->result();
    }

    public function get_by_id($id)
    {
        return $this->db->where('id_user', (int) $id)->get(self::TABLE)->row();
    }

    public function username_exists($username, $exclude_id = null)
    {
        $this->db->where('username', $username);
        if ($exclude_id) {
            $this->db->where('id_user !=', (int) $exclude_id);
        }
        return $this->db->count_all_results(self::TABLE) > 0;
    }

    public function insert_user($data)
    {
        $data['password_hash'] = password_hash($data['password'], PASSWORD_BCRYPT);
        unset($data['password']);
        $this->db->insert(self::TABLE, $data);
        return $this->db->insert_id();
    }

    public function update_user($id, $data)
    {
        if (!empty($data['password'])) {
            $data['password_hash'] = password_hash($data['password'], PASSWORD_BCRYPT);
        }
        unset($data['password']);
        $this->db->where('id_user', (int) $id)->update(self::TABLE, $data);
        return $this->db->affected_rows();
    }

    public function toggle_active($id)
    {
        $user = $this->get_by_id($id);
        if (!$user) {
            return false;
        }
        $new_status = $user->is_active ? 0 : 1;
        $this->db->where('id_user', (int) $id)->update(self::TABLE, ['is_active' => $new_status]);
        return $new_status;
    }

    public function reset_password($id, $new_password)
    {
        $hash = password_hash($new_password, PASSWORD_BCRYPT);
        $this->db->where('id_user', (int) $id)->update(self::TABLE, ['password_hash' => $hash]);
        return $this->db->affected_rows();
    }
}
