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

class Login_device extends CI_Controller {

	public function __construct() {
		parent::__construct();
		$this->load->helper('az_device_helper');
		$this->load->helper('az_access_time');
		$this->load->helper('az_auth');

		// method yang boleh diakses TANPA login
		$public = array('auto_device', 'activate', 'activate_by_code', 'recover_device', 'request_recovery');
		if (!in_array(strtolower($this->router->fetch_method()), $public)) {
			az_check_auth('dashboard');
		}
	}

	private function _all_users() {
		$this->db->select('user.iduser, user.name, user.username, role.name as role_name, outlet.outlet_name');
		$this->db->from('user');
		$this->db->join('role', 'role.idrole = user.idrole', 'left');
		$this->db->join('outlet', 'outlet.idoutlet = user.idoutlet', 'left');
		$this->db->where('user.status', 1);
		$this->db->order_by('outlet.outlet_name asc, role.name asc, user.name asc');
		return $this->db->get()->result();
	}

	/* ============ DAFTAR DEVICE BARU ============ */
	public function register() {
		if ($this->session->userdata('role_name') != 'administrator') { show_404(); return; }
		$this->load->library('form_validation');
		$this->form_validation->set_rules('idoutlet', 'Outlet', 'required');
		$this->form_validation->set_rules('device_type', 'Tipe Device', 'required|in_list[PC,HP]');
		$this->form_validation->set_rules('device_name', 'Nama Device', 'required');

		$selected   = $this->input->post('iduser');
		$form_ok    = $this->form_validation->run();
		$manual_err = '';
		if ($form_ok && (!is_array($selected) || count($selected) == 0))
			$manual_err = 'Pilih minimal 1 user yang boleh login otomatis di device ini.';

		if (!$form_ok || $manual_err != '') {
			$this->load->view('login_device/v_register', array(
				'outlets'    => $this->db->get_where('outlet', array('status' => 1))->result(),
				'users'      => $this->_all_users(),
				'selected'   => is_array($selected) ? $selected : array(),
				'manual_err' => $manual_err,
			));
			return;
		}

		$url_token = az_device_secret();          // untuk link lengkap (fallback)
		$code      = az_generate_activation_code(10); // kode 10 karakter untuk diketik user

		$this->db->insert('device_registry', array(
			'idoutlet'     => $this->input->post('idoutlet'),
			'device_type'  => $this->input->post('device_type'),
			'device_name'  => $this->input->post('device_name'),
			'device_token' => null,
			'device_token_hash' => null,
			'activation_token_hash'    => az_device_hash($url_token),
			'activation_token_expires' => date('Y-m-d H:i:s', strtotime('+24 hours')),
			'activation_code_hash'     => az_device_hash($code),
			'activated'    => 0,
			'recovery_token_status' => 'active',
			'next_rotation_at' => az_next_rotation_time(),
			'ip_address'   => $this->input->ip_address(),
			'user_agent'   => $this->input->user_agent(),
			'iduser'       => intval($selected[0]),
			'status'       => 1,
			'created'      => date('Y-m-d H:i:s'),
		));
		$insert_id = $this->db->insert_id();
		az_save_device_users($insert_id, $selected);

		$this->session->set_flashdata('success', 'Device berhasil didaftarkan.');
		$this->session->set_flashdata('activation_code', $code);
		$this->session->set_flashdata('activation_device_name', $this->input->post('device_name'));
		$this->session->set_flashdata('activation_url', app_url() . 'login_device/activate?token=' . urlencode($url_token));
		redirect('login_device/register');
	}

	/* ============ KIRIM ULANG KODE / LINK ============ */
	public function resend_link($iddevice = '') {
		if ($this->session->userdata('role_name') != 'administrator') { show_404(); return; }
		$iddevice = intval($iddevice);
		$this->db->where('iddevice', $iddevice); $this->db->where('status', 1);
		$device = $this->db->get('device_registry')->row();
		if (!$device) { $this->session->set_flashdata('error', 'Device tidak ditemukan.'); redirect('login_device/list_devices'); return; }

		$url_token = az_device_secret();
		$code      = az_generate_activation_code(10);

		$this->db->where('iddevice', $iddevice);
		$this->db->update('device_registry', array(
			'activation_token_hash'    => az_device_hash($url_token),
			'activation_token_expires' => date('Y-m-d H:i:s', strtotime('+24 hours')),
			'activation_code_hash'     => az_device_hash($code),
		));

		$this->session->set_flashdata('success', 'Kode aktivasi baru untuk "' . $device->device_name . '" sudah dibuat.');
		$this->session->set_flashdata('activation_code', $code);
		$this->session->set_flashdata('activation_device_name', $device->device_name);
		$this->session->set_flashdata('activation_url', app_url() . 'login_device/activate?token=' . urlencode($url_token));
		redirect('login_device/list_devices');
	}

	/* ============ DAFTAR DEVICE ============ */
	public function list_devices() {
		if ($this->session->userdata('role_name') != 'administrator') { show_404(); return; }
		$this->db->where('device_registry.status', 1);
		$this->db->join('outlet', 'device_registry.idoutlet = outlet.idoutlet', 'left');
		$this->db->order_by('device_registry.iddevice', 'asc');
		$devices = $this->db->get('device_registry')->result();
		foreach ($devices as $d) {
			$us = az_get_device_users($d->iddevice); $names = array();
			foreach ($us as $u) $names[] = $u->name;
			$d->user_names = implode(', ', $names);
			$d->user_count = count($us);
		}
		$this->load->view('login_device/v_list', array('devices' => $devices));
	}

	public function delete($id) {
		if ($this->session->userdata('role_name') != 'administrator') { show_404(); return; }
		$id = intval($id);
		$this->db->where('iddevice', $id); $this->db->update('device_registry', array('status' => 0));
		$this->db->where('iddevice', $id); $this->db->update('device_user', array('status' => 0));
		$this->session->set_flashdata('success', 'Device dinonaktifkan');
		redirect('login_device/list_devices');
	}

	public function edit_users($iddevice = '') {
		if ($this->session->userdata('role_name') != 'administrator') { show_404(); return; }
		$iddevice = intval($iddevice);
		$this->db->where('iddevice', $iddevice); $this->db->where('status', 1);
		$device = $this->db->get('device_registry')->row();
		if (!$device) { show_404(); return; }
		if ($this->input->method() == 'post') {
			$selected = $this->input->post('iduser');
			if (!is_array($selected) || count($selected) == 0) {
				$this->session->set_flashdata('error', 'Pilih minimal 1 user.');
				redirect('login_device/edit_users/' . $iddevice); return;
			}
			az_save_device_users($iddevice, $selected);
			$this->session->set_flashdata('success', 'User untuk device "' . $device->device_name . '" berhasil diperbarui.');
			redirect('login_device/list_devices'); return;
		}
		$this->db->where('idoutlet', $device->idoutlet); $outlet = $this->db->get('outlet')->row();
		$this->db->where('iddevice', $iddevice); $this->db->where('status', 1);
		$map = $this->db->get('device_user')->result(); $sel = array();
		foreach ($map as $m) $sel[] = intval($m->iduser);
		$this->load->view('login_device/v_edit_users', array(
			'device' => $device, 'outlet_name' => $outlet ? $outlet->outlet_name : '-',
			'users' => $this->_all_users(), 'selected' => $sel,
		));
	}

	/* ============ AUTO LOGIN (perangkat sudah aktif) ============ */
	public function auto_device() {
		$iduser = intval($this->input->post('iduser'));
		$chk = az_check_device();
		if (!$chk['allowed']) { $this->session->set_flashdata('error_login', 'Device tidak dikenal. Aktifkan device dulu atau login manual.'); redirect(app_url() . 'login'); return; }
		$device = $chk['device'];
		if ($iduser <= 0) { $this->session->set_flashdata('error_login', 'Pilih user terlebih dahulu.'); redirect(app_url() . 'login'); return; }
		$this->db->where('iddevice', $device->iddevice); $this->db->where('iduser', $iduser); $this->db->where('status', 1);
		if (!$this->db->get('device_user')->row()) { $this->session->set_flashdata('error_login', 'User ini tidak diizinkan login otomatis di device ini.'); redirect(app_url() . 'login'); return; }
		$this->db->select('username, iduser, user.name as user_name, user.idrole, role.name as role_name, user.idoutlet');
		$this->db->where('user.iduser', $iduser); $this->db->where('user.status', 1);
		$this->db->join('role', 'role.idrole = user.idrole', 'left');
		$u = $this->db->get('user');
		if ($u->num_rows() == 0) { $this->session->set_flashdata('error_login', 'User tidak aktif.'); redirect(app_url() . 'login'); return; }
		$chk_time = az_check_access_time($u->row()->iduser, $u->row()->role_name);
		if (!$chk_time['ok']) { $this->session->set_flashdata('error_login', $chk_time['msg']); redirect(app_url() . 'login'); return; }
		$this->session->set_userdata('username', $u->row()->username);
		$this->session->set_userdata('iduser', $u->row()->iduser);
		$this->session->set_userdata('name', $u->row()->user_name);
		$this->session->set_userdata('idrole', $u->row()->idrole);
		$this->session->set_userdata('role_name', $u->row()->role_name);
		$this->session->set_userdata('idoutlet', $u->row()->idoutlet);
		redirect(app_url() . 'home');
	}

	/* ============ AKTIVASI VIA LINK LENGKAP ============ */
	public function activate() {
		$token = $this->input->get('token');
		if (strlen($token) == 0) { show_404(); return; }
		$device = $this->db->where('activation_token_hash', az_device_hash($token))
			->where('activation_token_expires >=', date('Y-m-d H:i:s'))->where('status', 1)
			->get('device_registry')->row();
		if (!$device) { $this->_show_activate_fail(); return; }
		$this->_do_activate($device);
	}

	/* ============ AKTIVASI VIA KODE 10 KARAKTER (FITUR BARU) ============ */
	public function activate_by_code() {
		$code = trim((string)$this->input->post('activation_code'));
		if (strlen($code) < 6) {
			$this->session->set_flashdata('error_login', 'Kode aktivasi tidak valid.');
			redirect(app_url() . 'login'); return;
		}
		$device = $this->db->where('activation_code_hash', az_device_hash($code))
			->where('activation_token_expires >=', date('Y-m-d H:i:s'))->where('status', 1)
			->get('device_registry')->row();
		if (!$device) {
			$this->session->set_flashdata('error_login', 'Kode aktivasi salah / sudah kedaluwarsa / sudah dipakai. Minta kode baru ke admin.');
			redirect(app_url() . 'login'); return;
		}
		$this->_do_activate($device);
	}

	// proses aktivasi (dipakai activate & activate_by_code)
	private function _do_activate($device) {
		$recovery_token = az_issue_device_tokens($device->iddevice, true);
		$this->db->where('iddevice', $device->iddevice);
		$this->db->update('device_registry', array(
			'activated' => 1,
			'activation_token_hash' => null,
			'activation_token_expires' => null,
			'activation_code_hash' => null,
		));
		$this->load->view('login_device/v_activate', array(
			'recovery_token' => $recovery_token, 'device_name' => $device->device_name,
		));
	}

	private function _show_activate_fail() {
		echo '<div style="font-family:Arial;padding:30px;max-width:600px;margin:0 auto;">'
		   . '<h3>Kode / link tidak bisa dipakai.</h3>'
		   . '<p>Penyebab: sudah pernah dipakai, sudah lewat 24 jam, atau salah ketik.</p>'
		   . '<p><b>Solusi:</b> minta admin klik <b>"Kirim Ulang Kode"</b>, lalu ketik kode 10 karakter baru di halaman login perangkat ini.</p></div>';
	}

	/* ============ PEMULIHAN OTOMATIS (cookie hilang, recovery masih ada) ============ */
	public function recover_device() {
		header('Content-Type: application/json');
		$input = json_decode(file_get_contents('php://input'), true); if (!is_array($input)) $input = array();
		$recovery = isset($input['recovery_token']) ? $input['recovery_token'] : '';
		if (strlen($recovery) == 0) { echo json_encode(array('err_code' => 1, 'err_message' => 'Recovery token kosong.')); return; }
		$device = $this->db->where('status', 1)->where('recovery_token_hash', az_device_hash($recovery))
			->where('recovery_token_status', 'active')->get('device_registry')->row();
		if (!$device) { echo json_encode(array('err_code' => 1, 'err_message' => 'Recovery token tidak valid.')); return; }
		$new_recovery = az_issue_device_tokens($device->iddevice, true);
		echo json_encode(array('err_code' => 0, 'err_message' => 'OK', 'recovery_token' => $new_recovery, 'iddevice' => $device->iddevice));
	}

	/* ============ LAPOR KE ADMIN (semua hilang) ============ */
	public function request_recovery() {
		header('Content-Type: application/json');
		$input = json_decode(file_get_contents('php://input'), true); if (!is_array($input)) $input = array();
		$this->db->insert('device_recovery_request', array(
			'iddevice' => null,
			'device_name' => isset($input['device_name']) ? $input['device_name'] : '',
			'ip_address' => $this->input->ip_address(),
			'user_agent' => substr((string)$this->input->user_agent(), 0, 255),
			'reason' => 'Cookie/recovery token hilang',
			'status' => 'pending',
			'created' => date('Y-m-d H:i:s'),
		));
		echo json_encode(array('err_code' => 0, 'err_message' => 'Laporan terkirim ke admin.'));
	}

	public function recovery_requests() {
		if ($this->session->userdata('role_name') != 'administrator') { show_404(); return; }
		$this->db->order_by('created', 'desc');
		$this->load->view('login_device/v_recovery_requests', array('requests' => $this->db->get('device_recovery_request')->result()));
	}
}