Drawaria.online Moderator Profile Dashboard

Transforms the moderator profile page into a static, Maxton-like moderation dashboard with a real chart and local avatar upload.

// ==UserScript==
// @name         Drawaria.online Moderator Profile Dashboard
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Transforms the moderator profile page into a static, Maxton-like moderation dashboard with a real chart and local avatar upload.
// @author       YouTubeDrawaria
// @match        https://drawaria.online/profile/?uid=moderator
// @grant        GM_addStyle
// @grant        GM_setValue
// @grant        GM_getValue
// @require      https://code.jquery.com/jquery-3.6.0.min.js
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.min.js
// @icon         https://www.google.com/s2/favicons?sz=64&domain=drawaria.online
// @license      MIT
// ==/UserScript==

/* global $, Chart */ // Declare Chart as a global variable for Tampermonkey

(function() {
    'use strict';

    // Remove the existing content from the target page
    $('.row').remove();

    // --- HTML TEMPLATES ---
    // The main dashboard container
    const dashboardHTML = `
        <div id="maxton-mod-dashboard">
            <div id="dashboard-header">
                <h2>Moderation Dashboard</h2>
                <div class="header-controls">
                    <button id="theme-toggle-btn" class="control-button">☀️</button>
                    <!-- Settings button removed -->
                </div>
            </div>

            <div id="dashboard-stats-grid">
                <div class="stat-card welcome-card">
                    <div class="card-content">
                        <div class="avatar-container">
                            <img src="https://drawaria.online/avatar/cache/86e33830-86ea-11ec-8553-bff27824cf71.jpg" alt="User Avatar" class="user-avatar">
                            <span class="edit-icon avatar-edit-icon" title="Edit Avatar">✏️</span>
                            <input type="file" id="avatar-upload-input" accept="image/*" style="display: none;">
                        </div>
                        <div class="user-info-text">
                            <p class="welcome-text">Welcome back</p>
                            <h3 class="user-name-container">
                                <span class="user-name">YouTubeDrawaria</span>
                                <span class="edit-icon name-edit-icon" title="Edit Name">✏️</span>
                            </h3>
                        </div>
                    </div>
                </div>

                <div class="stat-card">
                    <div class="card-header">
                        <h4>Active Users</h4>
                        <span class="card-options">...</span>
                    </div>
                    <div class="card-content">
                        <p class="stat-value" id="activeUsersValue">42.5K</p>
                        <div class="stat-detail">
                            <span class="percentage" id="activeUsersPercentage">78%</span>
                            <div class="progress-bar-container"><div class="progress-bar" id="activeUsersProgressBar" style="width: 78%;"></div></div>
                        </div>
                    </div>
                </div>

                <div class="stat-card">
                    <div class="card-header">
                        <h4>Total Users</h4>
                        <span class="card-options">...</span>
                    </div>
                    <div class="card-content">
                        <p class="stat-value" id="totalUsersValue">97.4K</p>
                        <div class="chart-wrapper">
                            <canvas id="totalUsersChart"></canvas>
                        </div>
                        <p class="stat-note" id="totalUsersNote">12.5% from last month</p>
                    </div>
                </div>

                <div class="stat-card sales-card">
                    <div class="card-content">
                        <h4 class="card-title">Today's Sales</h4>
                        <p class="stat-value" id="todaySalesValue">$65.4K</p>
                        <div class="stat-detail">
                            <span class="growth-rate" id="salesGrowthRate">78.4% Growth Rate</span>
                            <div class="progress-bar-container"><div class="progress-bar" id="salesProgressBar" style="width: 78%;"></div></div>
                        </div>
                    </div>
                </div>

                 <div class="stat-card users-card">
                    <div class="card-header">
                        <h4>Current Players</h4>
                        <input type="text" id="user-search" placeholder="Search users..." class="search-input">
                    </div>
                    <div class="card-content user-list-content">
                        <div id="user-list-container"></div>
                    </div>
                </div>

                <div class="stat-card log-card">
                    <div class="card-header">
                        <h4>Moderation Logs</h4>
                        <span class="card-options">...</span>
                    </div>
                    <div class="card-content log-list-content">
                        <div id="log-panel"></div>
                    </div>
                </div>

                <div class="stat-card reports-card">
                    <div class="card-header">
                        <h4>Pending Reports</h4>
                        <span class="card-options">...</span>
                    </div>
                    <div class="card-content">
                        <p class="stat-value" id="pendingReportsValue">3</p>
                        <p class="stat-note">New reports needing review.</p>
                        <!-- View All button removed -->
                    </div>
                </div>
            </div>
        </div>
    `;

    const modalHTML = `
        <div id="mod-action-modal" class="mod-modal">
            <div class="mod-modal-content">
                <h4 id="modal-title">Moderation Action</h4>
                <p>User: <strong id="modal-user-name"></strong></p>
                <input type="hidden" id="modal-user-id">
                <div>
                    <label for="modal-reason">Reason (Required)</label>
                    <select id="modal-reason">
                        <option>Spamming / Flooding</option>
                        <option>Inappropriate Drawing</option>
                        <option>Offensive Language</option>
                        <option>Cheating / Hacking</option>
                        <option>Other</option>
                    </select>
                </div>
                <div id="modal-duration-group">
                    <label for="modal-duration">Duration</label>
                    <select id="modal-duration">
                        <option value="300">5 Minutes</option>
                        <option value="3600">1 Hour</option>
                        <option value="86400">1 Day</option>
                        <option value="-1">Permanent</option>
                    </select>
                </div>
                <div>
                    <label for="modal-notes">Internal Notes</label>
                    <textarea id="modal-notes" rows="3" placeholder="Visible only to mods..."></textarea>
                </div>
                <div class="mod-modal-buttons">
                    <button id="modal-confirm-btn" class="confirm-btn">Confirm</button>
                    <button id="modal-cancel-btn" class="cancel-btn">Cancel</button>
                </div>
            </div>
        </div>
    `;

    // Append the new dashboard and modal to the body
    $('body').append(dashboardHTML).append(modalHTML);


    // --- STYLES (CSS) ---
    GM_addStyle(`
        :root {
            --maxton-bg-dark: #1e1f26;
            --maxton-card-bg: #2b2e3a;
            --maxton-header-bg: #2b2e3a;
            --maxton-text-light: #e0e0e0;
            --maxton-text-muted: #8a8a8a;
            --maxton-accent-blue: #7289da;
            --maxton-accent-green: #43b581;
            --maxton-accent-orange: #faa61a;
            --maxton-accent-red: #f04747;
            --maxton-border-color: #3f424c;
            --maxton-shadow: 0 4px 15px rgba(0, 0, 0, 0.4);
            --maxton-border-radius: 12px;
        }

        /* Light Mode Variables */
        :root.light-mode {
            --maxton-bg-dark: #f0f2f5;
            --maxton-card-bg: #ffffff;
            --maxton-header-bg: #e3e5e8;
            --maxton-text-light: #2e3338;
            --maxton-text-muted: #6a737d;
            --maxton-border-color: #dcdfe3;
            --maxton-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
        }

        body {
            background-color: var(--maxton-bg-dark);
            color: var(--maxton-text-light);
            font-family: 'Inter', 'Helvetica Neue', Helvetica, Arial, sans-serif; /* Prefer a modern font */
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            overflow-x: hidden;
        }

        /* Ensure the dashboard fills the primary content area */
        #maxton-mod-dashboard {
            width: 95%; /* Adjust as needed for specific page layout */
            max-width: 1400px; /* Limit max width */
            margin: 20px auto; /* Center the dashboard */
            background-color: var(--maxton-bg-dark); /* Main background */
            border-radius: var(--maxton-border-radius);
            box-shadow: var(--maxton-shadow);
            padding: 20px;
            display: flex;
            flex-direction: column;
            gap: 20px;
        }

        #dashboard-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 15px 20px;
            background-color: var(--maxton-card-bg); /* Use card background for header too */
            border-radius: var(--maxton-border-radius);
            box-shadow: var(--maxton-shadow);
            color: var(--maxton-text-light);
        }

        #dashboard-header h2 {
            margin: 0;
            font-size: 24px;
            font-weight: 600;
            color: var(--maxton-text-light);
        }

        .header-controls .control-button {
            background-color: var(--maxton-accent-blue);
            color: white;
            border: none;
            padding: 8px 15px;
            border-radius: 8px;
            cursor: pointer;
            font-size: 14px;
            margin-left: 10px;
            transition: background-color 0.3s ease;
        }
        .header-controls .control-button:hover {
            background-color: #5b73d1; /* A darker shade of blue */
        }
        #theme-toggle-btn {
            background: none;
            color: var(--maxton-text-light);
            font-size: 20px;
            border: none;
            cursor: pointer;
        }

        #dashboard-stats-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
            gap: 20px;
            flex-grow: 1; /* Allow grid to grow */
        }

        .stat-card {
            background-color: var(--maxton-card-bg);
            border-radius: var(--maxton-border-radius);
            padding: 20px;
            box-shadow: var(--maxton-shadow);
            display: flex;
            flex-direction: column;
            color: var(--maxton-text-light);
            min-height: 150px; /* Ensure cards have a minimum height */
        }

        .stat-card.welcome-card {
            grid-column: span 2; /* Make welcome card span two columns on wider screens */
            display: flex;
            align-items: center;
            background: linear-gradient(135deg, #3a3f5a, #2b2e3a); /* Gradient background */
        }
        @media (max-width: 768px) {
            .stat-card.welcome-card {
                grid-column: span 1; /* Back to single column on smaller screens */
            }
        }

        .welcome-card .card-content {
            display: flex;
            align-items: center;
            width: 100%;
        }

        /* Edit Icon Styles */
        .avatar-container, .user-name-container {
            position: relative; /* For absolute positioning of edit icons */
            display: inline-flex; /* To wrap content tightly and allow flex behavior */
            align-items: center; /* For vertical alignment of items within */
        }

        .edit-icon {
            position: absolute;
            background-color: rgba(0, 0, 0, 0.6);
            color: white;
            border-radius: 50%;
            width: 28px; /* Slightly larger icon */
            height: 28px;
            display: flex;
            justify-content: center;
            align-items: center;
            font-size: 16px;
            cursor: pointer;
            opacity: 0;
            transition: opacity 0.3s ease-in-out, background-color 0.3s ease;
            pointer-events: none; /* Do not block clicks on avatar/name by default */
            z-index: 10; /* Ensure icon is on top */
        }
        .edit-icon:hover {
            background-color: rgba(0, 0, 0, 0.8);
        }

        /* Specific positioning for avatar edit icon */
        .avatar-container {
            margin-right: 15px;
            flex-shrink: 0;
        }
        .avatar-container .edit-icon {
            right: -5px; /* Position relative to the edge of the avatar circle */
            bottom: -5px;
            transform: none; /* Remove transform if using bottom/right directly */
        }

        /* Specific positioning for name edit icon */
        .user-name-container {
            flex-grow: 1; /* Allow name container to take available space */
            margin: 5px 0 0; /* Align with previous design */
        }
        .user-name-container .edit-icon {
            position: static; /* Make it flow with text */
            margin-left: 8px; /* Space between name and icon */
            transform: none;
            background: none; /* No background for inline icon */
            color: var(--maxton-text-muted); /* Match surrounding text color */
            font-size: 16px; /* Slightly larger for text */
            width: auto; /* Reset width/height for inline text */
            height: auto;
            border-radius: 0;
        }
        .user-name-container .edit-icon:hover {
            color: var(--maxton-text-light); /* Highlight on hover */
            background: none;
        }


        /* Hover effects for showing icons */
        .avatar-container:hover .avatar-edit-icon,
        .user-name-container:hover .name-edit-icon {
            opacity: 1;
            pointer-events: auto; /* Enable clicks on hover */
        }


        .welcome-card .user-avatar {
            width: 70px;
            height: 70px;
            border-radius: 50%;
            border: 3px solid var(--maxton-accent-blue);
            display: block; /* Ensure no extra space below image */
        }
        .welcome-card .user-info-text {
            flex-grow: 1;
            display: flex; /* Make it a flex container for alignment */
            flex-direction: column;
        }
        .welcome-card .welcome-text {
            margin: 0;
            color: var(--maxton-text-muted);
            font-size: 14px;
        }
        .welcome-card .user-name {
            font-size: 22px;
            font-weight: 700;
            color: var(--maxton-text-light);
        }


        .stat-card .card-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 15px;
        }
        .stat-card .card-header h4 {
            margin: 0;
            font-size: 16px;
            color: var(--maxton-text-light);
            font-weight: 600;
        }
        .stat-card .card-options {
            color: var(--maxton-text-muted);
            cursor: pointer;
            font-size: 20px;
        }

        .stat-card .stat-value {
            font-size: 32px;
            font-weight: 700;
            margin: 0 0 10px;
            color: var(--maxton-text-light);
        }

        .stat-card .stat-detail {
            display: flex;
            align-items: center;
            font-size: 14px;
            color: var(--maxton-text-muted);
            margin-top: auto; /* Push to bottom */
        }
        .stat-card .percentage, .stat-card .growth-rate {
            font-weight: 600;
            margin-right: 10px;
            /* Colors set dynamically by JS for positive/negative */
        }
        /* Default colors, overridden by JS */
        .stat-card .percentage { color: var(--maxton-accent-green); }
        .stat-card .growth-rate { color: var(--maxton-accent-green); }
        .stat-card .negative-growth { color: var(--maxton-accent-red); }


        .progress-bar-container {
            flex-grow: 1;
            height: 6px;
            background-color: var(--maxton-border-color);
            border-radius: 3px;
            overflow: hidden;
        }
        .progress-bar {
            height: 100%;
            background-color: var(--maxton-accent-blue);
            border-radius: 3px;
        }

        .chart-wrapper {
            position: relative; /* Needed for Chart.js responsiveness */
            height: 80px; /* Control chart height within the card */
            margin-bottom: 10px;
        }
        #totalUsersChart {
            /* Chart.js handles its own sizing, but this ensures it respects container */
            max-width: 100%;
            max-height: 100%;
        }


        .stat-card .stat-note {
            font-size: 12px;
            color: var(--maxton-text-muted);
            margin-top: 5px;
        }

        .search-input {
            width: 180px;
            padding: 8px 12px;
            background-color: var(--maxton-bg-dark);
            border: 1px solid var(--maxton-border-color);
            border-radius: 8px;
            color: var(--maxton-text-light);
            font-size: 14px;
        }
        .search-input::placeholder {
            color: var(--maxton-text-muted);
        }

        .user-list-content, .log-list-content {
            flex-grow: 1;
            overflow-y: auto; /* Make lists scrollable */
            max-height: 300px; /* Limit height for scrollable content */
            padding-right: 5px; /* For scrollbar */
        }

        /* User List Specifics */
        .user-item {
            display: flex;
            align-items: center;
            padding: 8px 0;
            border-bottom: 1px solid var(--maxton-border-color);
            cursor: pointer;
            transition: background-color 0.2s;
        }
        .user-item:last-child { border-bottom: none; }
        .user-item:hover { background-color: rgba(114, 137, 218, 0.1); } /* Light hover effect */

        .user-status-icon {
            margin-right: 10px;
            font-size: 18px;
            width: 20px;
            text-align: center;
            flex-shrink: 0;
        }
        .user-status-icon.reported { color: var(--maxton-accent-orange); } /* Orange */
        .user-status-icon.banned { color: var(--maxton-accent-red); } /* Red */
        .user-status-icon.muted { color: var(--maxton-text-muted); } /* Gray */
        .user-status-icon.mod { color: var(--maxton-accent-green); } /* Green */
        .user-status-icon.active { color: var(--maxton-accent-blue); } /* Blue for active */


        .user-name {
            flex-grow: 1;
            font-weight: 500;
            color: var(--maxton-text-light);
        }
        .user-actions {
            flex-shrink: 0;
        }
        .user-actions button {
            background-color: var(--maxton-accent-blue);
            border: none;
            color: white;
            border-radius: 6px;
            margin-left: 8px;
            padding: 5px 10px;
            font-size: 11px;
            cursor: pointer;
            transition: background-color 0.2s ease;
        }
        .user-actions button:hover { background-color: #5b73d1; }


        /* Log Panel Specifics */
        #log-panel {
            padding: 0; /* Already handled by card padding */
            font-size: 13px;
            line-height: 1.5;
        }
        .log-entry {
            margin-bottom: 8px;
            border-left: 3px solid var(--maxton-border-color);
            padding-left: 10px;
            color: var(--maxton-text-light);
        }
        .log-entry.mod-action { border-left-color: var(--maxton-accent-orange); }
        .log-entry.report { border-left-color: var(--maxton-accent-red); }
        .log-entry.system { border-left-color: var(--maxton-accent-blue); }
        .log-entry.info { border-left-color: var(--maxton-text-muted); }


        /* Modal styles (retained and adjusted for theme) */
        .mod-modal {
            display: none;
            position: fixed;
            z-index: 10000;
            left: 0; top: 0;
            width: 100%; height: 100%;
            background-color: rgba(0,0,0,0.7);
            justify-content: center;
            align-items: center;
        }
        .mod-modal-content {
            background-color: var(--maxton-card-bg);
            padding: 25px;
            border-radius: var(--maxton-border-radius);
            width: 90%;
            max-width: 500px;
            box-shadow: var(--maxton-shadow);
            color: var(--maxton-text-light);
        }
        .mod-modal-content h4 { margin-top: 0; color: var(--maxton-text-light); font-size: 20px; }
        .mod-modal-content label { display: block; margin-top: 15px; color: var(--maxton-text-muted); font-size: 14px; }
        .mod-modal-content input, .mod-modal-content select, .mod-modal-content textarea {
            width: calc(100% - 20px); /* Account for padding */
            padding: 10px;
            background-color: var(--maxton-bg-dark);
            border: 1px solid var(--maxton-border-color);
            border-radius: 6px;
            color: var(--maxton-text-light);
            margin-top: 5px;
            font-size: 14px;
            resize: vertical;
        }
        .mod-modal-buttons { text-align: right; margin-top: 25px; }
        .mod-modal-buttons button { padding: 10px 20px; border: none; border-radius: 8px; cursor: pointer; font-size: 15px; transition: background-color 0.3s ease; }
        .mod-modal-buttons .confirm-btn { background-color: var(--maxton-accent-green); color: white; }
        .mod-modal-buttons .confirm-btn:hover { background-color: #3aa873; }
        .mod-modal-buttons .cancel-btn { background-color: var(--maxton-text-muted); color: white; margin-left: 10px; }
        .mod-modal-buttons .cancel-btn:hover { background-color: #72767d; }
    `);

    // Initialize the script
    const AdvancedMod = {
        state: {
            users: [],
            logs: [],
            selectedUserId: null,
            filter: '',
            theme: GM_getValue('theme', 'dark'), // Load initial theme
            chartInstance: null // To store the Chart.js instance
        },

        ui: {
            dashboard: $('#maxton-mod-dashboard'),
            userListContainer: $('#user-list-container'),
            logPanel: $('#log-panel'),
            modal: $('#mod-action-modal'),
            themeToggleBtn: $('#theme-toggle-btn'),
            avatarImage: $('.welcome-card .user-avatar'), // Reference to the image itself
            avatarUploadInput: $('#avatar-upload-input'), // Reference to the hidden file input
            userNameSpan: $('.welcome-card .user-name'),   // Reference to the name span itself
            totalUsersChartCanvas: $('#totalUsersChart'), // Reference to the chart canvas

            // References to the new randomizable elements
            activeUsersValue: $('#activeUsersValue'),
            activeUsersPercentage: $('#activeUsersPercentage'),
            activeUsersProgressBar: $('#activeUsersProgressBar'),
            totalUsersValue: $('#totalUsersValue'),
            totalUsersNote: $('#totalUsersNote'),
            todaySalesValue: $('#todaySalesValue'),
            salesGrowthRate: $('#salesGrowthRate'),
            salesProgressBar: $('#salesProgressBar'),
            pendingReportsValue: $('#pendingReportsValue')
        },

        init: function() {
            this.applyTheme(this.state.theme); // Apply theme on init
            this.bindEvents();
            this.fetchUsers(); // Initial fetch (for user list)
            this.updateDashboardStats(); // Update all random stats
            this.renderTotalUsersChart(); // Initialize chart with random data

            // Periodically refresh users to simulate real-time updates
            // TODO: Replace with actual game's user list or API fetch
            setInterval(() => this.fetchUsers(), 5000);
            // Consider periodically updating other stats if they are truly dynamic
            // setInterval(() => this.updateDashboardStats(), 30000); // e.g., every 30 seconds
        },

        // --- HELPER FUNCTIONS FOR RANDOMIZATION ---
        getRandomInt: function(min, max) {
            return Math.floor(Math.random() * (max - min + 1)) + min;
        },

        getRandomFloat: function(min, max, decimals) {
            const str = (Math.random() * (max - min) + min).toFixed(decimals);
            return parseFloat(str);
        },

        getRandomPercentage: function(min = 0, max = 100) {
            return this.getRandomInt(min, max);
        },

        getRandomSignedPercentage: function(min = -20, max = 20) { // Default for growth rates
            return this.getRandomFloat(min, max, 1);
        },

        // --- DATA HANDLING ---
        fetchUsers: function() {
            // TODO: CRITICAL - Replace this with the actual game's user list.
            // You will need to inspect the game's JavaScript objects (e.g., in the console)
            // to find where the player data is stored. It might be in an object like `game.players`
            // or received via a WebSocket message.
            this.state.users = [
                { id: 'user123', name: 'CoolPlayer_7', status: 'active', reports: 0 },
                { id: 'user456', name: 'TrollFace_LOL', status: 'reported', reports: 3 },
                { id: 'user789', name: 'ArtMaster', status: 'active', reports: 0 },
                { id: 'user101', name: 'BannedUser1', status: 'banned', reports: 12 },
                { id: 'user112', name: 'MutedGuy', status: 'muted', reports: 1 },
                { id: 'user007', name: 'TheModerator', status: 'mod', reports: 0 },
            ];
            this.addLog('User list updated.', 'system');
            this.render();
        },

        // --- RENDERING ---
        render: function() {
            this.renderUserList();
            this.renderLogs();
            // Chart and main stats are updated by specific functions, not general render
        },

        updateDashboardStats: function() {
            // Active Users
            const activeUsers = this.getRandomFloat(30, 60, 1);
            const activeUsersPercent = this.getRandomPercentage(50, 95);
            this.ui.activeUsersValue.text(`${activeUsers}K`);
            this.ui.activeUsersPercentage.text(`${activeUsersPercent}%`);
            this.ui.activeUsersProgressBar.css('width', `${activeUsersPercent}%`);

            // Total Users (main value)
            const totalUsers = this.getRandomFloat(80, 120, 1);
            this.ui.totalUsersValue.text(`${totalUsers}K`);

            // Today's Sales
            const todaySales = this.getRandomFloat(50, 90, 1);
            const salesGrowth = this.getRandomSignedPercentage(-15, 15);
            this.ui.todaySalesValue.text(`$${todaySales}K`);
            this.ui.salesGrowthRate.text(`${salesGrowth > 0 ? '+' : ''}${salesGrowth}% Growth Rate`);
            this.ui.salesGrowthRate.toggleClass('negative-growth', salesGrowth < 0);
            this.ui.salesProgressBar.css('width', `${Math.abs(salesGrowth)}%`); // Use absolute for progress bar visual

            // Pending Reports
            const pendingReports = this.getRandomInt(0, 10);
            this.ui.pendingReportsValue.text(pendingReports);

            // Re-render chart with new random data
            this.renderTotalUsersChart();
            this.ui.totalUsersNote.text(`${salesGrowth > 0 ? '+' : ''}${salesGrowth}% from last month`); // Reusing sales growth for total users note
        },

        renderUserList: function() {
            this.ui.userListContainer.empty();
            const searchTerm = $('#user-search').val().toLowerCase();

            this.state.users
                .filter(user => user.name.toLowerCase().includes(searchTerm) || user.id.toLowerCase().includes(searchTerm))
                .forEach(user => {
                const userItem = $(`
                    <div class="user-item" data-id="${user.id}">
                        <div class="user-status-icon ${user.status}" title="${user.status}">
                            ${this.getStatusIcon(user.status)}
                        </div>
                        <div class="user-name">${user.name}</div>
                        <div class="user-actions">
                            <button class="action-btn" data-action="mute">Mute</button>
                            <button class="action-btn" data-action="kick">Kick</button>
                            <button class="action-btn" data-action="ban">Ban</button>
                        </div>
                    </div>
                `);
                this.ui.userListContainer.append(userItem);
            });
        },

        renderLogs: function() {
            this.ui.logPanel.empty();
            this.state.logs.slice(-50).forEach(log => { // Show last 50 logs for a cleaner view in a card
                const logEntry = $(`<div class="log-entry ${log.type}">${log.message}</div>`);
                this.ui.logPanel.append(logEntry);
            });
            this.ui.logPanel.scrollTop(this.ui.logPanel[0].scrollHeight); // Auto-scroll to bottom
        },

        renderTotalUsersChart: function() {
            if (this.state.chartInstance) {
                this.state.chartInstance.destroy(); // Destroy existing chart if it exists
            }

            const ctx = this.ui.totalUsersChartCanvas[0].getContext('2d');

            // Generate random data for the chart (7 points for 7 months)
            const chartData = Array.from({length: 7}, (_, i) => this.getRandomInt(70000, 100000));

            this.state.chartInstance = new Chart(ctx, {
                type: 'line', // Line chart for trend
                data: {
                    labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul'],
                    datasets: [{
                        label: 'Total Users',
                        data: chartData, // Use random data
                        borderColor: 'rgb(114, 137, 218)', // maxton-accent-blue
                        backgroundColor: 'rgba(114, 137, 218, 0.2)', // Semi-transparent fill
                        fill: true,
                        tension: 0.3, // Smooth lines
                        pointRadius: 3,
                        pointBackgroundColor: 'rgb(114, 137, 218)'
                    }]
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false, // Allow custom height
                    plugins: {
                        legend: {
                            display: false // No legend
                        },
                        tooltip: {
                            mode: 'index',
                            intersect: false,
                            backgroundColor: 'var(--maxton-card-bg)', // Match theme
                            titleColor: 'var(--maxton-text-light)',
                            bodyColor: 'var(--maxton-text-light)',
                            borderColor: 'var(--maxton-border-color)',
                            borderWidth: 1
                        }
                    },
                    scales: {
                        x: {
                            grid: {
                                display: false // No grid lines on x-axis
                            },
                            ticks: {
                                color: getComputedStyle(document.documentElement).getPropertyValue('--maxton-text-muted')
                            }
                        },
                        y: {
                            beginAtZero: false,
                            grid: {
                                color: getComputedStyle(document.documentElement).getPropertyValue('--maxton-border-color') // Subtle grid lines
                            },
                            ticks: {
                                color: getComputedStyle(document.documentElement).getPropertyValue('--maxton-text-muted'),
                                callback: function(value) {
                                    return value / 1000 + 'K'; // Format as 'K'
                                }
                            }
                        }
                    }
                }
            });
        },

        // --- ACTIONS ---
        addLog: function(message, type = 'info') {
            const timestamp = new Date().toLocaleTimeString();
            this.state.logs.push({ message: `[${timestamp}] ${message}`, type });
            this.renderLogs(); // Always re-render logs when new one is added
        },

        getStatusIcon: function(status) {
            switch(status) {
                case 'reported': return '⚠️';
                case 'banned': return '🚫';
                case 'muted': return '🔇';
                case 'mod': return '🛡️';
                case 'active': return '🟢'; // Added active status icon
                default: return '👤';
            }
        },

        openModal: function(action, userId) {
            const user = this.state.users.find(u => u.id === userId);
            if (!user) return;

            this.ui.modal.find('#modal-title').text(`${action.charAt(0).toUpperCase() + action.slice(1)} User`);
            this.ui.modal.find('#modal-user-name').text(user.name);
            this.ui.modal.find('#modal-user-id').val(user.id);
            this.ui.modal.find('#modal-duration-group').toggle(action !== 'kick');
            this.ui.modal.find('#modal-confirm-btn').attr('data-action', action);
            this.ui.modal.css('display', 'flex');
        },

        executeModAction: function(action, userId, reason, duration, notes) {
            const user = this.state.users.find(u => u.id === userId);
            if (!user) return;

            const durationText = duration === "-1" ? "permanently" : `for ${duration / 60} minutes`;
            const logMessage = `User ${user.name} (${userId}) was ${action}ed. Reason: ${reason}. ${action !== 'kick' ? `Duration: ${durationText}` : ''}. Notes: ${notes}`;
            this.addLog(logMessage, 'mod-action');

            // TODO: CRITICAL - This is where you call the game's actual moderation function.
            // It could be a WebSocket call or a JS function.
            // e.g., Game.sendModAction(action, userId, reason, duration);
            console.log("Executing Action:", { action, userId, reason, duration, notes });

            // Simulate the effect on the UI
            const userIndex = this.state.users.findIndex(u => u.id === userId);
            if (userIndex !== -1) {
                if (action === 'ban') this.state.users[userIndex].status = 'banned';
                if (action === 'mute') this.state.users[userIndex].status = 'muted';
                if (action === 'kick') {
                    this.state.users.splice(userIndex, 1);
                    this.state.selectedUserId = null;
                }
            }
            this.render();
            this.ui.modal.hide();
        },

        applyTheme: function(theme) {
            this.state.theme = theme;
            // Apply theme class to <html> element, as :root variables are defined there
            document.documentElement.className = ''; // Clear existing classes
            document.documentElement.classList.add(this.state.theme + '-mode');

            // Update the toggle button icon
            this.ui.themeToggleBtn.text(this.state.theme === 'dark' ? '☀️' : '🌙');

            // Update chart colors if theme changes
            if (this.state.chartInstance) {
                // Get computed styles for dynamic colors
                const textColor = getComputedStyle(document.documentElement).getPropertyValue('--maxton-text-muted');
                const gridColor = getComputedStyle(document.documentElement).getPropertyValue('--maxton-border-color');
                const cardBg = getComputedStyle(document.documentElement).getPropertyValue('--maxton-card-bg');

                this.state.chartInstance.options.scales.x.ticks.color = textColor;
                this.state.chartInstance.options.scales.y.ticks.color = textColor;
                this.state.chartInstance.options.scales.y.grid.color = gridColor;
                // Update tooltip background for theme consistency
                this.state.chartInstance.options.plugins.tooltip.backgroundColor = cardBg;
                this.state.chartInstance.options.plugins.tooltip.titleColor = getComputedStyle(document.documentElement).getPropertyValue('--maxton-text-light');
                this.state.chartInstance.options.plugins.tooltip.bodyColor = getComputedStyle(document.documentElement).getPropertyValue('--maxton-text-light');
                this.state.chartInstance.options.plugins.tooltip.borderColor = gridColor;
                this.state.chartInstance.update();
            }
        },

        toggleTheme: function() {
            const newTheme = this.state.theme === 'dark' ? 'light' : 'dark';
            this.applyTheme(newTheme);
            GM_setValue('theme', newTheme);
        },

        // --- SETTINGS PERSISTENCE ---
        saveSettings: function() {
            GM_setValue('theme', this.state.theme);
        },

        loadSettings: function() {
            this.state.theme = GM_getValue('theme', 'dark');
            this.applyTheme(this.state.theme); // Apply theme on load
        },

        // --- EVENT BINDING ---
        bindEvents: function() {
            // Theme Toggle
            this.ui.themeToggleBtn.on('click', () => this.toggleTheme());

            // User Search
            $('#user-search').on('keyup', () => this.renderUserList());

            // User Actions (Mute, Kick, Ban buttons within user items)
            this.ui.userListContainer.on('click', '.action-btn', (e) => {
                e.stopPropagation(); // Prevent any parent click handlers
                const target = $(e.currentTarget);
                const action = target.data('action');
                const userId = target.closest('.user-item').data('id');
                this.openModal(action, userId);
            });

            // Functional Edit Avatar (triggers hidden file input)
            $('.avatar-edit-icon').on('click', () => {
                this.ui.avatarUploadInput.click(); // Programmatically click the hidden file input
            });

            // Handle file selection for avatar
            this.ui.avatarUploadInput.on('change', (e) => {
                const file = e.target.files[0];
                if (file) {
                    const reader = new FileReader();
                    reader.onload = (readEvent) => {
                        this.ui.avatarImage.attr('src', readEvent.target.result);
                        this.addLog(`Avatar updated from local file: ${file.name}`, 'mod-action');
                    };
                    reader.onerror = (errorEvent) => {
                        console.error("Error reading file:", errorEvent);
                        this.addLog(`Failed to update avatar: Could not read file.`, 'error');
                    };
                    reader.readAsDataURL(file); // Read the file as a Data URL
                } else {
                    this.addLog('Avatar update cancelled (no file selected).', 'info');
                }
                e.target.value = null; // Clear the input so same file can be selected again
            });

            // Functional Edit Name
            $('.name-edit-icon').on('click', () => {
                const newName = prompt('Enter new name:', this.ui.userNameSpan.text());
                if (newName && newName.trim() !== '') {
                    this.ui.userNameSpan.text(newName.trim());
                    this.addLog(`Name changed to: ${newName}`, 'mod-action');
                } else if (newName !== null) { // User clicked OK but entered empty/whitespace
                    this.addLog('Name update cancelled (empty name not allowed).', 'info');
                } else { // User clicked Cancel
                     this.addLog('Name update cancelled.', 'info');
                }
            });
        }
    };

    // --- START THE SCRIPT ---
    AdvancedMod.init();

})();