<?php
declare(strict_types=1);

// Christo Lochenberg Developments | info@christodev.co.za | +27 61 523 9126

class AdminUsers extends Controller {
    
    public function __construct() {
        if (!isLoggedIn()) {
            header('Location: ' . URLROOT . '/users/login');
            exit;
        }

        // Allow access if they are an Admin OR if they are currently trying to return from impersonation
        if (!isAdmin() && !isset($_SESSION['admin_impersonating'])) {
            header('Location: ' . URLROOT . '/dashboard/index');
            exit;
        }
    }

    public function users(): void {
        $userModel = $this->model('User');
        $users = $userModel->getUsers();

        $data = [
            'title' => 'User Management',
            'users' => $users,
            'help_title' => 'User Matrix Guide',
            'help_content' => '
                <h4 class="font-bold text-gray-800 dark:text-gray-200 mt-0">User Matrix Overview</h4>
                <p>This is the central management interface for all registered accounts on your platform.</p>
                <h4 class="font-bold text-gray-800 dark:text-gray-200 mt-4">Available Actions</h4>
                <ul class="list-disc pl-5 space-y-2">
                    <li><strong>Impersonate:</strong> Temporarily log in as this user to troubleshoot issues or verify their workspace view. You can return to your admin session at any time using the banner at the top of the screen.</li>
                    <li><strong>Edit:</strong> Modify the user\'s personal details, system role, or active status.</li>
                    <li><strong>Delete:</strong> Permanently remove the user and all associated data from the database. This action cannot be undone.</li>
                </ul>
            '
        ];

        $this->view('admin/users', $data);
    }

    public function clients(): void {
        $userModel = $this->model('User');
        $clients = $userModel->getClients();

        $data = [
            'title' => 'Client Accounts',
            'description' => 'Manage your direct clients and subcontracted partner clients.',
            'clients' => $clients,
            'help_title' => 'Client Matrix Guide',
            'help_content' => '
                <h4 class="font-bold text-gray-800 dark:text-gray-200 mt-0">Client Management</h4>
                <p>This is your dedicated workspace for managing customer accounts without mixing them with internal staff records.</p>
                <ul class="list-disc pl-5 space-y-2 mt-2">
                    <li><strong>Add Client:</strong> Use the button at the top right to quickly onboard a new customer.</li>
                    <li><strong>Partner Links:</strong> You can see at a glance if a client belongs to you directly, or if they are linked to one of your subcontracting partners.</li>
                    <li><strong>Impersonate:</strong> You can temporarily log into any client account to see exactly what they see on their dashboard.</li>
                </ul>
            '
        ];

        $this->view('admin/clients', $data);
    }

    public function viewUser($id = null) {
        if (!$id) {
            flash('system_msg', 'Invalid user ID.', 'error');
            header('Location: ' . URLROOT . '/admin/users');
            exit;
        }

        $userId = (int)$id;
        $userModel = $this->model('User');
        $user = $userModel->getUserById($userId);

        if (!$user) {
            flash('system_msg', 'User not found.', 'error');
            header('Location: ' . URLROOT . '/admin/users');
            exit;
        }

        $data = [
            'title' => 'View User',
            'user' => $user,
            'help_title' => 'User Profile View',
            'help_content' => '
                <h4 class="font-bold text-gray-800 dark:text-gray-200 mt-0">Viewing Account Details</h4>
                <p>This is a read-only view of the user\'s profile, security settings, and timeline metrics.</p>
                <ul class="list-disc pl-5 space-y-2 mt-2">
                    <li><strong>Security Status:</strong> Check if the user has enabled Two-Factor Authentication or if their account is currently locked due to failed login attempts.</li>
                    <li><strong>Quick Actions:</strong> Use the buttons at the top right to quickly Impersonate or Edit this specific user.</li>
                </ul>
            '
        ];

        $this->view('admin/view_user', $data);
    }

    public function addUser() {
        $roleModel = $this->model('Role');
        $partnerModel = $this->model('Partner');
        
        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
            $_POST = filter_input_array(INPUT_POST, FILTER_SANITIZE_FULL_SPECIAL_CHARS);
            
            $data = [
                'name' => trim($_POST['name']),
                'company_name' => trim($_POST['company_name'] ?? ''),
                'email' => trim($_POST['email']),
                'password' => trim($_POST['password']),
                'role' => trim($_POST['role']),
                'staff_role_id' => empty($_POST['staff_role_id']) ? null : (int)$_POST['staff_role_id'],
                'partner_id' => empty($_POST['partner_id']) ? null : (int)$_POST['partner_id'],
                'is_active' => isset($_POST['is_active']) ? 1 : 0,
                'contact_number' => trim($_POST['contact_number'] ?? ''),
                'address_street' => trim($_POST['address_street'] ?? ''),
                'address_suburb' => trim($_POST['address_suburb'] ?? ''),
                'address_city' => trim($_POST['address_city'] ?? ''),
                'address_state' => trim($_POST['address_state'] ?? ''),
                'address_zip' => trim($_POST['address_zip'] ?? ''),
                'address_country' => trim($_POST['address_country'] ?? ''),
                
                'name_err' => '',
                'email_err' => '',
                'password_err' => '',
                'roles' => $roleModel->getRoles(),
                'partners' => $partnerModel->getPartners() 
            ];

            // Clean up unrelated fields based on role
            if ($data['role'] !== 'staff') { 
                $data['staff_role_id'] = null; 
            }
            if ($data['role'] !== 'client' && $data['role'] !== 'partner') { 
                $data['partner_id'] = null; 
            }
            if ($data['role'] !== 'client') {
                $data['company_name'] = null;
            }

            if ($data['role'] === 'partner' && empty($data['partner_id'])) {
                $data['name_err'] = 'You must select an existing partner agency for this user.';
            }

            $userModel = $this->model('User');

            if (empty($data['email'])) {
                $data['email_err'] = 'Please enter an email';
            } elseif ($userModel->findUserByEmail($data['email'])) {
                $data['email_err'] = 'Email is already taken';
            }

            if (empty($data['name'])) {
                $data['name_err'] = 'Please enter a name';
            }

            if (empty($data['password']) || strlen($data['password']) < 6) {
                $data['password_err'] = 'Password must be at least 6 characters';
            }

            if (empty($data['email_err']) && empty($data['name_err']) && empty($data['password_err'])) {
                
                $data['password'] = password_hash($data['password'], PASSWORD_DEFAULT);

                if ($userModel->addUserByAdmin($data)) {
                    
                    $token = bin2hex(random_bytes(32));
                    $userModel->addPasswordReset($data['email'], $token);
                    
                    $resetLink = URLROOT . '/users/resetPassword/' . $token;
                    $appName = getSettings()['app_name'] ?? SITENAME;
                    
                    $body = "<h2 style='color:#1f2937; margin-top:0;'>Welcome to {$appName}</h2>";
                    $body .= "<p>Hello {$data['name']},</p>";
                    $body .= "<p>An administrator has created an account for you. Before you can log in, you must set up a secure password for your account.</p>";
                    $body .= "<p style='text-align: center; margin: 30px 0;'><a href='{$resetLink}' style='display:inline-block; padding:12px 24px; background-color:#1c70b4; color:#ffffff; text-decoration:none; border-radius:6px; font-weight:bold;'>Set Your Password</a></p>";
                    $body .= "<p>If the button above does not work, copy and paste the following link into your browser:</p>";
                    $body .= "<p style='word-break: break-all; color: #6b7280; font-size: 14px;'>{$resetLink}</p>";

                    sendEmail($data['email'], "Welcome! Please set your password", $body);

                    systemLog('ADMIN_USER_ADDED', "Admin created a new user account: {$data['email']}. Welcome email and setup link queued.");
                    flash('system_msg', 'User added successfully! A welcome email with a password setup link has been sent to the user.', 'success');
                    
                    header('Location: ' . URLROOT . '/admin/users');
                    exit;
                }
            } else {
                $this->view('admin/add_user', $data);
            }
        } else {
            $defaultRole = isset($_GET['role']) && in_array($_GET['role'], ['admin', 'staff', 'client', 'partner']) ? $_GET['role'] : 'client';
            $data = [
                'name' => '', 'company_name' => '', 'email' => '', 'password' => '', 'role' => $defaultRole, 'staff_role_id' => null, 'partner_id' => null, 'is_active' => 1,
                'contact_number' => '', 'address_street' => '', 'address_suburb' => '', 'address_city' => '', 'address_state' => '', 'address_zip' => '', 'address_country' => '',
                'name_err' => '', 'email_err' => '', 'password_err' => '',
                'roles' => $roleModel->getRoles(),
                'partners' => $partnerModel->getPartners()
            ];
            $this->view('admin/add_user', $data);
        }
    }

    public function editUser($id = null) {
        if (!$id) {
            flash('system_msg', 'Invalid user ID.', 'error');
            header('Location: ' . URLROOT . '/admin/users');
            exit;
        }

        $userId = (int)$id;
        $userModel = $this->model('User');
        $roleModel = $this->model('Role');
        $partnerModel = $this->model('Partner');
        
        $user = $userModel->getUserById($userId);

        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
            $_POST = filter_input_array(INPUT_POST, FILTER_SANITIZE_FULL_SPECIAL_CHARS);
            
            $data = [
                'id' => $userId,
                'name' => trim($_POST['name']),
                'company_name' => trim($_POST['company_name'] ?? ''),
                'email' => trim($_POST['email']),
                'role' => trim($_POST['role']),
                'staff_role_id' => empty($_POST['staff_role_id']) ? null : (int)$_POST['staff_role_id'],
                'partner_id' => empty($_POST['partner_id']) ? null : (int)$_POST['partner_id'],
                'is_active' => isset($_POST['is_active']) ? 1 : 0,
                'contact_number' => trim($_POST['contact_number'] ?? ''),
                'address_street' => trim($_POST['address_street'] ?? ''),
                'address_suburb' => trim($_POST['address_suburb'] ?? ''),
                'address_city' => trim($_POST['address_city'] ?? ''),
                'address_state' => trim($_POST['address_state'] ?? ''),
                'address_zip' => trim($_POST['address_zip'] ?? ''),
                'address_country' => trim($_POST['address_country'] ?? ''),
                'password' => '',
                'password_err' => '',
                'roles' => $roleModel->getRoles(),
                'partners' => $partnerModel->getPartners()
            ];

            if ($data['role'] !== 'staff') { $data['staff_role_id'] = null; }
            if ($data['role'] !== 'client' && $data['role'] !== 'partner') { 
                $data['partner_id'] = null; 
            }
            if ($data['role'] !== 'client') {
                $data['company_name'] = null;
            }

            if ($data['role'] === 'partner' && empty($data['partner_id'])) {
                flash('system_msg', 'You must select an agency for this partner user.', 'error');
                $data['user'] = $user;
                $this->view('admin/edit_user', $data);
                return;
            }

            $newPassword = trim($_POST['new_password'] ?? '');
            if (!empty($newPassword)) {
                if (strlen($newPassword) < 6) {
                    $data['password_err'] = 'Password must be at least 6 characters.';
                } else {
                    $data['password'] = password_hash($newPassword, PASSWORD_DEFAULT);
                }
            }

            if ($userId === (int)$_SESSION['user_id'] && $data['is_active'] === 0) {
                flash('system_msg', 'You cannot disable your own account!', 'error');
            } elseif (!empty($data['password_err'])) {
                $data['user'] = $user;
                $this->view('admin/edit_user', $data);
                return;
            } else {
                if ($userModel->updateUserByAdmin($data)) {
                    systemLog('ADMIN_USER_UPDATED', "Admin updated permissions/details for user ID: {$userId}");
                    flash('system_msg', 'User updated successfully!', 'success');
                    header('Location: ' . URLROOT . '/admin/users');
                    exit;
                }
            }
        }

        $data = [
            'user' => $user,
            'password_err' => '',
            'roles' => $roleModel->getRoles(),
            'partners' => $partnerModel->getPartners()
        ];
        
        $this->view('admin/edit_user', $data);
    }

    public function deleteUser($id = null) {
        if ($_SERVER['REQUEST_METHOD'] == 'POST' && $id) {
            $userId = (int)$id;

            if ($userId === (int)$_SESSION['user_id']) {
                flash('system_msg', 'You cannot delete your own account!', 'error');
            } else {
                if ($this->model('User')->deleteUser($userId)) {
                    systemLog('ADMIN_USER_DELETED', "Admin permanently deleted user ID: {$userId}");
                    flash('system_msg', 'User permanently deleted!', 'success');
                } else {
                    flash('system_msg', 'Something went wrong while deleting the user.', 'error');
                }
            }

            header('Location: ' . URLROOT . '/admin/users');
            exit;
        } else {
            header('Location: ' . URLROOT . '/admin/users');
            exit;
        }
    }

    public function impersonate($id = null) {
        if ($_SERVER['REQUEST_METHOD'] == 'POST' && $id) {
            $userId = (int)$id;

            if ($userId === (int)$_SESSION['user_id']) {
                flash('system_msg', 'You cannot impersonate your own account.', 'error');
                header('Location: ' . URLROOT . '/admin/users');
                exit;
            }

            $userModel = $this->model('User');
            $targetUser = $userModel->getUserById($userId);

            if ($targetUser) {
                $_SESSION['admin_impersonating'] = [
                    'user_id' => $_SESSION['user_id'],
                    'user_email' => $_SESSION['user_email'],
                    'user_name' => $_SESSION['user_name'],
                    'user_role' => $_SESSION['user_role']
                ];

                $_SESSION['user_id'] = $targetUser->id;
                $_SESSION['user_email'] = $targetUser->email;
                $_SESSION['user_name'] = $targetUser->name;
                $_SESSION['user_role'] = $targetUser->role;

                systemLog('USER_IMPERSONATED', "Admin impersonated user ID: {$userId} ({$targetUser->email})");
                flash('system_msg', "You are now impersonating {$targetUser->name}.", 'success');
                
                if ($targetUser->role === 'admin') {
                    header('Location: ' . URLROOT . '/admin/index');
                } elseif ($targetUser->role === 'client') {
                    header('Location: ' . URLROOT . '/clientdashboard/index');
                } elseif ($targetUser->role === 'partner') {
                    header('Location: ' . URLROOT . '/partnerDashboard/index');
                } else {
                    header('Location: ' . URLROOT . '/dashboard/index');
                }
                exit;
            } else {
                flash('system_msg', 'User not found.', 'error');
                header('Location: ' . URLROOT . '/admin/users');
                exit;
            }
        } else {
            header('Location: ' . URLROOT . '/admin/users');
            exit;
        }
    }

    public function leaveImpersonation(): void {
        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
            if (isset($_SESSION['admin_impersonating'])) {
                $adminData = $_SESSION['admin_impersonating'];
                
                $_SESSION['user_id'] = $adminData['user_id'];
                $_SESSION['user_email'] = $adminData['user_email'];
                $_SESSION['user_name'] = $adminData['user_name'];
                $_SESSION['user_role'] = $adminData['user_role'];
                
                unset($_SESSION['admin_impersonating']);

                systemLog('IMPERSONATION_ENDED', "Admin ended impersonation and returned to normal session.");
                flash('system_msg', 'Impersonation ended. Welcome back.', 'success');

                header('Location: ' . URLROOT . '/admin/users');
                exit;
            }
        }
        
        header('Location: ' . URLROOT . (isClient() ? '/clientdashboard/index' : (isPartner() ? '/partnerDashboard/index' : '/dashboard/index')));
        exit;
    }
}