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

/**
 * One-time RBAC schema installer. Visit: /index.php/install/rbac
 * Restricted to logged-in Admin / Super Admin after first install,
 * or open when tables are missing.
 */
class Install extends CI_Controller
{
    public function __construct()
    {
        parent::__construct();
        $this->load->database();
        $this->load->library('session');
        $this->load->helper(array('url', 'rbac'));
        $this->load->model('rbac_m');
        $this->load->model('user_m');
    }

    public function rbac()
    {
        $ready = $this->rbac_m->tables_ready();
        $logged = (bool) $this->session->userdata('loggedin');

        if ($ready && $logged && !rbac_is_superadmin()) {
            show_error('Only Super Admin can re-run RBAC install.', 403);
            return;
        }
        if ($ready && !$logged) {
            // Allow first-time setup only when tables missing; if ready require login
            redirect(base_url('index.php/login'));
            return;
        }

        $messages = array();
        $ok = true;

        try {
            $this->create_tables();
            $messages[] = 'RBAC tables created / verified.';

            $this->user_m->ensure_columns();
            $messages[] = 'User table columns (role_id, status, email) ensured.';

            $this->seed_roles_modules();
            $messages[] = 'Roles and modules seeded.';

            $this->migrate_legacy_admins();
            $messages[] = 'Legacy Admin users linked to Super Admin role.';

            $super = $this->rbac_m->get_role_by_slug('superadmin');
            if ($super) {
                $this->rbac_m->grant_all_permissions($super->id, true);
                $messages[] = 'Super Admin granted all view/export permissions.';
            }

            $viewer = $this->rbac_m->get_role_by_slug('report_viewer');
            $officer = $this->rbac_m->get_role_by_slug('report_officer');
            if ($viewer) {
                $this->seed_default_report_perms($viewer->id, false);
                $messages[] = 'Report Viewer: view-only on all reports.';
            }
            if ($officer) {
                $this->seed_default_report_perms($officer->id, true);
                $messages[] = 'Report Officer: view + export on all reports.';
            }
        } catch (Exception $e) {
            $ok = false;
            $messages[] = 'Error: ' . $e->getMessage();
        }

        $this->output
            ->set_content_type('text/html')
            ->set_output($this->render_result($ok, $messages));
    }

    protected function create_tables()
    {
        $this->db->query("CREATE TABLE IF NOT EXISTS `app_roles` (
          `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
          `name` varchar(100) NOT NULL,
          `slug` varchar(100) NOT NULL,
          `description` varchar(255) DEFAULT NULL,
          `is_superadmin` tinyint(1) NOT NULL DEFAULT 0,
          `status` tinyint(1) NOT NULL DEFAULT 1,
          `created_at` datetime DEFAULT CURRENT_TIMESTAMP,
          `updated_at` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
          PRIMARY KEY (`id`),
          UNIQUE KEY `uq_app_roles_slug` (`slug`)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8");

        $this->db->query("CREATE TABLE IF NOT EXISTS `app_modules` (
          `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
          `module_key` varchar(80) NOT NULL,
          `module_name` varchar(150) NOT NULL,
          `module_group` varchar(80) NOT NULL DEFAULT 'Reports',
          `route` varchar(150) DEFAULT NULL,
          `sort_order` int(11) NOT NULL DEFAULT 0,
          `status` tinyint(1) NOT NULL DEFAULT 1,
          PRIMARY KEY (`id`),
          UNIQUE KEY `uq_app_modules_key` (`module_key`)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8");

        $this->db->query("CREATE TABLE IF NOT EXISTS `app_role_permissions` (
          `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
          `role_id` int(11) unsigned NOT NULL,
          `module_key` varchar(80) NOT NULL,
          `can_view` tinyint(1) NOT NULL DEFAULT 0,
          `can_export` tinyint(1) NOT NULL DEFAULT 0,
          PRIMARY KEY (`id`),
          UNIQUE KEY `uq_role_module` (`role_id`,`module_key`),
          KEY `idx_role_perm_module` (`module_key`)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8");

        $this->db->query("CREATE TABLE IF NOT EXISTS `app_settings` (
          `setting_key` varchar(80) NOT NULL,
          `setting_value` text NOT NULL,
          `updated_at` datetime DEFAULT NULL,
          PRIMARY KEY (`setting_key`)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8");

        $exists = $this->db->where('setting_key', 'ui_font_family')->get('app_settings')->row();
        if (!$exists) {
            $this->db->insert('app_settings', array(
                'setting_key' => 'ui_font_family',
                'setting_value' => 'ibm_plex',
                'updated_at' => date('Y-m-d H:i:s'),
            ));
        }
    }

    protected function seed_roles_modules()
    {
        $roles = array(
            array('id' => 1, 'name' => 'Super Admin', 'slug' => 'superadmin', 'description' => 'Full access to all reports and administration', 'is_superadmin' => 1, 'status' => 1),
            array('id' => 2, 'name' => 'Report Viewer', 'slug' => 'report_viewer', 'description' => 'Can view reports only (no export)', 'is_superadmin' => 0, 'status' => 1),
            array('id' => 3, 'name' => 'Report Officer', 'slug' => 'report_officer', 'description' => 'Can view and export assigned reports', 'is_superadmin' => 0, 'status' => 1),
        );
        foreach ($roles as $role) {
            $exists = $this->db->where('slug', $role['slug'])->get('app_roles')->row();
            if (!$exists) {
                $this->db->insert('app_roles', $role);
            }
        }

        $modules = array(
            array('overdue_report_details', 'Overdue Report', 'Circulation', 'report/overdue_report_details', 10),
            array('issue_report', 'Checkout Report', 'Circulation', 'report/issue_report', 20),
            array('current_checkout', 'Current Checkout Report', 'Circulation', 'report/current_checkout', 25),
            array('return_report', 'Return Report', 'Circulation', 'report/return_report', 30),
            array('circulation_report', 'Circulation Report', 'Circulation', 'report/circulation_report', 40),
            array('reservation_report', 'Reservation Report', 'Circulation', 'report/reservation_report', 50),
            array('due_clearance', 'Due Clearance Report', 'Circulation', 'report/due_clearance', 60),
            array('accession_register', 'Accession Register Report', 'Catalogue', 'report/accession_register', 70),
            array('search_catalogue_report', 'Search Catalogue Report', 'Catalogue', 'report/search_catalogue_report', 72),
            array('new_arrivals', 'New Arrivals Report', 'Catalogue', 'report/new_arrivals', 80),
            array('subject_wise_report', 'Subject Wise Report', 'Catalogue', 'report/subject_wise_report', 82),
            array('lac_new_titles_report', 'LAC New Titles Report', 'Documents', 'report/lac_new_titles_report', 185),
            array('book_report', 'Book Report', 'Catalogue', 'report/book_report', 83),
            array('patent_report', 'Patent Report', 'Catalogue', 'report/patent_report', 84),
            array('institutional_repository', 'Institutional Repository Report', 'Catalogue', 'report/institutional_repository', 85),
            array('standards_data', 'Standards Data Report', 'Catalogue', 'report/standards_data', 86),
            array('ereport_books', 'EReport Books Report', 'Catalogue', 'report/ereport_books', 87),
            array('application_notes_report', 'Application Notes Report', 'Catalogue', 'report/application_notes_report', 88),
            array('reports_book_report', 'Reports Book Report', 'Catalogue', 'report/reports_book_report', 89),
            array('journals_book_report', 'Journals Book Report', 'Catalogue', 'report/journals_book_report', 90),
            array('ebook_report', 'EBook Report', 'Catalogue', 'report/ebook_report', 91),
            array('top_books_report', 'Top Books Report', 'Circulation', 'report/top_books_report', 95),
            array('single_book_report', 'Single Catalogue History Report', 'Circulation', 'report/single_book_report', 100),
            array('overall_material_statistics_report', 'Material Statistics Report', 'Catalogue', 'report/overall_material_statistics_report', 110),
            array('publisher_year_wise_report', 'Publication Year Wise Report', 'Catalogue', 'report/publisher_year_wise_report', 120),
            array('accession_year_wise_report', 'Accession Year Wise Report', 'Catalogue', 'report/accession_year_wise_report', 122),
            array('accession_date_wise_report', 'Accession Date Wise Report', 'Catalogue', 'report/accession_date_wise_report', 123),
            array('barcode_range_report', 'Barcode Range Report', 'Catalogue', 'report/barcode_range_report', 124),
            array('price_range_report', 'Price Range Report', 'Catalogue', 'report/price_range_report', 127),
            array('publisher_person_wise_report', 'Publisher Wise Report', 'Catalogue', 'report/publisher_person_wise_report', 130),
            array('weed_out_report', 'Weed Out Report', 'Documents', 'report/weed_out_report', 186),
            array('budget_expenditure_report', 'Budget Expenditure Report', 'Acquisitions', 'report/budget_expenditure_report', 200),
            array('top_users_report', 'Top Users Report', 'Circulation', 'report/top_users_report', 140),
            array('single_user_report', 'Single User History Report', 'Circulation', 'report/single_user_report', 150),
            array('user_report', 'User Report', 'Users', 'report/user_report', 160),
            array('search_user_report', 'Search User Report', 'Users', 'report/search_user_report', 165),
            array('so_report', 'SO Report', 'Documents', 'report/so_report', 170),
            array('crv_report', 'CRV Report', 'Documents', 'report/crv_report', 180),
            array('manage_users', 'Manage Users', 'Administration', 'users', 900),
            array('manage_roles', 'Manage Roles', 'Administration', 'roles', 910),
            array('manage_permissions', 'Role Permissions', 'Administration', 'permissions', 920),
            array('manage_font_settings', 'Settings', 'Administration', 'settings', 930),
        );

        // Rename legacy checkout_report → circulation_report (modules + role perms).
        if ($this->db->table_exists('app_modules')) {
            $legacy = $this->db->where('module_key', 'checkout_report')->get('app_modules')->row();
            $modern = $this->db->where('module_key', 'circulation_report')->get('app_modules')->row();
            if ($legacy && !$modern) {
                $this->db->where('module_key', 'checkout_report')->update('app_modules', array(
                    'module_key' => 'circulation_report',
                    'module_name' => 'Circulation Report',
                    'route' => 'report/circulation_report',
                ));
            } elseif ($legacy && $modern) {
                $this->db->where('module_key', 'checkout_report')->delete('app_modules');
            }
        }
        if ($this->db->table_exists('app_role_permissions')) {
            $legacy_perms = $this->db->where('module_key', 'checkout_report')->get('app_role_permissions')->result();
            foreach ($legacy_perms as $lp) {
                $existing = $this->db
                    ->where('role_id', $lp->role_id)
                    ->where('module_key', 'circulation_report')
                    ->get('app_role_permissions')
                    ->row();
                if ($existing) {
                    $this->db->where('id', $lp->id)->delete('app_role_permissions');
                } else {
                    $this->db->where('id', $lp->id)->update('app_role_permissions', array(
                        'module_key' => 'circulation_report',
                    ));
                }
            }
        }

        foreach ($modules as $m) {
            $row = array(
                'module_key' => $m[0],
                'module_name' => $m[1],
                'module_group' => $m[2],
                'route' => $m[3],
                'sort_order' => $m[4],
                'status' => 1,
            );
            $exists = $this->db->where('module_key', $m[0])->get('app_modules')->row();
            if ($exists) {
                $this->db->where('module_key', $m[0])->update('app_modules', $row);
            } else {
                $this->db->insert('app_modules', $row);
            }
        }
    }

    protected function seed_default_report_perms($role_id, $with_export)
    {
        $modules = $this->rbac_m->get_modules(false);
        $perms = array();
        foreach ($modules as $m) {
            if (strpos($m->module_key, 'manage_') === 0) {
                continue;
            }
            $perms[$m->module_key] = array(
                'can_view' => 1,
                'can_export' => $with_export ? 1 : 0,
            );
        }
        $this->rbac_m->save_role_permissions($role_id, $perms);
    }

    protected function migrate_legacy_admins()
    {
        $super = $this->rbac_m->get_role_by_slug('superadmin');
        if (!$super || !$this->db->field_exists('role_id', 'user')) {
            return;
        }
        $this->db->where('usertype', 'Admin')
            ->group_start()
            ->where('role_id IS NULL', null, false)
            ->or_where('role_id', 0)
            ->group_end()
            ->update('user', array('role_id' => (int) $super->id, 'status' => 1));
    }

    protected function render_result($ok, $messages)
    {
        $html = '<!DOCTYPE html><html><head><meta charset="utf-8"><title>RBAC Install</title>';
        $html .= '<link rel="stylesheet" href="' . base_url('assets/dist/css/adminlte.min.css') . '">';
        $html .= '<style>body{padding:2rem;font-family:sans-serif} .box{max-width:640px;margin:auto}</style></head><body>';
        $html .= '<div class="box"><h2>RBAC Setup</h2>';
        $html .= $ok
            ? '<div class="alert alert-success">Installation completed successfully.</div>'
            : '<div class="alert alert-danger">Installation failed.</div>';
        $html .= '<ul>';
        foreach ($messages as $m) {
            $html .= '<li>' . htmlspecialchars($m) . '</li>';
        }
        $html .= '</ul>';
        $html .= '<p><strong>Important:</strong> Log out and sign in again so your session picks up the Super Admin role.</p>';
        $html .= '<p><a class="btn btn-primary" href="' . base_url('index.php/login/logout') . '">Logout &amp; Sign in</a> ';
        $html .= '<a class="btn btn-secondary" href="' . base_url('index.php/users') . '">Manage Users</a></p>';
        $html .= '</div></body></html>';
        return $html;
    }
}
