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

/**
 * Menu_model
 * Mengelola modul/menu dan permission berbasis role
 *
 * Tabel: menu_modules, menu_permissions
 */
class Menu_model extends CI_Model {

    // ═══════════════════════════════════════════════════════════
    // GET MODULES
    // ═══════════════════════════════════════════════════════════

    /** Semua modul (flat), optional filter aktif */
    public function get_all_modules($active_only = false) {
        if ($active_only) $this->db->where('is_active', 1);
        $this->db->order_by('parent_id', 'ASC');
        $this->db->order_by('sort_order', 'ASC');
        return $this->db->get('menu_modules')->result();
    }

    /** Modul by ID */
    public function get_module_by_id($id) {
        return $this->db->get_where('menu_modules', ['id' => $id])->row();
    }

    /** Modul by slug */
    public function get_module_by_slug($slug) {
        return $this->db->get_where('menu_modules', ['slug' => $slug])->row();
    }

    /** Modul top-level (parent_id IS NULL) */
    public function get_parent_modules() {
        $this->db->where('parent_id IS NULL', null, false);
        $this->db->order_by('sort_order', 'ASC');
        return $this->db->get('menu_modules')->result();
    }

    /** Anak dari parent tertentu */
    public function get_children($parent_id) {
        $this->db->where('parent_id', $parent_id);
        $this->db->order_by('sort_order', 'ASC');
        return $this->db->get('menu_modules')->result();
    }

    /**
     * Semua modul dengan permission semua role
     * Digunakan untuk halaman pengaturan matrix
     */
    public function get_modules_with_permissions() {
        $roles  = ['admin', 'ketua_rt', 'sekretaris', 'bendahara', 'warga'];
        $modules = $this->get_all_modules();

        foreach ($modules as &$mod) {
            $mod->permissions = [];
            foreach ($roles as $role) {
                $row = $this->db->get_where('menu_permissions', [
                    'module_id' => $mod->id,
                    'role'      => $role,
                ])->row();

                $mod->permissions[$role] = $row ?: (object)[
                    'can_view'   => 0,
                    'can_create' => 0,
                    'can_edit'   => 0,
                    'can_delete' => 0,
                ];
            }
        }
        unset($mod);
        return $modules;
    }

    // ═══════════════════════════════════════════════════════════
    // GET PERMISSIONS
    // ═══════════════════════════════════════════════════════════

    /**
     * Ambil permission satu role untuk semua modul
     * Digunakan di sidebar untuk memfilter menu yang tampil
     *
     * @param  string $role
     * @return array  [ slug => (object){can_view,can_create,...} ]
     */
    public function get_permissions_for_role($role) {
        $this->db->select('mm.slug, mp.can_view, mp.can_create, mp.can_edit, mp.can_delete, mm.is_active');
        $this->db->from('menu_modules mm');
        $this->db->join('menu_permissions mp', 'mp.module_id = mm.id AND mp.role = ' . $this->db->escape($role), 'left');
        $this->db->where('mm.is_active', 1);
        $rows = $this->db->get()->result();

        $map = [];
        foreach ($rows as $r) {
            $map[$r->slug] = $r;
        }
        return $map;
    }

    /**
     * Cek satu izin spesifik untuk role + slug
     *
     * @param  string $role
     * @param  string $slug   (e.g. 'iuran')
     * @param  string $action (view|create|edit|delete)
     * @return bool
     */
    public function can($role, $slug, $action = 'view') {
        $col = 'can_' . $action;
        $allowed_cols = ['can_view', 'can_create', 'can_edit', 'can_delete'];
        if (!in_array($col, $allowed_cols)) return false;

        $this->db->select("mp.$col as allowed, mm.is_active");
        $this->db->from('menu_modules mm');
        $this->db->join('menu_permissions mp', 'mp.module_id = mm.id', 'left');
        $this->db->where('mm.slug', $slug);
        $this->db->where('mp.role', $role);
        $row = $this->db->get()->row();

        if (!$row) return false;
        return ($row->is_active && $row->allowed);
    }

    // ═══════════════════════════════════════════════════════════
    // CRUD MODULES
    // ═══════════════════════════════════════════════════════════

    public function insert_module($data) {
        $this->db->insert('menu_modules', $data);
        return $this->db->insert_id();
    }

    public function update_module($id, $data) {
        $this->db->where('id', $id);
        return $this->db->update('menu_modules', $data);
    }

    public function delete_module($id) {
        // Hapus permissions dulu (FK sudah ON DELETE CASCADE, tapi double-aman)
        $this->db->where('module_id', $id);
        $this->db->delete('menu_permissions');

        $this->db->where('id', $id);
        return $this->db->delete('menu_modules');
    }

    /** Toggle is_active modul */
    public function toggle_active($id) {
        $mod = $this->get_module_by_id($id);
        if (!$mod) return false;
        $new_val = $mod->is_active ? 0 : 1;
        $this->db->where('id', $id);
        return $this->db->update('menu_modules', [
            'is_active'  => $new_val,
            'updated_at' => date('Y-m-d H:i:s'),
        ]);
    }

    // ═══════════════════════════════════════════════════════════
    // CRUD PERMISSIONS
    // ═══════════════════════════════════════════════════════════

    /**
     * Simpan permission (INSERT or UPDATE)
     *
     * @param int    $module_id
     * @param string $role
     * @param array  $perms  ['can_view'=>1, 'can_create'=>0, ...]
     */
    public function save_permission($module_id, $role, array $perms) {
        $exists = $this->db->get_where('menu_permissions', [
            'module_id' => $module_id,
            'role'      => $role,
        ])->row();

        $data = array_merge([
            'can_view'   => 0,
            'can_create' => 0,
            'can_edit'   => 0,
            'can_delete' => 0,
            'updated_at' => date('Y-m-d H:i:s'),
        ], $perms);

        if ($exists) {
            $this->db->where('module_id', $module_id)->where('role', $role);
            return $this->db->update('menu_permissions', $data);
        } else {
            $data['module_id']  = $module_id;
            $data['role']       = $role;
            $data['created_at'] = date('Y-m-d H:i:s');
            return $this->db->insert('menu_permissions', $data);
        }
    }

    /**
     * Batch simpan semua permission dari form matrix
     * $matrix = [ module_id => [ role => [ action => 0|1 ] ] ]
     */
    public function save_permission_matrix(array $matrix) {
        $this->db->trans_start();

        foreach ($matrix as $module_id => $roles) {
            foreach ($roles as $role => $perms) {
                $this->save_permission((int)$module_id, $role, [
                    'can_view'   => (int)($perms['view']   ?? 0),
                    'can_create' => (int)($perms['create'] ?? 0),
                    'can_edit'   => (int)($perms['edit']   ?? 0),
                    'can_delete' => (int)($perms['delete'] ?? 0),
                ]);
            }
        }

        $this->db->trans_complete();
        return $this->db->trans_status();
    }

    /**
     * Salin permission dari satu role ke role lain
     */
    public function copy_permissions($from_role, $to_role) {
        $rows = $this->db->get_where('menu_permissions', ['role' => $from_role])->result();
        $this->db->trans_start();
        foreach ($rows as $r) {
            $this->save_permission($r->module_id, $to_role, [
                'can_view'   => $r->can_view,
                'can_create' => $r->can_create,
                'can_edit'   => $r->can_edit,
                'can_delete' => $r->can_delete,
            ]);
        }
        $this->db->trans_complete();
        return $this->db->trans_status();
    }

    /**
     * Reset permission role ke default (semua 0)
     */
    public function reset_role_permissions($role) {
        $this->db->where('role', $role);
        return $this->db->update('menu_permissions', [
            'can_view'   => 0,
            'can_create' => 0,
            'can_edit'   => 0,
            'can_delete' => 0,
            'updated_at' => date('Y-m-d H:i:s'),
        ]);
    }

    // ═══════════════════════════════════════════════════════════
    // STATISTIK
    // ═══════════════════════════════════════════════════════════

    /** Berapa modul aktif */
    public function count_active_modules() {
        return $this->db->where('is_active', 1)->count_all_results('menu_modules');
    }

    /** Berapa modul per role yang can_view = 1 */
    public function count_accessible_for_role($role) {
        return $this->db->where('role', $role)->where('can_view', 1)
                        ->count_all_results('menu_permissions');
    }
}