<?php
class UserController extends Controller
{
    public function index(Request $request): void
    {
        $this->view('users/index', [
            'title' => lang('admin.users'),
            'breadcrumbs' => [
                ['label' => lang('admin.administration'), 'url' => '/admin/users'],
                ['label' => lang('admin.users')]
            ],
        ]);
    }

    public function datatable(Request $request): void
    {
        $db = $this->db();
        $draw = (int)$request->post('draw', 1);
        $start = (int)$request->post('start', 0);
        $length = (int)$request->post('length', 25);
        $searchValue = trim($request->post('search')['value'] ?? '');
        $orderCol = (int)($request->post('order')[0]['column'] ?? 0);
        $orderDir = ($request->post('order')[0]['dir'] ?? 'desc') === 'asc' ? 'ASC' : 'DESC';

        $columns = ['u.id', 'u.username', 'u.email', 'u.full_name_en', 'r.role_name_en', 'u.is_active', 'u.last_login_at'];
        $orderColumn = $columns[$orderCol] ?? 'u.id';

        $baseWhere = "u.is_deleted = 0";
        $params = [];

        if ($searchValue !== '') {
            $baseWhere .= " AND (u.username LIKE ? OR u.email LIKE ? OR u.full_name_en LIKE ? OR u.full_name_ar LIKE ?)";
            $s = "%{$searchValue}%";
            $params = [$s, $s, $s, $s];
        }

        $totalRecords = (int)$db->fetchColumn("SELECT COUNT(*) FROM auth_users u WHERE u.is_deleted = 0");
        $filteredRecords = (int)$db->fetchColumn(
            "SELECT COUNT(*) FROM auth_users u LEFT JOIN auth_user_roles ur ON u.id = ur.user_id AND ur.is_active = 1 LEFT JOIN auth_roles r ON ur.role_id = r.id WHERE {$baseWhere}",
            $params
        );

        $rows = $db->fetchAll(
            "SELECT u.id, u.username, u.email, u.full_name_en, u.full_name_ar, u.is_active, u.is_locked, u.last_login_at, u.last_login_ip, u.created_at,
                    GROUP_CONCAT(r.role_name_en SEPARATOR ', ') as roles_en, GROUP_CONCAT(r.role_name_ar SEPARATOR ', ') as roles_ar
             FROM auth_users u
             LEFT JOIN auth_user_roles ur ON u.id = ur.user_id AND ur.is_active = 1
             LEFT JOIN auth_roles r ON ur.role_id = r.id AND r.is_active = 1
             WHERE {$baseWhere}
             GROUP BY u.id
             ORDER BY {$orderColumn} {$orderDir}
             LIMIT {$length} OFFSET {$start}",
            $params
        );

        $data = [];
        foreach ($rows as $row) {
            $statusHtml = $row['is_active']
                ? '<span class="badge bg-success">Active</span>'
                : '<span class="badge bg-secondary">Inactive</span>';
            if ($row['is_locked']) {
                $statusHtml .= ' <span class="badge bg-danger">Locked</span>';
            }

            $actions = '<div class="btn-group btn-group-sm">';
            $actions .= '<a href="/admin/users/' . $row['id'] . '/edit" class="btn btn-outline-primary" title="Edit"><i class="fas fa-edit"></i></a>';
            $actions .= '<a href="/admin/users/' . $row['id'] . '/sessions" class="btn btn-outline-info" title="Sessions"><i class="fas fa-desktop"></i></a>';
            if ($row['is_locked']) {
                $actions .= '<button class="btn btn-outline-success btn-unlock" data-id="' . $row['id'] . '" title="Unlock"><i class="fas fa-lock-open"></i></button>';
            }
            $actions .= '</div>';

            $data[] = [
                'id'         => $row['id'],
                'username'   => e($row['username']),
                'full_name'  => e($row['full_name_en']),
                'email'      => e($row['email']),
                'roles'      => e($row['roles_en'] ?? '-'),
                'status'     => $statusHtml,
                'last_login' => $row['last_login_at'] ? format_datetime($row['last_login_at']) : '-',
                'actions'    => $actions,
            ];
        }

        $this->json([
            'draw' => $draw,
            'recordsTotal' => $totalRecords,
            'recordsFiltered' => $filteredRecords,
            'data' => $data,
        ]);
    }

    public function create(Request $request): void
    {
        $db = $this->db();
        $roles = $db->fetchAll("SELECT id, role_code, role_name_en, role_name_ar FROM auth_roles WHERE is_active = 1 ORDER BY role_name_en");

        $this->view('users/form', [
            'title' => lang('admin.create_user'),
            'breadcrumbs' => [
                ['label' => lang('admin.administration'), 'url' => '/admin/users'],
                ['label' => lang('admin.users'), 'url' => '/admin/users'],
                ['label' => lang('admin.create_user')]
            ],
            'user' => null,
            'roles' => $roles,
            'userRoles' => [],
        ]);
    }

    public function store(Request $request): void
    {
        if (!CSRF::validate($request->csrfToken())) {
            $this->json(['success' => false, 'message' => 'Invalid CSRF token'], 403);
            return;
        }

        $validator = new Validator($request->all(), [
            'username'      => 'required|string|min:3|max:100',
            'email'         => 'required|email|max:191',
            'password'      => 'required|string|min:8|max:100',
            'full_name_en'  => 'required|string|max:300',
            'full_name_ar'  => 'nullable|string|max:300',
            'phone'         => 'nullable|string|max:20',
        ]);

        if ($validator->fails()) {
            $this->json(['success' => false, 'errors' => $validator->errors()], 422);
            return;
        }

        $db = $this->db();

        $exists = $db->fetchColumn("SELECT COUNT(*) FROM auth_users WHERE username = ? AND is_deleted = 0", [$request->post('username')]);
        if ($exists > 0) {
            $this->json(['success' => false, 'errors' => ['username' => ['Username already exists']]], 422);
            return;
        }

        $emailExists = $db->fetchColumn("SELECT COUNT(*) FROM auth_users WHERE email = ? AND is_deleted = 0", [$request->post('email')]);
        if ($emailExists > 0) {
            $this->json(['success' => false, 'errors' => ['email' => ['Email already exists']]], 422);
            return;
        }

        $db->beginTransaction();
        try {
            $userId = $db->insert('auth_users', [
                'username'       => $request->post('username'),
                'email'          => $request->post('email'),
                'password_hash'  => password_hash($request->post('password'), PASSWORD_BCRYPT, ['cost' => 12]),
                'full_name_en'   => $request->post('full_name_en'),
                'full_name_ar'   => $request->post('full_name_ar', ''),
                'phone'          => $request->post('phone'),
                'is_active'      => $request->post('is_active', 1) ? 1 : 0,
                'must_change_password' => $request->post('must_change_password', 0) ? 1 : 0,
                'created_by'     => Auth::id(),
            ]);

            $roleIds = $request->post('roles', []);
            if (is_array($roleIds)) {
                foreach ($roleIds as $roleId) {
                    $db->insert('auth_user_roles', [
                        'user_id'     => $userId,
                        'role_id'     => (int)$roleId,
                        'assigned_by' => Auth::id(),
                        'is_active'   => 1,
                    ]);
                }
            }

            $this->audit('create', 'auth_users', $userId, "Created user: " . $request->post('username'));
            $db->commit();
            $this->json(['success' => true, 'message' => 'User created successfully', 'redirect' => '/admin/users']);
        } catch (\Exception $e) {
            $db->rollBack();
            Logger::error('User creation failed: ' . $e->getMessage());
            $this->json(['success' => false, 'message' => 'Failed to create user'], 500);
        }
    }

    public function edit(Request $request): void
    {
        $id = (int)$request->routeParam('id');
        $db = $this->db();

        $user = $db->fetchOne("SELECT * FROM auth_users WHERE id = ? AND is_deleted = 0", [$id]);
        if (!$user) {
            $this->abort(404, 'User not found');
            return;
        }

        $roles = $db->fetchAll("SELECT id, role_code, role_name_en, role_name_ar FROM auth_roles WHERE is_active = 1 ORDER BY role_name_en");
        $userRoles = $db->fetchAll("SELECT role_id FROM auth_user_roles WHERE user_id = ? AND is_active = 1", [$id]);
        $userRoleIds = array_column($userRoles, 'role_id');

        $this->view('users/form', [
            'title' => lang('admin.edit_user'),
            'breadcrumbs' => [
                ['label' => lang('admin.administration'), 'url' => '/admin/users'],
                ['label' => lang('admin.users'), 'url' => '/admin/users'],
                ['label' => lang('admin.edit_user')]
            ],
            'user' => $user,
            'roles' => $roles,
            'userRoles' => $userRoleIds,
        ]);
    }

    public function update(Request $request): void
    {
        $id = (int)$request->routeParam('id');
        if (!CSRF::validate($request->csrfToken())) {
            $this->json(['success' => false, 'message' => 'Invalid CSRF token'], 403);
            return;
        }

        $validator = new Validator($request->all(), [
            'username'      => 'required|string|min:3|max:100',
            'email'         => 'required|email|max:191',
            'full_name_en'  => 'required|string|max:300',
            'full_name_ar'  => 'nullable|string|max:300',
            'phone'         => 'nullable|string|max:20',
        ]);

        if ($validator->fails()) {
            $this->json(['success' => false, 'errors' => $validator->errors()], 422);
            return;
        }

        $db = $this->db();

        $exists = $db->fetchColumn("SELECT COUNT(*) FROM auth_users WHERE username = ? AND id != ? AND is_deleted = 0", [$request->post('username'), $id]);
        if ($exists > 0) {
            $this->json(['success' => false, 'errors' => ['username' => ['Username already taken']]], 422);
            return;
        }

        $db->beginTransaction();
        try {
            $data = [
                'username'       => $request->post('username'),
                'email'          => $request->post('email'),
                'full_name_en'   => $request->post('full_name_en'),
                'full_name_ar'   => $request->post('full_name_ar', ''),
                'phone'          => $request->post('phone'),
                'is_active'      => $request->post('is_active', 1) ? 1 : 0,
                'must_change_password' => $request->post('must_change_password', 0) ? 1 : 0,
                'updated_at'     => date('Y-m-d H:i:s'),
            ];

            $password = $request->post('password');
            if (!empty($password) && mb_strlen($password) >= 8) {
                $data['password_hash'] = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);
                $data['password_changed_at'] = date('Y-m-d H:i:s');
            }

            $db->update('auth_users', $data, 'id = ?', [$id]);

            $db->delete('auth_user_roles', 'user_id = ? AND is_active = 1', [$id]);
            $roleIds = $request->post('roles', []);
            if (is_array($roleIds)) {
                foreach ($roleIds as $roleId) {
                    $db->insert('auth_user_roles', [
                        'user_id'     => $id,
                        'role_id'     => (int)$roleId,
                        'assigned_by' => Auth::id(),
                        'is_active'   => 1,
                    ]);
                }
            }

            $this->audit('update', 'auth_users', $id, "Updated user: " . $request->post('username'));
            $db->commit();
            $this->json(['success' => true, 'message' => 'User updated successfully', 'redirect' => '/admin/users']);
        } catch (\Exception $e) {
            $db->rollBack();
            Logger::error('User update failed: ' . $e->getMessage());
            $this->json(['success' => false, 'message' => 'Failed to update user'], 500);
        }
    }

    public function toggle(Request $request): void
    {
        $id = (int)$request->routeParam('id');
        if (!CSRF::validate($request->csrfToken())) {
            $this->json(['success' => false, 'message' => 'Invalid CSRF token'], 403);
            return;
        }
        $db = $this->db();
        $user = $db->fetchOne("SELECT id, is_active, username FROM auth_users WHERE id = ? AND is_deleted = 0", [$id]);
        if (!$user) {
            $this->json(['success' => false, 'message' => 'User not found'], 404);
            return;
        }
        $newStatus = $user['is_active'] ? 0 : 1;
        $db->update('auth_users', ['is_active' => $newStatus, 'updated_at' => date('Y-m-d H:i:s')], 'id = ?', [$id]);
        $this->audit('update', 'auth_users', $id, ($newStatus ? 'Activated' : 'Deactivated') . " user: " . $user['username']);
        $this->json(['success' => true, 'message' => 'User status updated']);
    }

    public function lock(Request $request): void
    {
        $id = (int)$request->routeParam('id');
        if (!CSRF::validate($request->csrfToken())) { $this->json(['success' => false, 'message' => 'Invalid CSRF'], 403); return; }
        $db = $this->db();
        $db->update('auth_users', [
            'is_locked' => 1,
            'locked_at' => date('Y-m-d H:i:s'),
            'lock_reason' => $request->post('reason', 'Locked by admin'),
        ], 'id = ?', [$id]);
        $this->audit('update', 'auth_users', $id, 'Locked user account');
        $this->json(['success' => true, 'message' => 'User locked']);
    }

    public function unlock(Request $request): void
    {
        $id = (int)$request->routeParam('id');
        if (!CSRF::validate($request->csrfToken())) { $this->json(['success' => false, 'message' => 'Invalid CSRF'], 403); return; }
        $db = $this->db();
        $db->update('auth_users', [
            'is_locked' => 0,
            'locked_at' => null,
            'lock_reason' => null,
            'failed_login_attempts' => 0,
        ], 'id = ?', [$id]);
        $this->audit('update', 'auth_users', $id, 'Unlocked user account');
        $this->json(['success' => true, 'message' => 'User unlocked']);
    }

    public function forcePassword(Request $request): void
    {
        $id = (int)$request->routeParam('id');
        if (!CSRF::validate($request->csrfToken())) { $this->json(['success' => false, 'message' => 'Invalid CSRF'], 403); return; }
        $this->db()->update('auth_users', ['must_change_password' => 1, 'updated_at' => date('Y-m-d H:i:s')], 'id = ?', [$id]);
        $this->audit('update', 'auth_users', $id, 'Forced password change');
        $this->json(['success' => true, 'message' => 'Password change will be required on next login']);
    }

    public function sessions(Request $request): void
    {
        $id = (int)$request->routeParam('id');
        $db = $this->db();
        $user = $db->fetchOne("SELECT id, username, full_name_en FROM auth_users WHERE id = ? AND is_deleted = 0", [$id]);
        if (!$user) { $this->abort(404); return; }

        $sessions = $db->fetchAll(
            "SELECT * FROM auth_sessions WHERE user_id = ? ORDER BY started_at DESC LIMIT 50",
            [$id]
        );

        $this->view('users/sessions', [
            'title' => 'Sessions: ' . $user['full_name_en'],
            'breadcrumbs' => [
                ['label' => lang('admin.administration'), 'url' => '/admin/users'],
                ['label' => lang('admin.users'), 'url' => '/admin/users'],
                ['label' => 'Sessions']
            ],
            'targetUser' => $user,
            'sessions' => $sessions,
        ]);
    }
}