<?php
/**
 * User Management Controller
 */
class UserController extends Controller {
    
    /**
     * List all users
     */
    public function index() {
        if (!Auth::can('users.manage')) {
            $this->redirect('dashboard', ['error' => 'You do not have permission to manage users']);
            return;
        }
        
        $users = Database::fetchAll(
            "SELECT u.*, 
                    GROUP_CONCAT(r.role_name SEPARATOR ', ') as role_names,
                    c.command_name,
                    z.zone_name
             FROM users u
             LEFT JOIN user_roles ur ON u.id = ur.user_id
             LEFT JOIN roles r ON ur.role_id = r.id
             LEFT JOIN commands c ON u.command_id = c.id
             LEFT JOIN zones z ON c.zone_id = z.id
             GROUP BY u.id
             ORDER BY u.created_at DESC"
        );
        
        if ($users === false) $users = [];
        
        $this->view('users/index', ['users' => $users]);
    }
    
    /**
     * Show create user form
     */
    public function create() {
        if (!Auth::can('users.manage')) {
            $this->redirect('dashboard', ['error' => 'You do not have permission to create users']);
            return;
        }
        
        $roles = Database::fetchAll("SELECT * FROM roles ORDER BY role_name");
        $zones = Database::fetchAll("SELECT * FROM zones ORDER BY zone_name");
        
        if ($roles === false) $roles = [];
        if ($zones === false) $zones = [];
        
        $this->view('users/create', [
            'roles' => $roles,
            'zones' => $zones
        ]);
    }
    
    /**
     * Show edit user form
     */
    public function edit($id) {
        if (!Auth::can('users.manage')) {
            $this->redirect('dashboard', ['error' => 'You do not have permission to edit users']);
            return;
        }
        
        // Get user details
        $user = Database::fetchOne(
            "SELECT u.*, 
                    c.command_name,
                    z.zone_name
             FROM users u
             LEFT JOIN commands c ON u.command_id = c.id
             LEFT JOIN zones z ON c.zone_id = z.id
             WHERE u.id = ?",
            [$id]
        );
        
        if (!$user) {
            $this->redirect('users', ['error' => 'User not found']);
            return;
        }
        
        // Get all roles for dropdown
        $roles = Database::fetchAll("SELECT * FROM roles ORDER BY role_name");
        if ($roles === false) $roles = [];
        
        // Get user's current role IDs
        $userRoles = Database::fetchAll("SELECT role_id FROM user_roles WHERE user_id = ?", [$id]);
        $userRoleIds = [];
        if ($userRoles) {
            $userRoleIds = array_column($userRoles, 'role_id');
        }
        
        // Get all zones for dropdown
        $zones = Database::fetchAll("SELECT * FROM zones ORDER BY zone_name");
        if ($zones === false) $zones = [];
        
        $this->view('users/edit', [
            'user' => $user,
            'roles' => $roles,
            'userRoleIds' => $userRoleIds,
            'zones' => $zones
        ]);
    }
    
    /**
     * Store new user
     */
    public function store() {
        if (!Auth::can('users.manage')) {
            $this->redirect('dashboard', ['error' => 'You do not have permission to create users']);
            return;
        }
        
        // Validate CSRF token
        if (!Security::validateCsrfToken($_POST['csrf_token'] ?? '')) {
            $this->redirect('users/create', ['error' => 'Invalid security token']);
            return;
        }
        
        // Manual validation
        $errors = [];
        
        if (empty($_POST['username'])) {
            $errors['username'] = 'Username is required';
        } elseif (strlen($_POST['username']) < 3) {
            $errors['username'] = 'Username must be at least 3 characters';
        } elseif (strlen($_POST['username']) > 50) {
            $errors['username'] = 'Username must not exceed 50 characters';
        } else {
            $existing = Database::fetchOne("SELECT id FROM users WHERE username = ?", [$_POST['username']]);
            if ($existing) {
                $errors['username'] = 'Username already exists';
            }
        }
        
        if (empty($_POST['email'])) {
            $errors['email'] = 'Email is required';
        } elseif (!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
            $errors['email'] = 'Invalid email format';
        } else {
            $existing = Database::fetchOne("SELECT id FROM users WHERE email = ?", [$_POST['email']]);
            if ($existing) {
                $errors['email'] = 'Email already exists';
            }
        }
        
        if (empty($_POST['password'])) {
            $errors['password'] = 'Password is required';
        } elseif (strlen($_POST['password']) < 8) {
            $errors['password'] = 'Password must be at least 8 characters';
        }
        
        if (empty($_POST['confirm_password'])) {
            $errors['confirm_password'] = 'Confirm password is required';
        } elseif ($_POST['password'] !== $_POST['confirm_password']) {
            $errors['confirm_password'] = 'Passwords do not match';
        }
        
        if (empty($_POST['full_name'])) {
            $errors['full_name'] = 'Full name is required';
        } elseif (strlen($_POST['full_name']) > 100) {
            $errors['full_name'] = 'Full name must not exceed 100 characters';
        }
        
        if (empty($_POST['nis_number'])) {
            $errors['nis_number'] = 'NIS number is required';
        } else {
            $existing = Database::fetchOne("SELECT id FROM users WHERE nis_number = ?", [$_POST['nis_number']]);
            if ($existing) {
                $errors['nis_number'] = 'NIS number already exists';
            }
        }
        
        if (empty($_POST['rank'])) {
            $errors['rank'] = 'Rank is required';
        }
        
        if (empty($_POST['command_id'])) {
            $errors['command_id'] = 'Command is required';
        }
        
        if (empty($_POST['phone'])) {
            $errors['phone'] = 'Phone number is required';
        } elseif (strlen($_POST['phone']) > 20) {
            $errors['phone'] = 'Phone number must not exceed 20 characters';
        }
        
        if (!isset($_POST['roles']) || empty($_POST['roles'])) {
            $errors['roles'] = 'At least one role must be selected';
        }
        
        if (!empty($errors)) {
            Session::set('errors', $errors);
            Session::set('old', $_POST);
            $this->redirect('users/create');
            return;
        }
        
        Database::beginTransaction();
        
        try {
            // Hash password
            $passwordHash = password_hash($_POST['password'], PASSWORD_DEFAULT);
            
            // Insert user
            $userId = Database::insert('users', [
                'username' => $_POST['username'],
                'email' => $_POST['email'],
                'password_hash' => $passwordHash,
                'full_name' => $_POST['full_name'],
                'nis_number' => $_POST['nis_number'],
                'rank' => $_POST['rank'],
                'command_id' => $_POST['command_id'],
                'phone' => $_POST['phone'],
                'is_active' => 1,
                'created_by' => Auth::id(),
                'created_at' => date('Y-m-d H:i:s'),
                'updated_at' => date('Y-m-d H:i:s')
            ]);
            
            if (!$userId) {
                throw new Exception("Failed to insert user");
            }
            
            // Assign roles
            foreach ($_POST['roles'] as $roleId) {
                $roleAssignId = Database::insert('user_roles', [
                    'user_id' => $userId,
                    'role_id' => $roleId,
                    'assigned_by' => Auth::id(),
                    'assigned_at' => date('Y-m-d H:i:s')
                ]);
                
                if (!$roleAssignId) {
                    throw new Exception("Failed to assign role");
                }
            }
            
            Database::commit();
            
            // Log audit
            if (class_exists('AuditLogger')) {
                AuditLogger::logCreate('users', $userId, $_POST);
            }
            
            Session::set('success', 'User created successfully!');
            $this->redirect('users');
            
        } catch (Exception $e) {
            Database::rollBack();
            error_log("User creation error: " . $e->getMessage());
            Session::set('error', 'Failed to create user: ' . $e->getMessage());
            $this->redirect('users/create');
        }
    }
    
    /**
     * Update user
     */
    public function update($id) {
        if (!Auth::can('users.manage')) {
            $this->redirect('dashboard', ['error' => 'You do not have permission to edit users']);
            return;
        }
        
        if (!Security::validateCsrfToken($_POST['csrf_token'] ?? '')) {
            $this->redirect("users/edit/$id", ['error' => 'Invalid security token']);
            return;
        }
        
        $oldData = Database::fetchOne("SELECT * FROM users WHERE id = ?", [$id]);
        
        if (!$oldData) {
            $this->redirect('users', ['error' => 'User not found']);
            return;
        }
        
        // Validation logic
        $errors = [];
        
        if (empty($_POST['username'])) {
            $errors['username'] = 'Username is required';
        } elseif (strlen($_POST['username']) < 3) {
            $errors['username'] = 'Username must be at least 3 characters';
        } elseif (strlen($_POST['username']) > 50) {
            $errors['username'] = 'Username must not exceed 50 characters';
        } elseif ($_POST['username'] !== $oldData['username']) {
            $existing = Database::fetchOne("SELECT id FROM users WHERE username = ? AND id != ?", [$_POST['username'], $id]);
            if ($existing) {
                $errors['username'] = 'Username already exists';
            }
        }
        
        if (empty($_POST['email'])) {
            $errors['email'] = 'Email is required';
        } elseif (!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
            $errors['email'] = 'Invalid email format';
        } elseif ($_POST['email'] !== $oldData['email']) {
            $existing = Database::fetchOne("SELECT id FROM users WHERE email = ? AND id != ?", [$_POST['email'], $id]);
            if ($existing) {
                $errors['email'] = 'Email already exists';
            }
        }
        
        if (empty($_POST['full_name'])) {
            $errors['full_name'] = 'Full name is required';
        } elseif (strlen($_POST['full_name']) > 100) {
            $errors['full_name'] = 'Full name must not exceed 100 characters';
        }
        
        if (empty($_POST['nis_number'])) {
            $errors['nis_number'] = 'NIS number is required';
        } elseif ($_POST['nis_number'] !== $oldData['nis_number']) {
            $existing = Database::fetchOne("SELECT id FROM users WHERE nis_number = ? AND id != ?", [$_POST['nis_number'], $id]);
            if ($existing) {
                $errors['nis_number'] = 'NIS number already exists';
            }
        }
        
        if (empty($_POST['rank'])) {
            $errors['rank'] = 'Rank is required';
        }
        
        if (empty($_POST['command_id'])) {
            $errors['command_id'] = 'Command is required';
        }
        
        if (empty($_POST['phone'])) {
            $errors['phone'] = 'Phone number is required';
        } elseif (strlen($_POST['phone']) > 20) {
            $errors['phone'] = 'Phone number must not exceed 20 characters';
        }
        
        if (!empty($_POST['password'])) {
            if (strlen($_POST['password']) < 8) {
                $errors['password'] = 'Password must be at least 8 characters';
            }
            if (empty($_POST['confirm_password'])) {
                $errors['confirm_password'] = 'Confirm password is required';
            } elseif ($_POST['password'] !== $_POST['confirm_password']) {
                $errors['confirm_password'] = 'Passwords do not match';
            }
        }
        
        if (!isset($_POST['roles']) || empty($_POST['roles'])) {
            $errors['roles'] = 'At least one role must be selected';
        }
        
        if (!empty($errors)) {
            Session::set('errors', $errors);
            $this->redirect("users/edit/$id");
            return;
        }
        
        Database::beginTransaction();
        
        try {
            $updateData = [
                'username' => $_POST['username'],
                'email' => $_POST['email'],
                'full_name' => $_POST['full_name'],
                'nis_number' => $_POST['nis_number'],
                'rank' => $_POST['rank'],
                'command_id' => $_POST['command_id'],
                'phone' => $_POST['phone'],
                'is_active' => isset($_POST['is_active']) ? 1 : 0,
                'updated_at' => date('Y-m-d H:i:s')
            ];
            
            if (!empty($_POST['password'])) {
                $updateData['password_hash'] = password_hash($_POST['password'], PASSWORD_DEFAULT);
            }
            
            Database::update('users', $updateData, 'id = ?', [$id]);
            
            // Update roles
            Database::delete('user_roles', 'user_id = ?', [$id]);
            
            foreach ($_POST['roles'] as $roleId) {
                Database::insert('user_roles', [
                    'user_id' => $id,
                    'role_id' => $roleId,
                    'assigned_by' => Auth::id(),
                    'assigned_at' => date('Y-m-d H:i:s')
                ]);
            }
            
            Database::commit();
            
            if (class_exists('AuditLogger')) {
                AuditLogger::logUpdate('users', $id, $oldData, $updateData);
            }
            
            Session::set('success', 'User updated successfully!');
            $this->redirect('users');
            
        } catch (Exception $e) {
            Database::rollBack();
            error_log("User update error: " . $e->getMessage());
            Session::set('error', 'Failed to update user: ' . $e->getMessage());
            $this->redirect("users/edit/$id");
        }
    }
    
    /**
     * Toggle user active status
     */
    public function toggleStatus($id) {
        if (!Auth::can('users.manage')) {
            $this->redirect('dashboard', ['error' => 'You do not have permission to change user status']);
            return;
        }
        
        if ($id == Auth::id()) {
            Session::set('error', 'You cannot change your own status');
            $this->redirect('users');
            return;
        }
        
        $user = Database::fetchOne("SELECT * FROM users WHERE id = ?", [$id]);
        
        if (!$user) {
            Session::set('error', 'User not found');
            $this->redirect('users');
            return;
        }
        
        $newStatus = $user['is_active'] ? 0 : 1;
        $statusText = $newStatus ? 'activated' : 'deactivated';
        
        Database::update('users', ['is_active' => $newStatus], 'id = ?', [$id]);
        
        if (class_exists('AuditLogger')) {
            AuditLogger::log('STATUS_CHANGE', 'users', $id, null, 
                "User status changed to " . ($newStatus ? 'active' : 'inactive'));
        }
        
        Session::set('success', 'User "' . $user['username'] . '" has been ' . $statusText . ' successfully.');
        $this->redirect('users');
    }
    
    /**
     * Show user details
     */
    public function show($id) {
        if (!Auth::can('users.manage')) {
            $this->redirect('dashboard', ['error' => 'You do not have permission to view user details']);
            return;
        }
        
        $user = Database::fetchOne(
            "SELECT u.*, 
                    GROUP_CONCAT(r.role_name SEPARATOR ', ') as role_names,
                    c.command_name,
                    z.zone_name
             FROM users u
             LEFT JOIN user_roles ur ON u.id = ur.user_id
             LEFT JOIN roles r ON ur.role_id = r.id
             LEFT JOIN commands c ON u.command_id = c.id
             LEFT JOIN zones z ON c.zone_id = z.id
             WHERE u.id = ?
             GROUP BY u.id",
            [$id]
        );
        
        if (!$user) {
            $this->redirect('users', ['error' => 'User not found']);
            return;
        }
        
        $activities = [];
        if (class_exists('AuditLogger')) {
            $activities = AuditLogger::getLogs(['user_id' => $id], 20);
        }
        
        $this->view('users/show', [
            'user' => $user,
            'activities' => $activities
        ]);
    }
    
    /**
     * Profile page (for current user)
     */
    public function profile() {
        if (!Auth::check()) {
            $this->redirect('auth/login', ['error' => 'Please login to continue']);
            return;
        }
        
        $user = Database::fetchOne(
            "SELECT u.*, c.command_name, z.zone_name
             FROM users u
             LEFT JOIN commands c ON u.command_id = c.id
             LEFT JOIN zones z ON c.zone_id = z.id
             WHERE u.id = ?",
            [Auth::id()]
        );
        
        $this->view('users/profile', ['user' => $user]);
    }
    
    /**
     * Update profile (current user)
     */
    public function updateProfile() {
        if (!Auth::check()) {
            $this->redirect('auth/login', ['error' => 'Please login to continue']);
            return;
        }
        
        if (!Security::validateCsrfToken($_POST['csrf_token'] ?? '')) {
            $this->redirect('users/profile', ['error' => 'Invalid security token']);
            return;
        }
        
        $id = Auth::id();
        $oldData = Database::fetchOne("SELECT * FROM users WHERE id = ?", [$id]);
        
        if (!$oldData) {
            $this->redirect('users/profile', ['error' => 'User not found']);
            return;
        }
        
        $errors = [];
        
        if (empty($_POST['full_name'])) {
            $errors['full_name'] = 'Full name is required';
        } elseif (strlen($_POST['full_name']) > 100) {
            $errors['full_name'] = 'Full name must not exceed 100 characters';
        }
        
        if (empty($_POST['phone'])) {
            $errors['phone'] = 'Phone number is required';
        } elseif (strlen($_POST['phone']) > 20) {
            $errors['phone'] = 'Phone number must not exceed 20 characters';
        }
        
        if (empty($_POST['email'])) {
            $errors['email'] = 'Email is required';
        } elseif (!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
            $errors['email'] = 'Invalid email format';
        } elseif ($_POST['email'] !== $oldData['email']) {
            $existing = Database::fetchOne("SELECT id FROM users WHERE email = ? AND id != ?", [$_POST['email'], $id]);
            if ($existing) {
                $errors['email'] = 'Email already exists';
            }
        }
        
        if (!empty($_POST['current_password']) || !empty($_POST['new_password'])) {
            if (empty($_POST['current_password'])) {
                $errors['current_password'] = 'Current password is required';
            } elseif (!password_verify($_POST['current_password'], $oldData['password_hash'])) {
                $errors['current_password'] = 'Current password is incorrect';
            }
            
            if (!empty($_POST['new_password'])) {
                if (strlen($_POST['new_password']) < 8) {
                    $errors['new_password'] = 'New password must be at least 8 characters';
                }
                if (empty($_POST['confirm_password'])) {
                    $errors['confirm_password'] = 'Please confirm your new password';
                } elseif ($_POST['new_password'] !== $_POST['confirm_password']) {
                    $errors['confirm_password'] = 'New passwords do not match';
                }
            }
        }
        
        if (!empty($errors)) {
            Session::set('errors', $errors);
            $this->redirect('users/profile');
            return;
        }
        
        $updateData = [
            'full_name' => $_POST['full_name'],
            'email' => $_POST['email'],
            'phone' => $_POST['phone'],
            'updated_at' => date('Y-m-d H:i:s')
        ];
        
        if (!empty($_POST['new_password'])) {
            $updateData['password_hash'] = password_hash($_POST['new_password'], PASSWORD_DEFAULT);
        }
        
        Database::update('users', $updateData, 'id = ?', [$id]);
        
        if (class_exists('AuditLogger')) {
            AuditLogger::logUpdate('users', $id, $oldData, $updateData);
        }
        
        Session::set('full_name', $_POST['full_name']);
        Session::set('email', $_POST['email']);
        
        Session::set('success', 'Your profile has been updated successfully!');
        $this->redirect('users/profile');
    }
    
}
