<?php
ob_start();
ini_set('display_errors', 1);
error_reporting(E_ALL);

// Secure Session Configuration
ini_set('session.cookie_httponly', 1);
ini_set('session.use_only_cookies', 1);
ini_set('session.cookie_secure', isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 1 : 0);
ini_set('session.cookie_samesite', 'Strict');
session_name('TEXA_MITRA_SESS'); // Isolate from main admin session
session_start();

// =============================================
// TEXA Apps Member System - JSON File Storage
// Single monolithic file - No MySQL required
// =============================================

define('SECRET_KEY', 'TEXA-FLOW-2026-SECRET');
define('CODE_LENGTH', 12);
define('DATA_DIR', __DIR__ . '/../inject/data');

// =============================================
// DATA LAYER - JSON File Storage
// =============================================
function ensureDataDir() {
    if (!is_dir(DATA_DIR)) mkdir(DATA_DIR, 0755, true);
    if (!file_exists(DATA_DIR . '/.htaccess')) {
        file_put_contents(DATA_DIR . '/.htaccess', "Deny from all\n");
    }
}

function loadData($file) {
    ensureDataDir();
    $path = DATA_DIR . '/' . $file;
    if (!file_exists($path)) return [];
    $raw = file_get_contents($path);
    return json_decode($raw, true) ?: [];
}

function saveData($file, $data) {
    ensureDataDir();
    $path = DATA_DIR . '/' . $file;
    file_put_contents($path, json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), LOCK_EX);
}

function nextId($items) {
    $max = 0;
    foreach ($items as $it) { if (isset($it['id']) && is_int($it['id']) && $it['id'] > $max) $max = $it['id']; }
    return $max + 1;
}

function generateCode($length = CODE_LENGTH) {
    $chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
    $code = '';
    for ($i = 0; $i < $length; $i++) $code .= $chars[random_int(0, strlen($chars) - 1)];
    return $code;
}

// =============================================
// SEED DEFAULT APPLICATIONS
// =============================================
function seedApps() {
    $apps = loadData('applications.json');
    if (!empty($apps)) return;
    $apps = [
        ['id'=>'google-flow','name'=>'Google Flow','icon_type'=>'image','icon_value'=>'app_icons/google_flow.png','color_gradient'=>'linear-gradient(135deg, #1a73e8, #34a0ff)','max_servers'=>5,'default_url'=>'https://labs.google/fx/tools/flow','requires_cookie'=>1,'is_active'=>1,'sort_order'=>1],
        ['id'=>'google-whisk','name'=>'Google Whisk','icon_type'=>'image','icon_value'=>'app_icons/google_whisk.png','color_gradient'=>'linear-gradient(135deg, #0f9d58, #00e676)','max_servers'=>5,'default_url'=>'https://labs.google/fx/tools/whisk','requires_cookie'=>1,'is_active'=>1,'sort_order'=>2],
        ['id'=>'grok','name'=>'Grok','icon_type'=>'image','icon_value'=>'app_icons/grok.png','color_gradient'=>'linear-gradient(135deg, #6200ea, #aa00ff)','max_servers'=>5,'default_url'=>'https://grok.com/','requires_cookie'=>1,'is_active'=>1,'sort_order'=>3],
        ['id'=>'single-sora','name'=>'Single Sora\\nRemover','icon_type'=>'image','icon_value'=>'app_icons/sora-color.png','color_gradient'=>'linear-gradient(135deg, #e8710a, #ff9800)','max_servers'=>1,'default_url'=>'https://sora-wm.vercel.app/','requires_cookie'=>0,'is_active'=>1,'sort_order'=>4],
        ['id'=>'bulk-sora','name'=>'Bulk Sora\\nRemover','icon_type'=>'image','icon_value'=>'app_icons/sora.png','color_gradient'=>'linear-gradient(135deg, #d50000, #ff1744)','max_servers'=>1,'default_url'=>'https://texa-bulk-downloader.42web.io/','requires_cookie'=>0,'is_active'=>1,'sort_order'=>5],
    ];
    saveData('applications.json', $apps);
}
seedApps();

// =============================================
// PACKAGE DEFINITIONS
// =============================================
$PACKAGES = [
    'basic'    => ['google-flow'=>3, 'google-whisk'=>3, 'single-sora'=>1],
    'pro'      => ['google-flow'=>3, 'google-whisk'=>3, 'grok'=>3, 'single-sora'=>1],
    'ultimate' => ['google-flow'=>5, 'google-whisk'=>5, 'grok'=>5, 'single-sora'=>1, 'bulk-sora'=>1],
];
$PKG_LABELS = ['basic'=>'Basic','pro'=>'Pro','ultimate'=>'Ultimate','custom'=>'Custom'];

// Build APP_LABELS, APP_MAX, APP_URLS from JSON
$allAppsData = loadData('applications.json');
$APP_LABELS = []; $APP_MAX = []; $APP_URLS_PHP = [];
foreach ($allAppsData as $app) {
    if (!$app['is_active']) continue;
    $APP_LABELS[$app['id']] = $app['name'];
    $APP_MAX[$app['id']] = (int)$app['max_servers'];
    $APP_URLS_PHP[$app['id']] = $app['default_url'] ?? '';
}
// Also build full labels (including inactive) for admin
$ALL_APP_LABELS = [];
foreach ($allAppsData as $app) { $ALL_APP_LABELS[$app['id']] = $app['name']; }

$settings = loadData('settings.json');
// Harga paket: prioritas dari packages.json (main_prices), fallback ke settings.json
$PACKAGES_CONFIG = loadData('packages.json');
$pkg_prices = $PACKAGES_CONFIG['main_prices'] ?? $settings['pkg_prices'] ?? ['basic' => 50000, 'pro' => 100000, 'ultimate' => 150000, 'custom' => 0];

// Load packages configuration (already loaded above)
if (empty($PACKAGES_CONFIG['main'])) {
    $PACKAGES_CONFIG['main'] = [
        'basic'    => ['google-flow'=>3, 'google-whisk'=>3, 'single-sora'=>1],
        'pro'      => ['google-flow'=>3, 'google-whisk'=>3, 'grok'=>3, 'single-sora'=>1],
        'ultimate' => ['google-flow'=>5, 'google-whisk'=>5, 'grok'=>5, 'single-sora'=>1, 'bulk-sora'=>1],
    ];
}

// =============================================
// DASHBOARD STATS API
// =============================================
if (isset($_GET['api_dashboard_stats']) && $_SESSION['admin_role'] === 'mitra') {
    @ob_clean(); // Ensure no previous output
    ini_set('display_errors', 0);
    header('Content-Type: application/json');
    $range = $_GET['range'] ?? '7';
    $start_date = $_GET['start_date'] ?? '';
    $end_date = $_GET['end_date'] ?? '';
    
    $today = new DateTime();
    $start = null;
    $end = new DateTime(); // default to today
    
    if ($range === 'custom' && !empty($start_date) && !empty($end_date)) {
        $start = new DateTime($start_date);
        $end = new DateTime($end_date);
    } else {
        $days = (int)$range;
        if ($days <= 0) $days = 7;
        $start = clone $today;
        $start->modify("-{$days} days");
    }
    
    $start->setTime(0, 0, 0);
    $end->setTime(23, 59, 59);
    
    $members = loadData('members.json');
    $auditLogs = file_exists(DATA_DIR . '/audit.json') ? json_decode(file_get_contents(DATA_DIR . '/audit.json'), true) : [];
    
    $new_members = 0;
    $gross_sales = 0;
    $commission = 0;
    
    $rate_config = $_SESSION['commission_rate'] ?? [];
    if (!is_array($rate_config)) {
        $rate_config = ['basic' => (int)$rate_config, 'pro' => (int)$rate_config, 'ultimate' => (int)$rate_config];
    }
    $mitra_id = $_SESSION['user_id'];
    
    // Cari waktu reset terakhir untuk mitra ini
    $last_reset_time = null;
    foreach ($auditLogs as $log) {
        if (isset($log['action']) && $log['action'] === 'reset_data_mitra' && isset($log['target_user_id']) && $log['target_user_id'] == $mitra_id) {
            $last_reset_time = new DateTime($log['time']);
        }
    }
    
    $chart_data = [];
    $period = new DatePeriod($start, new DateInterval('P1D'), clone $end->modify('+1 day'));
    foreach ($period as $dt) {
        $chart_data[$dt->format('Y-m-d')] = ['members' => 0, 'sales' => 0, 'commission' => 0];
    }
    
    foreach ($auditLogs as $log) {
        if (!isset($log['mitra_id']) || $log['mitra_id'] != $mitra_id) continue;
        
        $logTime = new DateTime($log['time']);
        
        // Skip log jika terjadi sebelum waktu reset terakhir
        if ($last_reset_time && $logTime <= $last_reset_time) continue;
        
        if ($logTime >= $start && $logTime <= $end) {
            $dateStr = $logTime->format('Y-m-d');
            if (!isset($chart_data[$dateStr])) continue;
            
            if ($log['action'] === 'add_member') {
                $new_members++;
                $chart_data[$dateStr]['members']++;
                $val = (int)($log['price'] ?? 0);
                $gross_sales += $val;
                $chart_data[$dateStr]['sales'] += $val;
                $com = (int)($log['commission'] ?? 0);
                $commission += $com;
                $chart_data[$dateStr]['commission'] += $com;
            } elseif ($log['action'] === 'upgrade_member') {
                $val = (int)($log['price_added'] ?? 0);
                $gross_sales += $val;
                $chart_data[$dateStr]['sales'] += $val;
                $com = (int)($log['commission'] ?? 0);
                $commission += $com;
                $chart_data[$dateStr]['commission'] += $com;
            } elseif ($log['action'] === 'refund_member') {
                // Refund deductions
            }
        }
    }
    
    echo json_encode([
        'status' => 'success',
        'summary' => [
            'new_members' => $new_members,
            'gross_sales' => $gross_sales,
            'commission' => $commission
        ],
        'chart' => $chart_data,
        'last_sync' => date('Y-m-d H:i:s')
    ]);
    exit;
}

// =============================================
// DO SPIN API (Mitra Only)
// =============================================
if (isset($_GET['api_do_spin']) && $_SESSION['admin_role'] === 'mitra') {
    @ob_clean();
    ini_set('display_errors', 0);
    header('Content-Type: application/json');
    
    $mitra_id = $_SESSION['user_id'];
    $users = json_decode(file_get_contents(DATA_DIR . '/users.json'), true);
    $mitra_user = null;
    $mitra_idx = -1;
    foreach ($users as $i => $u) {
        if ($u['id'] === $mitra_id && $u['role'] === 'mitra') { $mitra_user = $u; $mitra_idx = $i; break; }
    }
    
    if (!$mitra_user || ($mitra_user['spins'] ?? 0) <= 0) {
        echo json_encode(['success'=>false,'message'=>'Tidak ada sisa spin.']);
        exit;
    }
    
    $spinner_prizes = $settings['spinner_prizes'] ?? [
        ['label'=>'🎉 50 Poin','type'=>'points','value'=>50,'color'=>'#FF6384'],
        ['label'=>'💰 Rp 25rb','type'=>'deposit','value'=>25000,'color'=>'#36A2EB'],
        ['label'=>'🔄 Coba Lagi','type'=>'none','value'=>0,'color'=>'#FFCE56'],
        ['label'=>'🎯 100 Poin','type'=>'points','value'=>100,'color'=>'#4BC0C0'],
        ['label'=>'💎 Rp 50rb','type'=>'deposit','value'=>50000,'color'=>'#9966FF'],
        ['label'=>'⭐ 25 Poin','type'=>'points','value'=>25,'color'=>'#FF9F40'],
        ['label'=>'🎁 Rp 10rb','type'=>'deposit','value'=>10000,'color'=>'#FF6384'],
        ['label'=>'🍀 2x Spin','type'=>'spin','value'=>2,'color'=>'#4BC0C0']
    ];
    
    $segmentIndex = random_int(0, count($spinner_prizes) - 1);
    $prize = $spinner_prizes[$segmentIndex];
    
    // Deduct 1 spin
    $users[$mitra_idx]['spins'] = ($mitra_user['spins'] ?? 0) - 1;
    
    // Apply prize
    if ($prize['type'] === 'points') {
        $users[$mitra_idx]['points'] = ($mitra_user['points'] ?? 0) + $prize['value'];
    } elseif ($prize['type'] === 'deposit') {
        $users[$mitra_idx]['deposit_balance'] = ($mitra_user['deposit_balance'] ?? 0) + $prize['value'];
    } elseif ($prize['type'] === 'spin') {
        $users[$mitra_idx]['spins'] += $prize['value'];
    }
    
    file_put_contents(DATA_DIR . '/users.json', json_encode($users, JSON_PRETTY_PRINT));
    
    // Log spin history
    $sh = loadData('spin_history.json');
    $sh[] = ['mitra_id'=>$mitra_id,'date'=>date('Y-m-d H:i:s'),'prize'=>$prize['label'],'type'=>$prize['type'],'value'=>$prize['value']];
    saveData('spin_history.json', $sh);
    
    // Update session
    $_SESSION['balance'] = $users[$mitra_idx]['balance'] ?? 0;
    
    echo json_encode([
        'success' => true,
        'segment' => $segmentIndex,
        'prize' => $prize,
        'remaining_spins' => $users[$mitra_idx]['spins'],
        'new_points' => $users[$mitra_idx]['points'] ?? 0,
        'new_deposit' => $users[$mitra_idx]['deposit_balance'] ?? 0
    ]);
    exit;
}

// =============================================
// API MODE - JSON Response (called by extension via Worker)
// =============================================
// =============================================
// RBAC & SESSION MANAGEMENT
// =============================================
if (isset($_GET['logout'])) {
    session_destroy();
    header('Location: ?');
    exit;
}

// Ensure users.json exists with default credentials if missing
$usersFile = DATA_DIR . '/users.json';
if (!file_exists($usersFile)) {
    $defaultUsers = [
        ['id' => 1, 'role' => 'owner', 'name' => 'Owner System', 'password_hash' => password_hash('4rg0v14n', PASSWORD_BCRYPT), 'created_at' => date('Y-m-d H:i:s')],
        ['id' => 2, 'role' => 'admin', 'name' => 'Admin Default', 'password_hash' => password_hash('asu123', PASSWORD_BCRYPT), 'created_at' => date('Y-m-d H:i:s')]
    ];
    file_put_contents($usersFile, json_encode($defaultUsers, JSON_PRETTY_PRINT));
}

// Simple Rate Limiting for Login
$settings = loadData('settings.json');
$lockout_minutes = (int)($settings['mitra_lockout_minutes'] ?? 15);
$lockout_seconds = $lockout_minutes * 60;
$max_attempts = (int)($settings['mitra_max_attempts'] ?? 5);

$loginAttemptsFile = DATA_DIR . '/login_attempts.json';
function checkRateLimit() {
    global $loginAttemptsFile, $lockout_seconds, $max_attempts;
    $ip = $_SERVER['REMOTE_ADDR'];
    $attempts = file_exists($loginAttemptsFile) ? json_decode(file_get_contents($loginAttemptsFile), true) : [];
    
    // Clean old attempts
    $now = time();
    foreach ($attempts as $key => $time) {
        if ($now - $time > $lockout_seconds) unset($attempts[$key]);
    }
    
    $ipAttempts = array_filter($attempts, function($k) use ($ip) { return strpos($k, $ip) === 0; }, ARRAY_FILTER_USE_KEY);
    
    if (count($ipAttempts) >= $max_attempts) {
        file_put_contents($loginAttemptsFile, json_encode($attempts));
        return false; // Blocked
    }
    return true;
}

function recordLoginAttempt() {
    global $loginAttemptsFile;
    $ip = $_SERVER['REMOTE_ADDR'];
    $attempts = file_exists($loginAttemptsFile) ? json_decode(file_get_contents($loginAttemptsFile), true) : [];
    $attempts[$ip . '_' . time()] = time();
    file_put_contents($loginAttemptsFile, json_encode($attempts));
}

$login_error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['login_password'])) {
    if (!checkRateLimit()) {
        $login_error = "Terlalu banyak percobaan. Coba lagi dalam {$lockout_minutes} menit.";
    } else {
        $pass = $_POST['login_password'] ?? '';
        $users = json_decode(file_get_contents($usersFile), true);
        $loggedIn = false;
        
        foreach ($users as $user) {
            if ($user['role'] === 'mitra') {
                if (password_verify($pass, $user['password_hash'])) {
                    if (empty($user['is_active'])) {
                        $login_error = 'Akun mitra dinonaktifkan.';
                        break;
                    }
                    $_SESSION['admin_logged_in'] = true;
                    $_SESSION['admin_role'] = 'mitra';
                    $_SESSION['user_id'] = $user['id'];
                    $_SESSION['user_name'] = $user['name'];
                    
                    $_SESSION['commission_rate'] = $user['commission_rate'] ?? 0;
                    $_SESSION['balance'] = $user['balance'] ?? 0;
                    $_SESSION['permissions'] = [
                        'add_member' => true,
                        'edit_member' => false,
                        'inject_cookies' => false,
                        'view_stats' => true
                    ];

                    $loggedIn = true;
                    header('Location: ?');
                    exit;
                }
            }
        }
        
        if (!$loggedIn && empty($login_error)) {
            recordLoginAttempt();
            $login_error = 'Kredensial salah atau akses ditolak!';
        }
    }
}

if (empty($_SESSION['admin_logged_in']) || $_SESSION['admin_role'] !== 'mitra') {
?>
<!DOCTYPE html>
<html lang="id">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Mitra Portal - TEKNO APPS</title>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet"/>
    <style>
        :root { --bg: #001020; --deep: #020c18; --border: rgba(0,150,255,.18); --text: #e8f4ff; --bright: #0099ff; --muted: #4a7a9b; }
        body { background: var(--deep); color: var(--text); font-family: 'Inter', sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; }
        body::before{content:"";position:fixed;inset:0;pointer-events:none;background:radial-gradient(ellipse at 50% 50%,rgba(150,0,255,.15) 0%,transparent 70%);}
        .login-card { background: rgba(10,4,30,.85); padding: 40px; border-radius: 15px; border: 1px solid var(--border); width: 100%; max-width: 360px; box-shadow: 0 10px 40px rgba(0,0,0,0.5); text-align: center; position: relative; z-index: 1; backdrop-filter: blur(12px); }
        .logo { width: 50px; height: 50px; border-radius: 14px; background: linear-gradient(135deg,#9900ff,#5500cc); display: inline-flex; align-items: center; justify-content: center; font-size: 18px; font-weight: 900; box-shadow: 0 0 18px rgba(150,0,255,.4); margin-bottom: 15px; }
        .login-card h2 { color: #d8a8ff; margin-top: 0; margin-bottom: 5px; font-size: 20px; font-weight: 800; }
        .login-card p { font-size: 12px; color: var(--muted); margin-bottom: 25px; }
        input { width: 100%; padding: 12px 15px; margin-bottom: 15px; border: 1px solid var(--border); background: rgba(20,0,50,0.6); color: var(--text); border-radius: 8px; box-sizing: border-box; outline: none; font-family: 'Inter', sans-serif; font-size: 13px; transition: all 0.2s; text-align: center; letter-spacing: 1px;}
        input:focus { border-color: #aa00ff; box-shadow: 0 0 0 3px rgba(150,0,255,.15); }
        button { width: 100%; padding: 12px; background: linear-gradient(135deg,#7700cc,#9900ff); color: white; border: none; border-radius: 8px; cursor: pointer; font-weight: 700; font-size: 14px; transition: 0.3s; box-shadow: 0 4px 14px rgba(150,0,255,.3); }
        button:hover { transform: translateY(-1px); box-shadow: 0 6px 20px rgba(150,0,255,.4); }
        .err { color: #ff4d4d; font-size: 12px; margin-bottom: 15px; background: rgba(255,77,77,.1); border: 1px solid rgba(255,77,77,.3); padding: 10px; border-radius: 6px; }
    </style>
</head>
<body>
    <div class="login-card">
        <div class="logo">TX</div>
        <h2>Portal Mitra</h2>
        <p>Login Reseller & Mitra Afiliasi</p>
        <?php if($login_error) echo '<div class="err">'.$login_error.'</div>'; ?>
        <form method="POST">
            <input type="password" name="login_password" placeholder="••••••••" required autofocus autocomplete="off" style="letter-spacing:2px;">
            <button type="submit">MASUK</button>
        </form>
        <?php if (!empty($settings['mitra_wa_group'])): ?>
        <a href="<?php echo htmlspecialchars($settings['mitra_wa_group']); ?>" target="_blank" style="display:inline-block; margin-top:20px; font-size:12px; color:#25D366; text-decoration:none; font-weight:600;">
           &#x1F4F2; Gabung Grup WhatsApp Mitra
        </a>
        <?php endif; ?>
    </div>

</body>
</html>
<?php
    exit;
}

// Role-based Authorization Middleware
$role = $_SESSION['admin_role'] ?? 'admin';
$tab = $_GET['tab'] ?? 'members';

// Default perms if owner, or load from session
if ($role === 'owner') {
    $user_perms = ['add_member' => true, 'edit_member' => true, 'inject_cookies' => true, 'view_stats' => true];
} else {
    $user_perms = $_SESSION['permissions'] ?? ['add_member' => true, 'edit_member' => true, 'inject_cookies' => true, 'view_stats' => true];
}

// Admin is restricted to allowed tabs
if ($role === 'admin') {
    $allowed_tabs = ['members'];
    if ($user_perms['inject_cookies']) $allowed_tabs[] = 'cookies';
    if (!in_array($tab, $allowed_tabs)) {
        header('HTTP/1.1 403 Forbidden');
        die('<h2>403 - Akses Ditolak</h2><p>Anda tidak memiliki izin untuk mengakses halaman ini.</p><a href="?tab=members">Kembali</a>');
    }
}

// Mitra is restricted to allowed tabs
if ($role === 'mitra') {
    $allowed_tabs = ['members', 'mitradashboard', 'audit', 'products'];
    // Allow 'mitras' temporarily if returning to owner
    if (isset($_SESSION['original_owner_id']) && $tab === 'mitras') {
        $allowed_tabs[] = 'mitras';
    }
    if (!in_array($tab, $allowed_tabs)) {
        header('HTTP/1.1 403 Forbidden');
        die('<h2>403 - Akses Ditolak</h2><p>Anda tidak memiliki izin untuk mengakses halaman ini.</p><a href="?tab=members">Kembali</a>');
    }
    
    // Override pkg_prices dengan harga khusus mitra (jika ada di packages.json)
    $mitra_price_key = 'mitra_' . $_SESSION['user_id'] . '_prices';
    if (isset($PACKAGES_CONFIG[$mitra_price_key])) {
        $pkg_prices = $PACKAGES_CONFIG[$mitra_price_key];
    }
}

// Action restriction for admin & mitra
if (($role === 'admin' || $role === 'mitra') && $_SERVER['REQUEST_METHOD'] === 'POST') {
    $action = $_POST['action'] ?? '';
    $allowed_admin_actions = [];
    if ($user_perms['add_member']) $allowed_admin_actions[] = 'add';
    if ($user_perms['edit_member']) {
        $allowed_admin_actions[] = 'update';
        $allowed_admin_actions[] = 'toggle';
        $allowed_admin_actions[] = 'delete';
    }
    
    // allow return_to_owner if they are impersonating
    if (isset($_SESSION['original_owner_id'])) {
        $allowed_admin_actions[] = 'return_to_owner';
    }
    
    if ($action !== '' && !in_array($action, $allowed_admin_actions)) {
         header('HTTP/1.1 403 Forbidden');
         die('403 - Akses Ditolak untuk aksi ini. ('.$action.')');
    }
}

// =============================================
// ADMIN PANEL MODE - HTML UI
// =============================================
$msg = ''; $msgType = '';
if (isset($_SESSION['flash_msg'])) {
    $msg = $_SESSION['flash_msg'];
    $msgType = $_SESSION['flash_msgType'] ?? 'info';
    unset($_SESSION['flash_msg'], $_SESSION['flash_msgType']);
}

// Reload apps for admin (include inactive)
$allAppsForAdmin = loadData('applications.json');
usort($allAppsForAdmin, function($a,$b){ return ($a['sort_order']??0) - ($b['sort_order']??0); });
// Rebuild labels with ALL apps for admin forms
$APP_LABELS_ALL = [];
$APP_MAX_ALL = [];
foreach ($allAppsForAdmin as $app) {
    $APP_LABELS_ALL[$app['id']] = $app['name'];
    $APP_MAX_ALL[$app['id']] = (int)$app['max_servers'];
}

// Edit fetch
$editData = null;
if (isset($_GET['edit'])) {
    $eid = (int)$_GET['edit'];
    $members = loadData('members.json');
    foreach ($members as $m) { if ($m['id'] === $eid) { $editData = $m; break; } }
}

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
    $pa = $_POST['action'];

    if ($pa === 'add') {
        $name = trim($_POST['name'] ?? ''); $days = (int)($_POST['days'] ?? 7);
        $custom_code = trim($_POST['custom_code'] ?? '');
        $pkg = $_POST['package'] ?? 'basic';
        if (!array_key_exists($pkg, $PKG_LABELS)) $pkg = 'basic';
        $custom_cfg = null; // Mitra cannot set custom config
        if (empty($name) || $days < 1) { $msg='Nama wajib diisi dan durasi minimal 1 hari.'; $msgType='error'; }
        else {
            $members = loadData('members.json');
            $code = !empty($custom_code) ? $custom_code : generateCode();
            
            // Check for duplicate name
            $nameExists = false;
            foreach ($members as $m) {
                if (strtolower(trim($m['name'])) === strtolower($name)) {
                    $nameExists = true;
                    break;
                }
            }
            
            // Check uniqueness of code
            $codeExists = false;
            foreach ($members as $m) { if ($m['code'] === $code) { $codeExists = true; break; } }
            
            if ($nameExists) { 
                $msg='Nama member sudah terdaftar, harap gunakan nama lain.'; $msgType='error'; 
            } elseif ($codeExists) { 
                $msg='Kode akses sudah digunakan, coba lagi.'; $msgType='error'; 
            } else {
                global $pkg_prices;
                $PACKAGES_CONFIG = loadData('packages.json');
                
                // If manual price is set, use it. Otherwise, calculate based on package base price and days
                $manual_price_input = trim($_POST['manual_price'] ?? '');
                if ($manual_price_input !== '') {
                    $revenue = (int)$manual_price_input;
                } else {
                    $mitra_id_key = ($_SESSION['admin_role'] === 'mitra') ? 'mitra_' . $_SESSION['user_id'] . '_prices' : null;
                    $current_pkg_prices = $pkg_prices;
                    if ($mitra_id_key && isset($PACKAGES_CONFIG[$mitra_id_key])) {
                        $current_pkg_prices = $PACKAGES_CONFIG[$mitra_id_key];
                    }
                    $base_price = $current_pkg_prices[$pkg] ?? 0;
                    $revenue = (int)round(($base_price / 30) * $days);
                }
                
                $payment_status = $_POST['payment_status'] ?? 'lunas';
                if ($_SESSION['admin_role'] === 'mitra') {
                    $payment_status = 'belum_lunas'; // Force Mitra entries to un-paid by default
                }
                
                // === DEPOSIT CHECK: Block if deposit insufficient ===
                if ($_SESSION['admin_role'] === 'mitra') {
                    $users_check = json_decode(file_get_contents(DATA_DIR . '/users.json'), true);
                    $mitra_check = null;
                    foreach ($users_check as $u) { 
                        if ((int)$u['id'] == (int)$_SESSION['user_id']) { 
                            $mitra_check = $u; 
                            break; 
                        } 
                    }
                    
                    if (!$mitra_check) {
                        $msg = '⛔ Error: Data mitra tidak ditemukan. Silakan logout dan login kembali.';
                        $msgType = 'error';
                        goto skip_add_member;
                    }
                    
                    $deposit_bal = $mitra_check['deposit_balance'] ?? 0;
                    $minus_limit = $mitra_check['deposit_minus_limit'] ?? -500000;
                    
                    // Pre-calculate commission to check net deduction
                    $rate_cfg_check = $mitra_check['commission_rate'] ?? $_SESSION['commission_rate'] ?? [];
                    if (!is_array($rate_cfg_check)) {
                        $rate_cfg_check = ['basic' => (int)$rate_cfg_check, 'pro' => (int)$rate_cfg_check, 'ultimate' => (int)$rate_cfg_check];
                    }
                    $base_komisi_check = $rate_cfg_check[$pkg] ?? $rate_cfg_check['basic'] ?? 0;
                    // Komisi proporsional berdasarkan durasi (base = 30 hari)
                    $komisi_check = (int)round(($base_komisi_check / 30) * $days);
                    $net_deduction = $revenue - $komisi_check; // Harga - Komisi = yang benar-benar berkurang
                    $kredit_tersisa = $deposit_bal - $minus_limit;
                    
                    if ($net_deduction > $kredit_tersisa) {
                        $saldo_fmt = number_format($deposit_bal, 0, ',', '.');
                        $limit_fmt = number_format($minus_limit, 0, ',', '.');
                        $net_fmt = number_format($net_deduction, 0, ',', '.');
                        $kredit_fmt = number_format($kredit_tersisa, 0, ',', '.');
                        $msg = '⛔ SALDO DEPOSIT TIDAK MENCUKUPI! Silakan lakukan deposit terlebih dahulu sebelum menambah member baru.'
                             . "\n\n📊 Rincian:"
                             . "\n• Saldo saat ini: Rp " . $saldo_fmt
                             . "\n• Batas minus: Rp " . $limit_fmt
                             . "\n• Kredit tersisa: Rp " . $kredit_fmt
                             . "\n• Biaya transaksi ini (Harga - Komisi): Rp " . $net_fmt
                             . "\n\n💰 Hubungi Owner untuk melakukan top up deposit Anda.";
                        $msgType = 'error';
                        goto skip_add_member;
                    }
                }
                
                $new_member_id = nextId($members);
                $members[] = ['id'=>$new_member_id,'code'=>$code,'name'=>$name,'expiry_date'=>date('Y-m-d',strtotime("+{$days} days")),'package'=>$pkg,'custom_config'=>$custom_cfg,'is_active'=>1,'created_at'=>date('Y-m-d H:i:s'),'last_used'=>null,'active_device_id'=>null,'price_paid'=>$revenue, 'payment_status'=>$payment_status, 'created_by'=>$_SESSION['user_name'] ?? 'System', 'updated_by'=>null, 'mitra_id'=> ($_SESSION['admin_role'] === 'mitra' ? $_SESSION['user_id'] : null)];
                saveData('members.json', $members);
                
                // Update mitra unified deposit balance (deposit - harga + komisi)
                if ($_SESSION['admin_role'] === 'mitra') {
                    $users = json_decode(file_get_contents(DATA_DIR . '/users.json'), true);
                    $rate_config = $_SESSION['commission_rate'] ?? [];
                    if (!is_array($rate_config)) {
                        $rate_config = ['basic' => (int)$rate_config, 'pro' => (int)$rate_config, 'ultimate' => (int)$rate_config];
                    }
                    $base_komisi = $rate_config[$pkg] ?? $rate_config['basic'] ?? 0;
                    // Komisi proporsional berdasarkan durasi (base = 30 hari)
                    $komisi = (int)round(($base_komisi / 30) * $days);
                    $net_deduction = $revenue - $komisi; // Harga - Komisi
                    
                    foreach ($users as $i => $u) {
                        if ($u['id'] === $_SESSION['user_id']) {
                            // Komisi tetap di-track terpisah untuk laporan
                            $users[$i]['balance'] = ($u['balance'] ?? 0) + $komisi;
                            $_SESSION['balance'] = $users[$i]['balance'];
                            
                            // Deposit terpadu: kurangi harga, tambah komisi kembali
                            // Saldo Akhir = Saldo Sebelum - Harga + Komisi
                            $old_deposit = $u['deposit_balance'] ?? 0;
                            $users[$i]['deposit_balance'] = $old_deposit - $revenue + $komisi;
                            
                            // Add cashback points (bisa 0 = tidak ada cashback)
                            $cb_rate = $u['cashback_rate'] ?? 0;
                            $earned_points = ($cb_rate > 0) ? floor($revenue / $cb_rate) : 0;
                            $users[$i]['points'] = ($u['points'] ?? 0) + $earned_points;
                            
                            // Add 1 spin per transaction
                            $users[$i]['spins'] = ($u['spins'] ?? 0) + 1;
                            
                            break;
                        }
                    }
                    file_put_contents(DATA_DIR . '/users.json', json_encode($users, JSON_PRETTY_PRINT));
                    
                    // Log points earned
                    if ($earned_points > 0) {
                        $ph = loadData('points_history.json');
                        $ph[] = ['mitra_id'=>$_SESSION['user_id'],'date'=>date('Y-m-d H:i:s'),'source'=>"Transaksi: {$PKG_LABELS[$pkg]} - {$name}",'points'=>$earned_points];
                        saveData('points_history.json', $ph);
                    }
                    
                    // Log deposit change (net: harga - komisi)
                    $dh = loadData('deposit_history.json');
                    $dh[] = ['id'=>count($dh)+1,'mitra_id'=>$_SESSION['user_id'],'amount'=>-$net_deduction,'balance_before'=>$old_deposit,'balance_after'=>$users[$i]['deposit_balance'],'date'=>date('Y-m-d H:i:s'),'note'=>"Transaksi: {$name} ({$PKG_LABELS[$pkg]}) | Harga: Rp ".number_format($revenue,0,',','.').". Komisi: +Rp ".number_format($komisi,0,',','.'),'by'=>'Sistem (Auto)'];
                    saveData('deposit_history.json', $dh);
                    
                    // Log the activity
                    $auditFile = DATA_DIR . '/audit.json';
                    $audit = file_exists($auditFile) ? json_decode(file_get_contents($auditFile), true) : [];
                    $audit[] = ['time' => date('Y-m-d H:i:s'), 'action' => 'add_member', 'member_id' => $new_member_id, 'member_name' => $name, 'price' => $revenue, 'commission' => $komisi, 'net_deduction' => $net_deduction, 'points_earned' => $earned_points, 'by' => $_SESSION['user_name'] ?? 'Mitra', 'mitra_id' => $_SESSION['user_id']];
                    file_put_contents($auditFile, json_encode($audit, JSON_PRETTY_PRINT));
                }
                
                $msg="Member <strong>{$name}</strong> ditambahkan. Kode: <strong>{$code}</strong> | Paket: <strong>{$PKG_LABELS[$pkg]}</strong>"; $msgType='success';
                skip_add_member:
            }
        }
    }
    if ($pa === 'update') {
        $id = (int)($_POST['id'] ?? 0); $name = trim($_POST['name'] ?? '');
        $code = trim($_POST['code'] ?? ''); $expiry = trim($_POST['expiry_date'] ?? '');
        $pkg = $_POST['package'] ?? 'basic';
        if (!array_key_exists($pkg, $PKG_LABELS)) $pkg = 'basic';
        if (empty($name)||empty($code)||empty($expiry)) { $msg='Semua field wajib diisi.'; $msgType='error'; }
        else {
            $members = loadData('members.json');
            foreach ($members as $i => $m) {
                if ($m['id'] === $id) {
                    $members[$i]['name'] = $name; $members[$i]['code'] = $code;
                    $members[$i]['payment_status'] = $_POST['payment_status'] ?? ($m['payment_status'] ?? 'lunas');
                    
                    // Hitung durasi tambahan jika ada
                    $old_expiry = new DateTime($m['expiry_date']);
                    $new_expiry = new DateTime($expiry);
                    $diff = $old_expiry->diff($new_expiry);
                    $days_added = $diff->invert ? 0 : $diff->days;
                    
                    // Hanya tambahkan harga jika ada hari tambahan
                    if ($days_added > 0) {
                        global $pkg_prices;
                        $base_price = $pkg_prices[$pkg] ?? 0;
                        $revenue_addition = (int)round(($base_price / 30) * $days_added);
                        
                        $members[$i]['price_paid'] = ($m['price_paid'] ?? 0) + $revenue_addition;
                        
                        // Update komisi mitra untuk perpanjangan
                        if ($_SESSION['admin_role'] === 'mitra') {
                            $users = json_decode(file_get_contents(DATA_DIR . '/users.json'), true);
                            $rate_config = $_SESSION['commission_rate'] ?? [];
                            if (!is_array($rate_config)) {
                                $rate_config = ['basic' => (int)$rate_config, 'pro' => (int)$rate_config, 'ultimate' => (int)$rate_config];
                            }
                            $base_komisi = $rate_config[$pkg] ?? $rate_config['basic'] ?? 0;
                            // Komisi proporsional berdasarkan durasi tambahan (base = 30 hari)
                            $komisi = (int)round(($base_komisi / 30) * $days_added);
                            foreach ($users as $ui => $u) {
                                if ($u['id'] === $_SESSION['user_id']) {
                                    $users[$ui]['balance'] = ($u['balance'] ?? 0) + $komisi;
                                    $_SESSION['balance'] = $users[$ui]['balance'];
                                    break;
                                }
                            }
                            file_put_contents(DATA_DIR . '/users.json', json_encode($users, JSON_PRETTY_PRINT));
                            
                            // Log the activity
                            $auditFile = DATA_DIR . '/audit.json';
                            $audit = file_exists($auditFile) ? json_decode(file_get_contents($auditFile), true) : [];
                            $audit[] = ['time' => date('Y-m-d H:i:s'), 'action' => 'upgrade_member', 'member_id' => $id, 'member_name' => $name, 'price_added' => $revenue_addition, 'commission' => $komisi, 'by' => $_SESSION['user_name'] ?? 'Mitra', 'mitra_id' => $_SESSION['user_id']];
                            file_put_contents($auditFile, json_encode($audit, JSON_PRETTY_PRINT));
                        }
                    }
                    
                    $members[$i]['expiry_date'] = $expiry; $members[$i]['package'] = $pkg;
                    // Reset custom_config to null so the apps follow the newly selected package
                    $members[$i]['custom_config'] = null;
                    
                    $members[$i]['updated_by'] = $_SESSION['user_name'] ?? 'System';
                    $members[$i]['updated_at'] = date('Y-m-d H:i:s');
                    
                    if ($days_added <= 0) {
                        $auditFile = DATA_DIR . '/audit.json';
                        $audit = file_exists($auditFile) ? json_decode(file_get_contents($auditFile), true) : [];
                        $audit[] = ['time' => date('Y-m-d H:i:s'), 'action' => 'update_member', 'member_id' => $id, 'member_name' => $name, 'by' => $_SESSION['user_name'] ?? 'Mitra', 'mitra_id' => $_SESSION['user_id']];
                        file_put_contents($auditFile, json_encode($audit, JSON_PRETTY_PRINT));
                    }
                    
                    break;
                }
            }
            saveData('members.json', $members);
            $msg='Member berhasil diperbarui.'; $msgType='success';
        }
        $editData = null;
    }
    if ($pa === 'toggle') {
        $id = (int)($_POST['id'] ?? 0); $members = loadData('members.json');
        foreach ($members as $i => $m) { 
            if ($m['id'] === $id) { 
                $members[$i]['is_active'] = $m['is_active'] ? 0 : 1; 
                $members[$i]['updated_by'] = $_SESSION['user_name'] ?? 'System';
                $members[$i]['updated_at'] = date('Y-m-d H:i:s');
                break; 
            } 
        }
        saveData('members.json', $members); $msg='Status diperbarui.'; $msgType='info';
    }
    if ($pa === 'refund_member') {
        $id = (int)($_POST['id'] ?? 0);
        $refund_amount = (int)($_POST['refund_amount'] ?? 0);
        $members = loadData('members.json');
        $found = false;
        foreach ($members as $i => $m) {
            if ($m['id'] === $id) {
                // Pastikan mitra hanya bisa refund member miliknya sendiri
                if (!empty($m['mitra_id']) && $m['mitra_id'] == $_SESSION['user_id']) {
                    $members[$i]['is_active'] = 0; // Nonaktifkan member
                    // Update audit/log untuk refund
                    $auditFile = DATA_DIR . '/audit.json';
                    $audit = file_exists($auditFile) ? json_decode(file_get_contents($auditFile), true) : [];
                    $audit[] = ['time' => date('Y-m-d H:i:s'), 'action' => 'refund_member', 'member_id' => $id, 'member_name' => $m['name'], 'refund_amount' => $refund_amount, 'by' => $_SESSION['user_name'] ?? 'Mitra', 'mitra_id' => $_SESSION['user_id']];
                    file_put_contents($auditFile, json_encode($audit, JSON_PRETTY_PRINT));
                    $found = true;
                    $msg="Refund berhasil diproses. Member dinonaktifkan. Jumlah dikembalikan: Rp " . number_format($refund_amount, 0, ',', '.'); 
                    $msgType='success';
                }
                break;
            }
        }
        if ($found) { saveData('members.json', $members); }
        else { $msg='Member tidak ditemukan atau Anda tidak memiliki akses.'; $msgType='error'; }
    }
    if ($pa === 'delete') {
        $id = (int)($_POST['id'] ?? 0); $members = loadData('members.json');
        
        // --- Added for deletion notification ---
        $deleted_name = "Member";
        foreach ($members as $m) {
            if ($m['id'] === $id) {
                $deleted_name = $m['name'];
                break;
            }
        }
        // ---------------------------------------

        $members = array_values(array_filter($members, function($m) use ($id) { return $m['id'] !== $id; }));
        saveData('members.json', $members); 
        
        $auditFile = DATA_DIR . '/audit.json';
        $audit = file_exists($auditFile) ? json_decode(file_get_contents($auditFile), true) : [];
        $audit[] = ['time' => date('Y-m-d H:i:s'), 'action' => 'delete_member', 'member_id' => $id, 'member_name' => $deleted_name, 'by' => $_SESSION['user_name'] ?? 'Mitra', 'mitra_id' => $_SESSION['user_id']];
        file_put_contents($auditFile, json_encode($audit, JSON_PRETTY_PRINT));
        
        $msg="Member <strong>{$deleted_name}</strong> dihapus."; $msgType='info';
    }

    // APP MANAGEMENT
    if ($pa === 'add_app') {
        $id = trim($_POST['id'] ?? ''); $name = trim($_POST['name'] ?? '');
        $max_srv = (int)($_POST['max_servers'] ?? 1); $url = trim($_POST['default_url'] ?? '');
        $hidden_elements = trim($_POST['hidden_elements'] ?? '');
        $req_cookie = isset($_POST['requires_cookie']) ? 1 : 0;
        
        $custom_servers = [];
        if (isset($_POST['server_names']) && is_array($_POST['server_names'])) {
            foreach ($_POST['server_names'] as $idx => $sname) {
                $sname = trim($sname);
                $surl = trim($_POST['server_urls'][$idx] ?? '');
                if ($sname !== '') {
                    $custom_servers[] = ['name' => $sname, 'url' => $surl];
                }
            }
        }
        if (count($custom_servers) > 0) {
            $max_srv = count($custom_servers);
        }
        if (empty($id)) $id = strtolower(trim(preg_replace('/[^A-Za-z0-9-]+/', '-', $name), '-'));
        $icon_type = 'emoji'; $icon_val = 'ðŸ“¦';
        if (isset($_FILES['icon_file']) && $_FILES['icon_file']['error'] === UPLOAD_ERR_OK) {
            $fileExt = strtolower(pathinfo($_FILES['icon_file']['name'], PATHINFO_EXTENSION));
            if (in_array($fileExt, ['png','jpg','jpeg','gif','svg'])) {
                $uploadDir = __DIR__ . '/app_icons/';
                if (!is_dir($uploadDir)) mkdir($uploadDir, 0777, true);
                $newFileName = $id . '_' . time() . '.' . $fileExt;
                if (move_uploaded_file($_FILES['icon_file']['tmp_name'], $uploadDir . $newFileName)) {
                                $icon_type = 'image';
                                $protocol = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') ? 'https' : 'http';
                                // Fix base URL generation for #HOST folder
                                $scriptDir = dirname($_SERVER['PHP_SELF']);
                                $scriptDir = str_replace('\\', '/', $scriptDir);
                                $base_url = $protocol . '://' . $_SERVER['HTTP_HOST'] . rtrim($scriptDir, '/');
                                
                                $icon_val = $base_url . '/app_icons/' . $newFileName;
                            }
            }
        }
        if (empty($id)||empty($name)) { $msg='ID dan Nama wajib diisi.'; $msgType='error'; }
        else {
            $apps = loadData('applications.json');
            $exists = false; foreach ($apps as $a) { if ($a['id'] === $id) { $exists = true; break; } }
            if ($exists) { $msg='ID aplikasi sudah digunakan.'; $msgType='error'; }
            else {
                $maxSort = 0; foreach ($apps as $a) { if (($a['sort_order']??0) > $maxSort) $maxSort = $a['sort_order']; }
                $apps[] = ['id'=>$id,'name'=>$name,'icon_type'=>$icon_type,'icon_value'=>$icon_val,'color_gradient'=>'linear-gradient(135deg, #0066ff, #0099ff)','max_servers'=>$max_srv,'default_url'=>$url,'requires_cookie'=>$req_cookie,'hidden_elements'=>$hidden_elements,'is_active'=>1,'sort_order'=>$maxSort+1,'custom_servers'=>$custom_servers];
                saveData('applications.json', $apps);
                $msg="Aplikasi <strong>{$name}</strong> berhasil ditambahkan."; $msgType='success';
                echo "<script>window.location.href='index.php?tab=apps';</script>"; exit();
            }
        }
    }
    if ($pa === 'update_app') {
        $id = trim($_POST['id'] ?? ''); $name = trim($_POST['name'] ?? '');
        $max_srv = (int)($_POST['max_servers'] ?? 1); $url = trim($_POST['default_url'] ?? '');
        $hidden_elements = trim($_POST['hidden_elements'] ?? '');
        $req_cookie = isset($_POST['requires_cookie']) ? 1 : 0;
        
        $custom_servers = [];
        if (isset($_POST['server_names']) && is_array($_POST['server_names'])) {
            foreach ($_POST['server_names'] as $idx => $sname) {
                $sname = trim($sname);
                $surl = trim($_POST['server_urls'][$idx] ?? '');
                if ($sname !== '') {
                    $custom_servers[] = ['name' => $sname, 'url' => $surl];
                }
            }
        }
        if (count($custom_servers) > 0) {
            $max_srv = count($custom_servers);
        }
        if (empty($id)||empty($name)) { $msg='ID dan Nama wajib diisi.'; $msgType='error'; }
        else {
            $apps = loadData('applications.json');
            foreach ($apps as $i => $a) {
                if ($a['id'] === $id) {
                    $apps[$i]['name'] = $name; $apps[$i]['max_servers'] = $max_srv;
                    $apps[$i]['default_url'] = $url; $apps[$i]['requires_cookie'] = $req_cookie;
                    $apps[$i]['hidden_elements'] = $hidden_elements;
                    $apps[$i]['custom_servers'] = $custom_servers;
                    // Icon upload
                    if (isset($_FILES['icon_file']) && $_FILES['icon_file']['error'] === UPLOAD_ERR_OK) {
                        $fileExt = strtolower(pathinfo($_FILES['icon_file']['name'], PATHINFO_EXTENSION));
                        if (in_array($fileExt, ['png','jpg','jpeg','gif','svg'])) {
                            $uploadDir = __DIR__ . '/app_icons/';
                            if (!is_dir($uploadDir)) mkdir($uploadDir, 0777, true);
                            $newFileName = $id . '_' . time() . '.' . $fileExt;
                            if (move_uploaded_file($_FILES['icon_file']['tmp_name'], $uploadDir . $newFileName)) {
                                $apps[$i]['icon_type'] = 'image';
                                $protocol = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') ? 'https' : 'http';
                                // Fix base URL generation for #HOST folder
                                $scriptDir = dirname($_SERVER['PHP_SELF']);
                                // Remove backslashes and ensure no double slash issues
                                $scriptDir = str_replace('\\', '/', $scriptDir);
                                $base_url = $protocol . '://' . $_SERVER['HTTP_HOST'] . rtrim($scriptDir, '/');
                                
                                // Pastikan URL encode pada nama file jika mengandung karakter aneh, tapi di sini kita pakai timestamp jadi aman
                                $apps[$i]['icon_value'] = $base_url . '/app_icons/' . $newFileName;
                            }
                        }
                    }
                    break;
                }
            }
            saveData('applications.json', $apps);
            $msg="Aplikasi <strong>{$name}</strong> berhasil diperbarui."; $msgType='success';
            echo "<script>window.location.href='index.php?tab=apps';</script>"; exit();
        }
    }
    if ($pa === 'toggle_app') {
        $id = $_POST['id'] ?? ''; $apps = loadData('applications.json');
        foreach ($apps as $i => $a) { if ($a['id'] === $id) { $apps[$i]['is_active'] = $a['is_active'] ? 0 : 1; break; } }
        saveData('applications.json', $apps); $msg='Status aplikasi diperbarui.'; $msgType='info';
        echo "<script>window.location.href='index.php?tab=apps';</script>"; exit();
    }
    if ($pa === 'delete_app') {
        $id = $_POST['id'] ?? '';
        $apps = loadData('applications.json');
        $apps = array_values(array_filter($apps, function($a) use ($id) { return $a['id'] !== $id; }));
        saveData('applications.json', $apps);
        $cookies = loadData('cookies.json');
        $cookies = array_values(array_filter($cookies, function($c) use ($id) { return $c['app_id'] !== $id; }));
        saveData('cookies.json', $cookies);
        $msg='Aplikasi dihapus.'; $msgType='info';
        echo "<script>window.location.href='index.php?tab=apps';</script>"; exit();
    }
    
    // Apply PRG Pattern for all other actions
    if (!empty($msg)) {
        $_SESSION['flash_msg'] = $msg;
        $_SESSION['flash_msgType'] = $msgType;
        
        $tab = $_GET['tab'] ?? '';
        $redirect_url = 'index.php' . ($tab ? '?tab=' . urlencode($tab) : '');
        header("Location: " . $redirect_url);
        exit();
    }
}

// Prepare member list
$members = loadData('members.json');
usort($members, function($a,$b){ return strtotime($b['created_at']??'0') - strtotime($a['created_at']??'0'); });

// Apply Filters
if (isset($_GET['search']) || isset($_GET['f_paket']) || isset($_GET['f_status']) || isset($_GET['f_expire']) || isset($_GET['f_date']) || isset($_GET['f_payment']) || isset($_GET['f_start_date']) || isset($_GET['f_end_date'])) {
    $search = strtolower(trim($_GET['search'] ?? ''));
    $f_paket = trim($_GET['f_paket'] ?? '');
    $f_status = trim($_GET['f_status'] ?? '');
    $f_expire = trim($_GET['f_expire'] ?? '');
    $f_date = trim($_GET['f_date'] ?? '');
    $f_payment = trim($_GET['f_payment'] ?? '');
    $f_start_date = trim($_GET['f_start_date'] ?? '');
    $f_end_date = trim($_GET['f_end_date'] ?? '');
    
    $filtered_members = [];
    $today = date('Y-m-d');

    foreach ($members as $m) {
        $match = true;
        
        // Filter by Mitra
        if ($role === 'mitra' && ($m['mitra_id'] ?? null) !== $_SESSION['user_id']) {
            continue;
        }
        
        // Search by name or code
        if ($search !== '') {
            if (strpos(strtolower($m['name']), $search) === false && strpos(strtolower($m['code']), $search) === false) {
                $match = false;
            }
        }
        
        // Filter by package
        if ($f_paket !== '' && $m['package'] !== $f_paket) {
            $match = false;
        }
        
        // Filter by payment status
        if ($f_payment !== '') {
            $ps = $m['payment_status'] ?? 'lunas'; // default to lunas if not set
            if ($f_payment !== $ps) {
                $match = false;
            }
        }
        
        // Filter by start and end date (transaction created_at)
        if ($f_start_date !== '') {
            $c_date = date('Y-m-d', strtotime($m['created_at'] ?? '0'));
            if ($c_date < $f_start_date) {
                $match = false;
            }
        }
        if ($f_end_date !== '') {
            $c_date = date('Y-m-d', strtotime($m['created_at'] ?? '0'));
            if ($c_date > $f_end_date) {
                $match = false;
            }
        }
        
        // Filter by status (aktif, nonaktif, expired)
        if ($f_status !== '') {
            $isExpired = ($m['expiry_date'] < $today);
            if ($f_status === 'aktif') {
                if (!$m['is_active'] || $isExpired) $match = false;
            } elseif ($f_status === 'nonaktif') {
                if ($m['is_active']) $match = false;
            } elseif ($f_status === 'expired') {
                if (!$isExpired) $match = false;
            }
        }
        
        // Filter by expiry (< 14 Hari, < 7 Hari, < 3 Hari)
        if ($f_expire !== '' && $match) {
            $isExpired = ($m['expiry_date'] < $today);
            if ($isExpired) {
                $match = false; // Already expired, so remaining days is 0, but user wants active remaining days
            } else {
                $expDateTime = new DateTime($m['expiry_date']);
                $todayDateTime = new DateTime($today);
                $diffDays = (int)$todayDateTime->diff($expDateTime)->days;
                if ($f_expire === '14' && $diffDays > 14) $match = false;
                if ($f_expire === '7' && $diffDays > 7) $match = false;
                if ($f_expire === '3' && $diffDays > 3) $match = false;
            }
        }
        
        // Filter by custom date
        if ($f_date !== '' && $match) {
            if ($m['expiry_date'] !== $f_date) {
                $match = false;
            }
        }
        
        if ($match) {
            $filtered_members[] = $m;
        }
    }
    $members = $filtered_members;
} else {
    // If no GET filters are set, we still need to filter for Mitra!
    if ($role === 'mitra') {
        $filtered_members = [];
        foreach ($members as $m) {
            if (($m['mitra_id'] ?? null) === $_SESSION['user_id']) {
                $filtered_members[] = $m;
            }
        }
        $members = $filtered_members;
    }
}

// Apply Sorting
$f_sort = $_GET['f_sort'] ?? 'newest';
if ($f_sort !== 'newest') {
    usort($members, function($a, $b) use ($f_sort) {
        if ($f_sort === 'oldest') {
            return strtotime($a['created_at'] ?? '0') - strtotime($b['created_at'] ?? '0');
        } elseif ($f_sort === 'expire_asc') {
            return strtotime($a['expiry_date']) - strtotime($b['expiry_date']);
        } elseif ($f_sort === 'expire_desc') {
            return strtotime($b['expiry_date']) - strtotime($a['expiry_date']);
        } elseif ($f_sort === 'price_desc') {
            return (int)($b['price_paid'] ?? 0) - (int)($a['price_paid'] ?? 0);
        } elseif ($f_sort === 'price_asc') {
            return (int)($a['price_paid'] ?? 0) - (int)($b['price_paid'] ?? 0);
        }
        return 0;
    });
}

$todayDate = new DateTime();
$total = count($members); // Used the filtered members list so Mitra only sees their own totals
$active = 0; $expired = 0; $totalRevenue = 0; $totalSales = 0;
foreach ($members as $m) {
    $exp = new DateTime($m['expiry_date']);
    if ($todayDate > $exp) $expired++;
    elseif ($m['is_active']) $active++;
    
    if ($role === 'mitra') {
        $rate_config = $_SESSION['commission_rate'] ?? [];
        if (!is_array($rate_config)) {
            $rate_config = ['basic' => (int)$rate_config, 'pro' => (int)$rate_config, 'ultimate' => (int)$rate_config];
        }
        $m_pkg = $m['package'] ?? 'basic';
        $rate = $rate_config[$m_pkg] ?? $rate_config['basic'] ?? 0;
        
        $grossSale = (int)($m['price_paid'] ?? 0);
        $totalSales += $grossSale;
        $totalRevenue += $rate;
    } else {
        $totalRevenue += (int)($m['price_paid'] ?? 0);
    }
}

// Edit app fetch
$editApp = null;
if (isset($_GET['edit_app'])) {
    $eaid = $_GET['edit_app'];
    foreach (loadData('applications.json') as $a) { if ($a['id'] === $eaid) { $editApp = $a; break; } }
}

// Reload all apps for display
$allAppsForAdmin = loadData('applications.json');
usort($allAppsForAdmin, function($a,$b){ return ($a['sort_order']??0) - ($b['sort_order']??0); });
// Rebuild active labels for cookies tab
$APP_LABELS = []; $APP_MAX = []; $APP_URLS_PHP = [];
foreach ($allAppsForAdmin as $app) {
    if ($app['is_active']) {
        $APP_LABELS[$app['id']] = $app['name'];
        $APP_MAX[$app['id']] = (int)$app['max_servers'];
        $APP_URLS_PHP[$app['id']] = $app['default_url'] ?? '';
    }
}

// Prepare cookie metadata for UI
$cookiesData = loadData('cookies.json');
$cookieMeta = [];
foreach ($cookiesData as $c) {
    $key = $c['app_id'] . '_' . $c['server_index'];
    $cookieMeta[$key] = [
        'updated_by' => $c['updated_by'] ?? 'System',
        'updated_at' => $c['updated_at'] ?? 'Unknown'
    ];
}
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
<title>TEKNO APPS Member Manager</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet"/>
<style>
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
:root{--deep:#020c18;--blue:#0066ff;--bright:#0099ff;--light:#4db8ff;--text:#e8f4ff;--sub:#7aaed4;--muted:#4a7a9b;--glass:rgba(4,22,48,.85);--border:rgba(0,150,255,.18);--ok:#00e676;--err:#ff4d4d;--warn:#ffaa00}
body{min-height:100vh;background:var(--deep);font-family:"Inter",sans-serif;color:var(--text)}
body::before{content:"";position:fixed;inset:0;pointer-events:none;background:radial-gradient(ellipse at 15% 15%,rgba(0,80,180,.22) 0%,transparent 55%),radial-gradient(ellipse at 85% 85%,rgba(0,40,130,.16) 0%,transparent 55%)}
.wrap{max-width:1040px;margin:0 auto;padding:28px 18px;position:relative;z-index:1}
.hdr{display:flex;align-items:center;gap:14px;margin-bottom:26px}
.logo{width:46px;height:46px;border-radius:13px;background:linear-gradient(135deg,#0044cc,#0099ff);display:flex;align-items:center;justify-content:center;font-size:15px;font-weight:900;box-shadow:0 0 18px rgba(0,150,255,.4)}
.hdr-text h1{font-size:20px;font-weight:800;background:linear-gradient(135deg,#e0f0ff,#4db8ff);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}
.hdr-text p{font-size:11px;color:var(--muted);margin-top:2px}
.stats{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-bottom:22px}
.sc{background:var(--glass);border:1px solid var(--border);border-radius:13px;padding:16px 18px;backdrop-filter:blur(12px)}
.sv{font-size:26px;font-weight:800;margin-bottom:3px}
.sl{font-size:10px;color:var(--muted);letter-spacing:.5px;text-transform:uppercase}
.sc.t .sv{color:var(--bright)}.sc.a .sv{color:var(--ok)}.sc.e .sv{color:var(--err)}
.alert{padding:11px 15px;border-radius:9px;margin-bottom:18px;font-size:12.5px;font-weight:500}
.alert.success{background:rgba(0,230,118,.1);border:1px solid rgba(0,230,118,.3);color:var(--ok)}
.alert.error{background:rgba(255,77,77,.1);border:1px solid rgba(255,77,77,.3);color:var(--err)}
.alert.info{background:rgba(0,150,255,.1);border:1px solid rgba(0,150,255,.3);color:var(--light)}
.card{background:var(--glass);border:1px solid var(--border);border-radius:15px;backdrop-filter:blur(16px);padding:22px;margin-bottom:22px;overflow:visible;}
.card.edit-card{border-color:rgba(255,170,0,.3);box-shadow:0 0 20px rgba(255,170,0,.1)}
.ct{font-size:13px;font-weight:700;color:#a8d8ff;margin-bottom:16px;display:flex;align-items:center;gap:8px}
.ct::before{content:"";width:3px;height:15px;border-radius:2px;background:linear-gradient(180deg,var(--blue),var(--bright));flex-shrink:0}
.ct.edit-ct::before{background:linear-gradient(180deg,var(--warn),#ff8800)}
.fg{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.fi{display:flex;flex-direction:column;gap:5px}
.fi.full{grid-column:1/-1}
label{font-size:10px;font-weight:700;color:var(--light);letter-spacing:.8px;text-transform:uppercase}
input[type=text],input[type=url],input[type=date],input[type=search],input[type=number]{width:100%;padding:9px 13px;background:rgba(0,20,50,.6);border:1px solid var(--border);border-radius:8px;color:var(--text);font-size:13px;font-family:inherit;outline:none;transition:border-color .2s,box-shadow .2s}
input:focus{border-color:var(--bright);box-shadow:0 0 0 3px rgba(0,150,255,.15)}
input::placeholder{color:var(--muted)}
.dur-group{display:flex;gap:8px;flex-wrap:wrap}
.dur-btn{flex:1;padding:10px 8px;border-radius:9px;border:2px solid var(--border);background:rgba(0,30,80,.4);color:var(--sub);font-size:12px;font-weight:700;font-family:inherit;cursor:pointer;transition:all .2s;text-align:center}
.dur-btn:hover{border-color:var(--bright);color:var(--light);background:rgba(0,60,160,.3)}
.dur-btn.selected{border-color:var(--blue);background:rgba(0,80,200,.35);color:#fff;box-shadow:0 0 12px rgba(0,100,255,.3)}
.dur-badge{display:block;font-size:9px;color:var(--muted);margin-top:2px;font-weight:500;letter-spacing:.5px}
.dur-btn.selected .dur-badge{color:var(--light)}
.pkg-group{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}
.pkg-btn{padding:12px 6px;border-radius:10px;border:2px solid var(--border);background:rgba(0,20,60,.5);color:var(--sub);font-size:13px;font-weight:700;font-family:inherit;cursor:pointer;transition:all .2s;text-align:center;line-height:1.3;white-space:nowrap}
.pkg-btn:hover{border-color:var(--bright);background:rgba(0,60,160,.3);color:var(--light)}
.pkg-btn .pkg-name{display:block;font-size:13px;font-weight:800}
.pkg-btn .pkg-desc{display:block;font-size:9px;margin-top:3px;font-weight:500;letter-spacing:.3px;opacity:.7}
.pkg-btn[data-pkg="basic"].selected{border-color:#0099ff;background:rgba(0,100,220,.25);color:#7ad4ff}
.pkg-btn[data-pkg="basic"].selected .pkg-desc{opacity:1}
.pkg-btn[data-pkg="pro"].selected{border-color:#00e676;background:rgba(0,160,80,.2);color:#00e676}
.pkg-btn[data-pkg="pro"].selected .pkg-desc{opacity:1}
.pkg-btn[data-pkg="ultimate"].selected{border-color:#ffaa00;background:rgba(180,110,0,.2);color:#ffcc44}
.pkg-btn[data-pkg="ultimate"].selected .pkg-desc{opacity:1}
.pkg-btn[data-pkg="custom"].selected{border-color:#cc44ff;background:rgba(100,0,180,.2);color:#ee88ff}
.pkg-btn[data-pkg="custom"].selected .pkg-desc{opacity:1}
.custom-cfg{display:none;margin-top:12px;padding:14px;background:rgba(100,0,200,.08);border:1px solid rgba(150,50,255,.2);border-radius:10px}
.custom-cfg.visible{display:block}
.app-row{display:flex;align-items:center;justify-content:space-between;padding:7px 0;border-bottom:1px solid rgba(0,80,160,.1);gap:12px}
.app-row:last-child{border-bottom:none}
.app-chk{display:flex;align-items:center;gap:8px;flex:1}
.app-chk input[type=checkbox]{width:16px;height:16px;cursor:pointer;accent-color:var(--bright)}
.app-chk label{font-size:12px;font-weight:500;letter-spacing:0;text-transform:none;color:var(--text);cursor:pointer}
.srv-ctrl{display:flex;align-items:center;gap:6px;flex-shrink:0}
.srv-ctrl label{font-size:10px;color:var(--muted);white-space:nowrap}
.srv-ctrl input{width:58px;text-align:center;padding:5px 8px}
.btn{padding:10px 20px;border-radius:8px;border:none;font-size:12.5px;font-weight:700;font-family:inherit;cursor:pointer;transition:all .2s;display:inline-flex;align-items:center;gap:6px;text-decoration:none}
.bp{background:linear-gradient(135deg,#0055cc,#0088ff);color:#fff;box-shadow:0 4px 14px rgba(0,100,255,.3)}
.bp:hover{transform:translateY(-1px);box-shadow:0 6px 20px rgba(0,120,255,.4)}
.bw{background:linear-gradient(135deg,#aa6000,#ff9900);color:#fff;box-shadow:0 4px 14px rgba(200,100,0,.3)}
.bw:hover{transform:translateY(-1px);box-shadow:0 6px 20px rgba(200,120,0,.4)}
.bsm{padding:5px 11px;font-size:11px;border-radius:7px}
.bd{background:rgba(180,20,20,.3);color:#ff8080;border:1px solid rgba(255,60,60,.2)}
.bd:hover{background:rgba(200,30,30,.5)}
.bt{background:rgba(0,60,140,.3);color:var(--light);border:1px solid var(--border)}
.bt:hover{background:rgba(0,100,200,.4)}
.be2{background:rgba(180,120,0,.25);color:#ffcc44;border:1px solid rgba(255,180,0,.2)}
.be2:hover{background:rgba(200,140,0,.4)}
.sr{display:flex;gap:10px;margin-bottom:14px}
.sr input{flex:1}
.tw{overflow:visible; max-width: 100%;}
table{width:100%;border-collapse:collapse; white-space: nowrap; table-layout: fixed;}
th{font-size:10px;font-weight:700;color:var(--muted);letter-spacing:.7px;text-transform:uppercase;padding:7px 5px;text-align:left;border-bottom:1px solid var(--border)}
td{padding:8px 5px;font-size:11px;border-bottom:1px solid rgba(0,80,160,.1);vertical-align:middle; text-overflow: ellipsis; overflow: hidden;}
tr:last-child td{border-bottom:none}
tr:hover td{background:rgba(0,60,140,.12)}
code.kd{display:inline-block; max-width:100%; overflow:hidden; text-overflow:ellipsis; vertical-align:bottom; background:rgba(0,80,160,.25);border:1px solid var(--border);border-radius:6px;padding:3px 8px;font-size:11px;font-family:"Courier New",monospace;color:var(--light);letter-spacing:0.5px}
.badge{display:inline-flex;align-items:center;padding:2px 7px;border-radius:20px;font-size:9.5px;font-weight:700;letter-spacing:.4px}
.ba{background:rgba(0,230,118,.1);border:1px solid rgba(0,230,118,.3);color:var(--ok)}
.be{background:rgba(255,77,77,.1);border:1px solid rgba(255,77,77,.2);color:var(--err)}
.bn{background:rgba(100,100,100,.12);border:1px solid rgba(150,150,150,.18);color:#888}
.pb-basic{background:rgba(0,100,220,.15);border:1px solid rgba(0,150,255,.3);color:#7ad4ff}
.pb-pro{background:rgba(0,160,80,.12);border:1px solid rgba(0,230,118,.25);color:#00e676}
.pb-ultimate{background:rgba(200,120,0,.15);border:1px solid rgba(255,170,0,.3);color:#ffcc44}
.pb-custom{background:rgba(120,0,200,.15);border:1px solid rgba(180,50,255,.3);color:#ee88ff}
.sisa{font-size:10.5px}
.sisa.ok{color:var(--ok)}.sisa.warn{color:var(--warn)}.sisa.err{color:var(--err)}
.empty{text-align:center;padding:36px;color:var(--muted);font-size:13px}
.tabs{display:flex;gap:10px;margin-bottom:20px;border-bottom:1px solid var(--border);padding-bottom:12px;overflow-x:auto;white-space:nowrap;-webkit-overflow-scrolling:touch;}
.tabs::-webkit-scrollbar{display:none;}
.tab-btn{flex-shrink:0;}
.tab-btn{background:transparent;border:none;color:var(--muted);font-size:14px;font-weight:700;cursor:pointer;padding:8px 16px;border-radius:8px;transition:0.2s}
.tab-btn:hover{color:var(--light);background:var(--glass)}
.tab-btn.active{color:var(--bright);background:rgba(0,100,255,0.15);box-shadow:0 0 10px rgba(0,150,255,0.2)}
.tab-content{display:none}
.tab-content.active{display:block}
textarea{width:100%;background:rgba(0,20,50,.6);border:1px solid var(--border);border-radius:8px;padding:12px;color:var(--text);font-family:monospace;font-size:12px;resize:vertical;min-height:150px;outline:none}
textarea:focus{border-color:var(--bright);box-shadow:0 0 0 3px rgba(0,150,255,.15)}
select{width:100%;background:rgba(0,20,50,.6);border:1px solid var(--border);border-radius:8px;padding:9px 13px;color:var(--text);font-size:13px;outline:none;cursor:pointer}
select option { background-color: var(--deep); color: var(--text); }

/* Dropdown Actions */
.act-dropdown { position: relative; display: inline-block; overflow: visible !important; }
.act-btn { background: rgba(0, 100, 255, 0.2); border: 1px solid var(--border); color: var(--light); padding: 4px 10px; border-radius: 6px; cursor: pointer; display: flex; align-items: center; gap: 4px; font-size: 11px; transition: 0.2s; position: relative; z-index: 10; }
.act-btn:hover { background: rgba(0, 120, 255, 0.4); }
.act-menu { display: none; position: absolute; right: 0; top: 100%; margin-top: 4px; background: var(--deep); border: 1px solid var(--border); border-radius: 8px; min-width: 120px; box-shadow: 0 5px 15px rgba(0,0,0,0.5); z-index: 1000; overflow: hidden; }
.act-menu.show { display: block; }
.act-menu a, .act-menu button { display: block; width: 100%; text-align: left; padding: 8px 12px; font-size: 11px; background: transparent; border: none; color: var(--text); cursor: pointer; transition: 0.2s; text-decoration: none; }
.act-menu a:hover, .act-menu button:hover { background: rgba(0, 100, 255, 0.2); color: var(--light); }
.act-menu .m-edit { color: #ffcc44; }
.act-menu .m-del { color: #ff4d4d; border-top: 1px solid rgba(255,255,255,0.05); }

/* Column Widths */
.member-table th:nth-child(1) { width: 4%; }
.member-table th:nth-child(2) { width: 22%; }
.member-table th:nth-child(3) { width: 18%; }
.member-table th:nth-child(4) { width: 10%; }
.member-table th:nth-child(5) { width: 12%; }
.member-table th:nth-child(6) { width: 8%; }
.member-table th:nth-child(7) { width: 10%; }
.member-table th:nth-child(8) { width: 8%; }
.member-table th:nth-child(9) { width: 8%; text-align: right; }
.member-table td:nth-child(9) { text-align: right; overflow: visible; }

/* App Table Specific Adjustments */
.app-table th:nth-child(1) { width: 35%; }
.app-table th:nth-child(2) { width: 12%; }
.app-table th:nth-child(3) { width: 15%; }
.app-table th:nth-child(4) { width: 15%; }
.app-table th:nth-child(5) { width: 10%; }
.app-table th:nth-child(6) { width: 13%; text-align: right; }
.app-table td:nth-child(6) { text-align: right; overflow: visible; }

@media (max-width: 768px) {
  .wrap{padding:18px 12px}.logo{width:38px;height:38px;font-size:13px}.hdr-text h1{font-size:16px}
  .stats{grid-template-columns:1fr 1fr;gap:9px;margin-bottom:18px}.sc{padding:12px 14px}.sv{font-size:21px}
  .fg{grid-template-columns:1fr}.card{padding:16px;border-radius:12px}
  .btn{padding:9px 16px;font-size:12px}.bp,.bw{width:100%;justify-content:center}
  .sr{flex-direction:column;gap:8px}.pkg-group{gap:6px}
  /* On mobile, allow horizontal scrolling if it still overflows */
  .tw{overflow-x:auto;}
  table { min-width: 700px; }
}
@media (max-width: 768px) {
  .stats { grid-template-columns: repeat(2, 1fr) !important; }
}
@media (max-width: 768px) {
  .stats { grid-template-columns: repeat(2, 1fr) !important; }
}
@media (max-width: 480px) {
  .wrap{padding:14px 10px}
  .stats{grid-template-columns:1fr !important}
  .hdr-text p{display:none}
  .tw table { min-width: 100% !important; table-layout: auto !important; }
  .tw table, .tw tbody, .tw th, .tw td, .tw tr { display: block; box-sizing: border-box; width: 100%; }
  .tw table thead{display:none}
  .tw table tr{background:rgba(0,30,70,.4);border:1px solid var(--border);border-radius:10px;margin-bottom:10px;padding:10px 12px}
  .tw table td{display:flex;justify-content:space-between;align-items:center;border:none;padding:8px 0;font-size:12px; overflow: visible; white-space: normal !important; text-align:right;}
  .tw table td::before{content:attr(data-label);font-size:10px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.6px;flex-shrink:0;margin-right:8px;text-align:left;}
  .pkg-btn{min-width:60px;font-size:11px}
  .act-menu { bottom: 100%; top: auto; margin-bottom: 4px; right: 0; left: auto; z-index: 9999; }
  .filter-container { flex-direction: column; align-items: stretch !important; }
  .filter-container > div { width: 100%; margin-bottom: 5px; text-align: left !important; }
  .filter-container select, .filter-container input { width: 100% !important; }
}
</style>
</head>
<body>
<div class="wrap">
<div class="hdr" style="justify-content: space-between;">
  <div style="display:flex;align-items:center;gap:14px;">
    <div class="logo">TX</div>
    <div class="hdr-text">
      <h1>Portal Mitra &mdash; TEKNO APPS</h1>
      <p>Kelola penjualan &amp; komisi (Afiliasi) &bull; Login sebagai: <strong style="color:var(--bright);"><?php echo htmlspecialchars($_SESSION['user_name'] ?? ucfirst($role)); ?></strong> <span class="badge pb-custom" style="font-size:8px; padding:1px 4px;"><?php echo strtoupper($role); ?></span></p>
    </div>
  </div>
  <div style="display:flex; gap:10px;">
    <a href="?logout=1" class="btn bd" style="padding: 8px 15px; font-size: 11px;">&#x1F6AA; Logout</a>
  </div>
</div>
<?php 
// Load fresh mitra data for deposit display
$mitraData = null;
$usersForDeposit = json_decode(file_get_contents(DATA_DIR . '/users.json'), true);
foreach ($usersForDeposit as $u) { if ($u['id'] === $_SESSION['user_id']) { $mitraData = $u; break; } }
$dep_bal = $mitraData['deposit_balance'] ?? 0;
$dep_minus = $mitraData['deposit_minus_limit'] ?? -500000;
$dep_available = $dep_bal - $dep_minus;
$dep_color = $dep_bal < 0 ? '#ff4d4d' : '#00e676';
$mitra_points = $mitraData['points'] ?? 0;
$mitra_spins = $mitraData['spins'] ?? 0;
$mitra_komisi_total = $mitraData['balance'] ?? 0;
?>

<!-- DEPOSIT BALANCE CARD -->
<div class="card" style="background: linear-gradient(135deg, rgba(0,100,200,0.15), rgba(0,200,100,0.1)); border-color: rgba(0,200,100,0.3); margin-bottom: 18px; padding: 20px;">
  <div>
    <div style="font-size:10px; color:var(--muted); text-transform:uppercase; letter-spacing:1px; margin-bottom:4px;">💰 Saldo Deposit (Deposit + Komisi - Transaksi)</div>
    <div style="font-size:28px; font-weight:900; color:<?php echo $dep_color; ?>;">Rp <?php echo number_format($dep_bal, 0, ',', '.'); ?></div>
    <div style="font-size:11px; color:var(--muted); margin-top:4px;">Batas Minus: Rp <?php echo number_format($dep_minus, 0, ',', '.'); ?> &bull; Kredit Tersedia: Rp <?php echo number_format($dep_available, 0, ',', '.'); ?></div>
    <div style="font-size:10px; color:#00e676; margin-top:6px;">📊 Total Komisi Terkumpul: Rp <?php echo number_format($mitra_komisi_total, 0, ',', '.'); ?></div>
    <div style="font-size:9px; color:var(--muted); margin-top:4px; font-style:italic;">Saldo = Deposit Awal + Komisi Penjualan - Harga Transaksi. Hubungi Owner untuk top up.</div>
  </div>
</div>

<div class="stats" style="grid-template-columns: repeat(<?php echo $user_perms['view_stats'] ? 4 : 3; ?>, 1fr);">
  <div class="sc t"><div class="sv"><?php echo $total; ?></div><div class="sl">Total Member</div></div>
  <div class="sc a"><div class="sv"><?php echo $active; ?></div><div class="sl">Aktif</div></div>
  <div class="sc e"><div class="sv"><?php echo $expired; ?></div><div class="sl">Expired</div></div>
  <?php if ($user_perms['view_stats']): ?>
  <div class="sc r" style="background: linear-gradient(135deg, rgba(0,230,118,0.1), rgba(0,200,100,0.1)); border-color: rgba(0,230,118,0.3);">
    <div class="sv" style="color: #00e676; font-size: 20px;">Rp <?php echo number_format($role === 'mitra' ? $totalRevenue : $totalRevenue, 0, ',', '.'); ?></div>
    <div class="sl" style="color: #00e676;"><?php echo $role === 'mitra' ? 'Total Pendapatan' : 'Total Pendapatan'; ?></div>
  </div>
  <?php endif; ?>
</div>

<?php if ($msg): ?>
<div class="alert <?php echo $msgType; ?>" style="<?php echo (strpos($msg, 'DEPOSIT TIDAK MENCUKUPI') !== false) ? 'background:rgba(255,40,40,0.15); border:2px solid rgba(255,60,60,0.5); padding:20px; font-size:13px;' : ''; ?> white-space:pre-line;">
  <?php echo $msgType==='success'?'&#x2705;':($msgType==='error'?'&#x274C;':'&#x2139;&#xFE0F;'); ?> <?php echo nl2br($msg); ?>
</div>
<?php endif; ?>

<div class="tabs">
  <button class="tab-btn <?php echo $tab==='members'?'active':''; ?>" onclick="switchTab('members')">Member Saya</button>
  <button class="tab-btn <?php echo $tab==='products'?'active':''; ?>" onclick="switchTab('products')">Produk & Harga</button>
  <button class="tab-btn <?php echo $tab==='mitradashboard'?'active':''; ?>" onclick="switchTab('mitradashboard')">Dashboard Pendapatan</button>
  <button class="tab-btn <?php echo $tab==='audit'?'active':''; ?>" onclick="switchTab('audit')">Histori Log</button>
</div><!-- MEMBERS TAB -->
<div id="tab-members" class="tab-content <?php echo $tab==='members'?'active':''; ?>">
<?php
function renderPkgSelector($selPkg, $prefix, $customCfg, $APP_LABELS, $APP_MAX) {
  global $pkg_prices;
?>
<div class="fi full">
  <label>Paket</label>
  <input type="hidden" name="package" id="<?php echo $prefix;?>_pkg_val" value="<?php echo htmlspecialchars($selPkg); ?>"/>
  <div class="pkg-group" id="<?php echo $prefix;?>_pkg_group">
    <button type="button" class="pkg-btn<?php echo $selPkg==='basic'?' selected':''; ?>" data-pkg="basic" onclick="setPkg('<?php echo $prefix;?>','basic', <?php echo $pkg_prices['basic']??0; ?>)"><span class="pkg-name">Basic</span><span class="pkg-desc" style="color:#00e676;font-weight:bold;font-size:10px;">Rp <?php echo number_format($pkg_prices['basic']??0, 0, ',', '.'); ?></span><span class="pkg-desc">Flow &middot; Whisk &middot; Sora</span></button>
    <button type="button" class="pkg-btn<?php echo $selPkg==='pro'?' selected':''; ?>" data-pkg="pro" onclick="setPkg('<?php echo $prefix;?>','pro', <?php echo $pkg_prices['pro']??0; ?>)"><span class="pkg-name">Pro</span><span class="pkg-desc" style="color:#00e676;font-weight:bold;font-size:10px;">Rp <?php echo number_format($pkg_prices['pro']??0, 0, ',', '.'); ?></span><span class="pkg-desc">+Grok</span></button>
    <button type="button" class="pkg-btn<?php echo $selPkg==='ultimate'?' selected':''; ?>" data-pkg="ultimate" onclick="setPkg('<?php echo $prefix;?>','ultimate', <?php echo $pkg_prices['ultimate']??0; ?>)"><span class="pkg-name">Ultimate</span><span class="pkg-desc" style="color:#00e676;font-weight:bold;font-size:10px;">Rp <?php echo number_format($pkg_prices['ultimate']??0, 0, ',', '.'); ?></span><span class="pkg-desc">Full Access</span></button>
    <button type="button" class="pkg-btn<?php echo $selPkg==='custom'?' selected':''; ?>" data-pkg="custom" style="pointer-events: none; opacity: 0.3;" title="Mitra tidak dapat menggunakan paket Custom"><span class="pkg-name">Custom</span><span class="pkg-desc" style="color:#00e676;font-weight:bold;font-size:10px;">Rp <?php echo number_format($pkg_prices['custom']??0, 0, ',', '.'); ?></span><span class="pkg-desc">Pilih Sendiri</span></button>
  </div>
  <div class="custom-cfg visible" id="<?php echo $prefix;?>_custom" style="margin-top:15px;border-top:1px solid rgba(255,255,255,0.05);padding-top:10px;">
    <div style="font-size:11px;color:var(--light);margin-bottom:10px;font-weight:600">Konfigurasi Akses Aplikasi: <span style="font-weight:normal;color:var(--muted)">(Mengikuti Paket - Read Only)</span></div>
    <div id="<?php echo $prefix;?>_app_list_container">
      <!-- App list will be rendered via JS -->
    </div>
  </div>
</div>
<?php } ?>

<?php if ($editData):
  $editPkg = $editData['package'] ?? 'basic';
  $editCustom = !empty($editData['custom_config']) && is_array($editData['custom_config']) ? $editData['custom_config'] : [];
?>
<div class="card edit-card">
  <div class="ct edit-ct">Edit Member: <?php echo htmlspecialchars($editData['name']); ?></div>
  <form method="POST">
    <input type="hidden" name="action" value="update"/>
    <input type="hidden" name="id" value="<?php echo $editData['id']; ?>"/>
    <div class="fg">
      <div class="fi"><label>Nama Member</label><input type="text" name="name" value="<?php echo htmlspecialchars($editData['name']); ?>" required/></div>
      <div class="fi"><label>Kode Akses</label><input type="text" name="code" value="<?php echo htmlspecialchars($editData['code']); ?>" required/></div>
      <div class="fi full">
        <label>Ubah Tanggal Expire / Tambah Hari</label>
        <div style="display:flex; gap:10px; align-items:center;">
          <input type="date" name="expiry_date" id="edit_expiry_date" value="<?php echo $editData['expiry_date']; ?>" style="flex:1;" required/>
          <span style="color:var(--muted);font-size:12px;">atau</span>
          <div style="display:flex; align-items:center; background:rgba(0,20,50,.6); border:1px solid var(--border); border-radius:8px; padding:0 12px; width: 150px;">
            <span style="font-size:16px; color:#00e676; font-weight:bold; margin-right:5px;">+</span>
            <input type="number" id="edit_add_days" placeholder="Hari" min="1" oninput="addDaysToExpiry(this.value)" style="flex:1; background:transparent; border:none; color:var(--text); font-size:14px; outline:none; text-align:center; padding: 10px 0;"/>
          </div>
        </div>
        <p style="font-size:10px; color:var(--muted); margin-top:4px;">Pilih tanggal manual ATAU ketik jumlah hari untuk menambahkan masa aktif dari tanggal expire saat ini.</p>
      </div>
      <div class="fi full" style="margin-bottom: 8px;">
        <label>Harga / Pendapatan Transaksi (Rp)</label>
        <div style="background: rgba(0,230,118,0.1) !important; border: 1px solid rgba(0,230,118,0.3) !important; padding: 12px; border-radius: 8px;">
          <input type="number" value="<?php echo htmlspecialchars($editData['price_paid'] ?? 0); ?>" readonly style="width: 100%; background: transparent !important; border: none !important; color: #00e676 !important; outline: none; font-size: 14px;"/>
        </div>
        <p style="font-size:10px; color:var(--muted); margin-top:4px;">Harga dikunci (hanya Owner yang dapat mengubah aturan harga).</p>
      </div>
      <?php renderPkgSelector($editPkg, 'ed', $editCustom, $APP_LABELS_ALL, $APP_MAX_ALL); ?>
      <div class="fi full" style="display:flex; gap:8px; justify-content:space-between; margin-top:15px; border-top: 1px dashed rgba(255,255,255,0.1); padding-top: 15px;">
        <button type="button" class="btn" style="background: rgba(255,0,0,0.1); color: #ff4d4d; border: 1px solid rgba(255,0,0,0.3);" onclick="confirmRefund(<?php echo $editData['id']; ?>, '<?php echo $editData['expiry_date']; ?>', <?php echo $editData['price_paid'] ?? 0; ?>)">
          &#128176; Refund & Nonaktifkan
        </button>
        <div style="display:flex;gap:8px;">
          <a href="?" class="btn bt">Batal</a>
          <button type="submit" class="btn bw">&#x270E; Simpan Perubahan</button>
        </div>
      </div>
    </div>
  </form>
</div>
<script>
const ORIGINAL_EXPIRY = '<?php echo $editData['expiry_date']; ?>';
function addDaysToExpiry(days) {
    const d = parseInt(days) || 0;
    const expDateInput = document.getElementById('edit_expiry_date');
    if (!expDateInput) return;
    
    if (d > 0) {
        const dateObj = new Date(ORIGINAL_EXPIRY);
        dateObj.setDate(dateObj.getDate() + d);
        const yyyy = dateObj.getFullYear();
        const mm = String(dateObj.getMonth() + 1).padStart(2, '0');
        const dd = String(dateObj.getDate()).padStart(2, '0');
        expDateInput.value = `${yyyy}-${mm}-${dd}`;
    } else {
        expDateInput.value = ORIGINAL_EXPIRY;
    }
}

function confirmRefund(memberId, expiryDate, pricePaid) {
    if (pricePaid <= 0) {
        alert("Member ini tidak memiliki data harga yang dibayar, tidak dapat melakukan refund.");
        return;
    }
    
    const today = new Date();
    const expDate = new Date(expiryDate);
    const diffTime = expDate - today;
    const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
    
    if (diffDays <= 0) {
        alert("Member sudah expired, tidak ada sisa durasi untuk direfund.");
        return;
    }
    
    const totalDays = 30; // Asumsi paket 30 hari untuk perhitungan proporsional (bisa diubah jika perlu)
    
    let baseRefund = Math.round((pricePaid / 30) * diffDays);
    if (baseRefund > pricePaid) baseRefund = pricePaid;
    
    const adminFeePercent = <?php echo $settings['refund_admin_fee_percent'] ?? 25; ?>;
    const adminFee = Math.round(baseRefund * (adminFeePercent / 100));
    const netRefund = baseRefund - adminFee;
    
    const msg = `DETAIL REFUND MEMBER\n` +
                `Sisa Durasi Aktif: ${diffDays} hari\n` +
                `Harga Dibayar: Rp ${pricePaid.toLocaleString('id-ID')}\n\n` +
                `Perhitungan Refund (Proporsional): Rp ${baseRefund.toLocaleString('id-ID')}\n` +
                `Potongan Admin (${adminFeePercent}%): - Rp ${adminFee.toLocaleString('id-ID')}\n` +
                `---------------------------\n` +
                `Total Dana Dikembalikan: Rp ${netRefund.toLocaleString('id-ID')}\n\n` +
                `Lanjutkan proses refund dan nonaktifkan member ini?`;
                
    if (confirm(msg)) {
        const form = document.createElement('form');
        form.method = 'POST';
        form.style.display = 'none';
        
        const actionInput = document.createElement('input');
        actionInput.name = 'action';
        actionInput.value = 'refund_member';
        form.appendChild(actionInput);
        
        const idInput = document.createElement('input');
        idInput.name = 'id';
        idInput.value = memberId;
        form.appendChild(idInput);
        
        const refundAmountInput = document.createElement('input');
        refundAmountInput.name = 'refund_amount';
        refundAmountInput.value = netRefund;
        form.appendChild(refundAmountInput);
        
        document.body.appendChild(form);
        form.submit();
    }
}
</script>
<?php endif; ?>

<?php if ($user_perms['add_member']): ?>
<div class="card">
  <div class="ct">Tambah Member Baru</div>
  <form method="POST">
    <input type="hidden" name="action" value="add"/>
    <input type="hidden" name="expiry_days" id="expiry_days" value="7"/>
    <div class="fg">
      <div class="fi"><label>Nama Member</label><input type="text" name="name" placeholder="contoh: John Doe" required/></div>
      <div class="fi"><label>Kode Akses</label><input type="text" name="custom_code" placeholder="Kosongkan untuk auto-generate"/></div>
      <div class="fi full">
        <label>Durasi Aktif</label>
        <input type="hidden" name="days" id="add_days" value="30"/>
        <div class="dur-group" style="display:flex; gap:10px; align-items:stretch;">
          <div style="flex:1; display:flex; gap:10px;">
            <button type="button" class="dur-btn selected" data-days="30" onclick="setDays(30)" style="flex:1;">30 Hari<span class="dur-badge">Premium</span></button>
          </div>
        </div>
      </div>
      <div class="fi full" style="margin-bottom: 8px;">
        <label>Harga / Pendapatan Transaksi (Rp)</label>
        <div style="background: rgba(0,230,118,0.1) !important; border: 1px solid rgba(0,230,118,0.3) !important; padding: 12px; border-radius: 8px;">
          <input type="number" id="add_manual_price" placeholder="Otomatis mengikuti paket" readonly style="width: 100%; background: transparent !important; border: none !important; color: #00e676 !important; outline: none; font-size: 14px;"/>
        </div>
        <p style="font-size:10px; color:var(--muted); margin-top:4px;">Harga dihitung otomatis berdasarkan paket dan durasi (hanya Owner yang dapat mengubah aturan harga).</p>
      </div>
      <?php renderPkgSelector('basic', 'add', [], $APP_LABELS_ALL, $APP_MAX_ALL); ?>
      <div class="fi full" style="display:flex;justify-content:flex-end;margin-top:4px">
        <button type="submit" class="btn bp">&#x2726; Tambah Member</button>
      </div>
    </div>
  </form>
</div>
<?php endif; ?>

<div class="card">
  <div class="ct">Daftar Member</div>
  <div class="sr filter-container" style="background: rgba(255,255,255,0.02); padding: 15px; border-radius: 8px; margin-bottom: 15px;">
    <form method="GET" style="display:flex; gap:10px; flex-wrap: wrap; align-items: flex-end;">
      <div style="flex: 1; min-width: 200px;">
        <label style="display:block; font-size:11px; margin-bottom:4px; color:var(--muted)">Cari Nama / Kode</label>
        <input type="search" name="search" value="<?php echo htmlspecialchars($_GET['search'] ?? ''); ?>" placeholder="Masukkan kata kunci..." style="width:100%; margin:0;" />
      </div>
      <div style="width: 150px;">
        <label style="display:block; font-size:11px; margin-bottom:4px; color:var(--muted)">Paket</label>
        <select name="f_paket" style="width:100%; margin:0; padding: 10px; background: var(--bg); border: 1px solid rgba(255,255,255,0.1); color: var(--fg); border-radius: 6px;">
          <option value="">Semua Paket</option>
          <option value="basic" <?php echo (isset($_GET['f_paket']) && $_GET['f_paket'] === 'basic') ? 'selected' : ''; ?>>Basic (Rp <?php echo number_format($pkg_prices['basic']??0, 0, ',', '.'); ?>)</option>
          <option value="pro" <?php echo (isset($_GET['f_paket']) && $_GET['f_paket'] === 'pro') ? 'selected' : ''; ?>>Pro (Rp <?php echo number_format($pkg_prices['pro']??0, 0, ',', '.'); ?>)</option>
          <option value="ultimate" <?php echo (isset($_GET['f_paket']) && $_GET['f_paket'] === 'ultimate') ? 'selected' : ''; ?>>Ultimate (Rp <?php echo number_format($pkg_prices['ultimate']??0, 0, ',', '.'); ?>)</option>
          <option value="custom" <?php echo (isset($_GET['f_paket']) && $_GET['f_paket'] === 'custom') ? 'selected' : ''; ?>>Custom</option>
        </select>
      </div>
      <div style="width: 150px;">
        <label style="display:block; font-size:11px; margin-bottom:4px; color:var(--muted)">Status</label>
        <select name="f_status" style="width:100%; margin:0; padding: 10px; background: var(--bg); border: 1px solid rgba(255,255,255,0.1); color: var(--fg); border-radius: 6px;">
          <option value="">Semua Status</option>
          <option value="aktif" <?php echo (isset($_GET['f_status']) && $_GET['f_status'] === 'aktif') ? 'selected' : ''; ?>>Aktif</option>
          <option value="nonaktif" <?php echo (isset($_GET['f_status']) && $_GET['f_status'] === 'nonaktif') ? 'selected' : ''; ?>>Nonaktif</option>
          <option value="expired" <?php echo (isset($_GET['f_status']) && $_GET['f_status'] === 'expired') ? 'selected' : ''; ?>>Expired</option>
        </select>
      </div>
      <div style="width: 150px;">
        <label style="display:block; font-size:11px; margin-bottom:4px; color:var(--muted)">Pembayaran</label>
        <select name="f_payment" style="width:100%; margin:0; padding: 10px; background: var(--bg); border: 1px solid rgba(255,255,255,0.1); color: var(--fg); border-radius: 6px;">
          <option value="">Semua Pembayaran</option>
          <option value="lunas" <?php echo (isset($_GET['f_payment']) && $_GET['f_payment'] === 'lunas') ? 'selected' : ''; ?>>Lunas</option>
          <option value="belum_lunas" <?php echo (isset($_GET['f_payment']) && $_GET['f_payment'] === 'belum_lunas') ? 'selected' : ''; ?>>Belum Lunas</option>
        </select>
      </div>
      <div style="width: 150px;">
        <label style="display:block; font-size:11px; margin-bottom:4px; color:var(--muted)">Expire (Sisa)</label>
        <select name="f_expire" style="width:100%; margin:0; padding: 10px; background: var(--bg); border: 1px solid rgba(255,255,255,0.1); color: var(--fg); border-radius: 6px;">
          <option value="">Semua Waktu</option>
          <option value="14" <?php echo (isset($_GET['f_expire']) && $_GET['f_expire'] === '14') ? 'selected' : ''; ?>>&lt; 14 Hari</option>
          <option value="7" <?php echo (isset($_GET['f_expire']) && $_GET['f_expire'] === '7') ? 'selected' : ''; ?>>&lt; 7 Hari</option>
          <option value="3" <?php echo (isset($_GET['f_expire']) && $_GET['f_expire'] === '3') ? 'selected' : ''; ?>>&lt; 3 Hari</option>
        </select>
      </div>
      <div style="width: 150px;">
        <label style="display:block; font-size:11px; margin-bottom:4px; color:var(--muted)">Tanggal Expire</label>
        <input type="date" name="f_date" value="<?php echo htmlspecialchars($_GET['f_date']??''); ?>" style="width:100%; margin:0; padding: 9px; background: var(--bg); border: 1px solid rgba(255,255,255,0.1); color: var(--fg); border-radius: 6px; font-size: 13px; outline: none;">
      </div>
      <div style="width: 150px;">
        <label style="display:block; font-size:11px; margin-bottom:4px; color:var(--muted)">Start Transaksi</label>
        <input type="date" name="f_start_date" value="<?php echo htmlspecialchars($_GET['f_start_date']??''); ?>" style="width:100%; margin:0; padding: 9px; background: var(--bg); border: 1px solid rgba(255,255,255,0.1); color: var(--fg); border-radius: 6px; font-size: 13px; outline: none;">
      </div>
      <div style="width: 150px;">
        <label style="display:block; font-size:11px; margin-bottom:4px; color:var(--muted)">End Transaksi</label>
        <input type="date" name="f_end_date" value="<?php echo htmlspecialchars($_GET['f_end_date']??''); ?>" style="width:100%; margin:0; padding: 9px; background: var(--bg); border: 1px solid rgba(255,255,255,0.1); color: var(--fg); border-radius: 6px; font-size: 13px; outline: none;">
      </div>
      <div style="width: 150px;">
        <label style="display:block; font-size:11px; margin-bottom:4px; color:var(--muted)">Urutkan (Sortir)</label>
        <select name="f_sort" style="width:100%; margin:0; padding: 10px; background: var(--bg); border: 1px solid rgba(255,255,255,0.1); color: var(--fg); border-radius: 6px;">
          <option value="newest" <?php echo (!isset($_GET['f_sort']) || $_GET['f_sort'] === 'newest') ? 'selected' : ''; ?>>Terbaru</option>
          <option value="oldest" <?php echo (isset($_GET['f_sort']) && $_GET['f_sort'] === 'oldest') ? 'selected' : ''; ?>>Terlama</option>
          <option value="expire_asc" <?php echo (isset($_GET['f_sort']) && $_GET['f_sort'] === 'expire_asc') ? 'selected' : ''; ?>>Expire Terdekat</option>
          <option value="expire_desc" <?php echo (isset($_GET['f_sort']) && $_GET['f_sort'] === 'expire_desc') ? 'selected' : ''; ?>>Expire Terjauh</option>
          <option value="price_desc" <?php echo (isset($_GET['f_sort']) && $_GET['f_sort'] === 'price_desc') ? 'selected' : ''; ?>>Harga Tertinggi</option>
          <option value="price_asc" <?php echo (isset($_GET['f_sort']) && $_GET['f_sort'] === 'price_asc') ? 'selected' : ''; ?>>Harga Terendah</option>
        </select>
      </div>
      <div style="display:flex; gap: 8px;">
        <button type="submit" class="btn bp" style="margin:0; padding: 8px 16px;">Terapkan Filter</button>
        <?php if (!empty($_GET['search']) || !empty($_GET['f_paket']) || !empty($_GET['f_status']) || !empty($_GET['f_expire']) || !empty($_GET['f_date']) || !empty($_GET['f_payment']) || !empty($_GET['f_start_date']) || !empty($_GET['f_end_date']) || (!empty($_GET['f_sort']) && $_GET['f_sort'] !== 'newest')): ?>
          <a href="?" class="btn bt" style="margin:0; padding: 8px 16px; line-height: 20px;">Reset Filter</a>
        <?php endif; ?>
      </div>
    </form>
  </div>
  <div class="tw" style="overflow: visible;"><table class="member-table">
    <thead><tr><th>#</th><th>Nama</th><th>Kode</th><th>Paket</th><th>Expire</th><th>Sisa</th><th>Login</th><th>Status</th><th>Aksi</th></tr></thead>
    <tbody>
    <?php $i=1;
    if (empty($members)): ?>
      <tr><td colspan="9" class="empty">Belum ada member. Tambahkan di atas.</td></tr>
    <?php else: foreach ($members as $r):
      $today2 = new DateTime(); $exp = new DateTime($r['expiry_date']);
      $isExp = $today2 > $exp;
      $sisa = $isExp ? 0 : (int)$today2->diff($exp)->days;
      $cls = $isExp ? 'be' : ($r['is_active'] ? 'ba' : 'bn');
      $lbl = $isExp ? 'EXPIRED' : ($r['is_active'] ? 'AKTIF' : 'NONAKTIF');
      $sc = $isExp ? 'err' : ($sisa <= 3 ? 'warn' : 'ok');
      $pkg = $r['package'] ?? 'basic';
      $pkgLbl = $PKG_LABELS[$pkg] ?? 'Basic';
    ?>
      <tr>
        <td data-label="#" style="color:var(--muted)"><?php echo $i++; ?></td>
        <td data-label="Nama">
          <strong><?php echo htmlspecialchars($r['name']); ?></strong>
          <?php if(!empty($r['price_paid']) && $user_perms['view_stats']): ?>
          <?php 
              $ps = $r['payment_status'] ?? 'lunas';
              $ps_color = $ps === 'belum_lunas' ? '#ff4d4d' : '#00e676';
              $ps_text = $ps === 'belum_lunas' ? '(Belum Lunas)' : '(Lunas)';
          ?>
          <div style="font-size:9px; color:<?php echo $ps_color; ?>; margin-top:3px;">+Rp <?php echo number_format($r['price_paid'],0,',','.'); ?> <?php echo $ps_text; ?></div>
          <?php endif; ?>
          <?php if(!empty($r['updated_by'])): ?>
          <div style="font-size:8.5px; color:var(--muted); margin-top:3px; font-style:italic;">Edit: <?php echo htmlspecialchars($r['updated_by']); ?></div>
          <?php elseif(!empty($r['created_by'])): ?>
          <div style="font-size:8.5px; color:var(--muted); margin-top:3px; font-style:italic;">Input: <?php echo htmlspecialchars($r['created_by']); ?></div>
          <?php endif; ?>
        </td>
        <td data-label="Kode"><code class="kd"><?php echo htmlspecialchars($r['code']); ?></code></td>
        <td data-label="Paket"><span class="badge pb-<?php echo $pkg; ?>"><?php echo $pkgLbl; ?></span></td>
        <td data-label="Expire" style="color:<?php echo $isExp?'var(--err)':'var(--sub)'; ?>"><?php echo $r['expiry_date']; ?></td>
        <td data-label="Sisa"><span class="sisa <?php echo $sc; ?>"><?php echo $isExp ? 'Expired' : "{$sisa} hari"; ?></span></td>
        <td data-label="Login" style="color:var(--muted);font-size:11px"><?php echo $r['last_used'] ? date('d/m/Y H:i',strtotime($r['last_used'])) : '-'; ?></td>
        <td data-label="Status"><span class="badge <?php echo $cls; ?>"><?php echo $lbl; ?></span></td>
        <td data-label="Aksi">
          <div class="act-dropdown">
            <button class="act-btn" onclick="toggleMenu(this)">&#x270E; Aksi &#x25BC;</button>
            <div class="act-menu">
              <?php if ($user_perms['edit_member']): ?>
              <a href="?edit=<?php echo $r['id']; ?>" class="m-edit">&#x270E; Edit</a>
              <form method="POST" style="margin:0"><input type="hidden" name="action" value="toggle"/><input type="hidden" name="id" value="<?php echo $r['id']; ?>"/><button type="submit"><?php echo $r['is_active']?'&#x1F512; Nonaktifkan':'&#x1F513; Aktifkan'; ?></button></form>
              <form method="POST" style="margin:0" onsubmit="return confirm('Hapus member ini?')"><input type="hidden" name="action" value="delete"/><input type="hidden" name="id" value="<?php echo $r['id']; ?>"/><button type="submit" class="m-del">&#x1F5D1; Hapus</button></form>
              <?php else: ?>
              <button type="button" onclick="alert('Akses ditolak. Anda tidak memiliki izin untuk mengedit member.')" class="m-edit" style="color:var(--muted)">&#x270E; Edit (Terkunci)</button>
              <?php endif; ?>
            </div>
          </div>
        </td>
      </tr>
    <?php endforeach; endif; ?>
    </tbody>
  </table></div>
</div>
</div>

<!-- DASHBOARD MITRA TAB -->
<div id="tab-mitradashboard" class="tab-content <?php echo $tab==='mitradashboard'?'active':''; ?>">
  <div class="card">
    <div class="ct" style="display:flex; justify-content:space-between; align-items:center;">
        <span>Laporan Pendapatan & Komisi</span>
        <div style="display:flex; gap:10px; font-size:11px;">
            <span id="sync_status" style="color:var(--muted);">Syncing...</span>
            <button onclick="fetchDashboardStats()" class="btn bsm bt" style="padding:4px 8px;">&#x21bb; Refresh</button>
        </div>
    </div>
    
    <!-- Filter Controls -->
    <div class="sr filter-container" style="background: rgba(255,255,255,0.02); padding: 15px; border-radius: 8px; margin-bottom: 15px; display:flex; gap:10px; flex-wrap:wrap; align-items:flex-end;">
        <div>
            <label style="display:block; font-size:11px; margin-bottom:4px; color:var(--muted)">Periode</label>
            <select id="dash_range" onchange="toggleCustomDate(); fetchDashboardStats();" style="width:150px; padding:8px; border-radius:6px;">
                <option value="7">7 Hari Terakhir</option>
                <option value="14">14 Hari Terakhir</option>
                <option value="30">1 Bulan Terakhir</option>
                <option value="custom">Custom Range</option>
            </select>
        </div>
        <div id="custom_date_wrapper" style="display:none; gap:10px;">
            <div>
                <label style="display:block; font-size:11px; margin-bottom:4px; color:var(--muted)">Start Date</label>
                <input type="date" id="dash_start" style="padding:7px; border-radius:6px;"/>
            </div>
            <div>
                <label style="display:block; font-size:11px; margin-bottom:4px; color:var(--muted)">End Date</label>
                <input type="date" id="dash_end" style="padding:7px; border-radius:6px;"/>
            </div>
            <button onclick="fetchDashboardStats()" class="btn bp" style="padding:8px 12px; margin-bottom:2px;">Terapkan</button>
        </div>
        <div style="flex:1; text-align:right;">
            <button onclick="exportDashboardData('csv')" class="btn be2" style="padding:8px 12px; margin-bottom:2px;">&#x1F4E4; Export Excel/CSV</button>
        </div>
    </div>

    <!-- Summary Stats -->
    <!-- Summary Stats: 3 cards only -->
    <div class="stats" style="grid-template-columns: repeat(3, 1fr);">
        <div class="sc t">
            <?php 
                $rate_config = $_SESSION['commission_rate'] ?? [];
                if (!is_array($rate_config)) {
                    $rate_config = ['basic' => (int)$rate_config, 'pro' => (int)$rate_config, 'ultimate' => (int)$rate_config];
                }
            ?>
            <div class="sv" style="font-size:14px; line-height:1.2;">
              B: Rp <?php echo number_format($rate_config['basic'] ?? 0, 0, ',', '.'); ?><br>
              P: Rp <?php echo number_format($rate_config['pro'] ?? 0, 0, ',', '.'); ?><br>
              U: Rp <?php echo number_format($rate_config['ultimate'] ?? 0, 0, ',', '.'); ?>
            </div>
            <div class="sl">Komisi per Transaksi</div>
        </div>
        <div class="sc e">
            <div class="sv" id="stat_sales" style="color:#ff4d4d;">Rp 0</div>
            <div class="sl">Penjualan (Gross) Periode Ini</div>
        </div>
        <div class="sc a" style="background: linear-gradient(135deg, rgba(0,230,118,0.1), rgba(0,200,100,0.1)); border-color: rgba(0,230,118,0.3);">
            <div class="sv" id="stat_com" style="color: #00e676; font-size: 20px;">Rp 0</div>
            <div class="sl" style="color: #00e676;">Komisi Periode Ini</div>
        </div>
    </div>
    
    <!-- Chart Data Table (Simplified representation) -->
    <div style="margin-top:20px;">
        <h3 style="font-size:13px; color:var(--light); margin-bottom:10px;">Detail Harian (Periode Terpilih)</h3>
        <div class="tw" style="max-height: 300px; overflow-y: auto;">
            <table id="dash_table" class="table">
                <thead>
                    <tr>
                        <th>Tanggal</th>
                        <th>Member Baru</th>
                        <th>Penjualan (Gross)</th>
                        <th>Komisi Didapat</th>
                    </tr>
                </thead>
                <tbody id="dash_table_body">
                    <tr><td colspan="4" style="text-align:center;">Memuat data...</td></tr>
                </tbody>
            </table>
        </div>
    </div>
    

  </div>
</div>

<!-- AUDIT TAB -->

<!-- PRODUCTS & PRICING TAB -->
<div id="tab-products" class="tab-content <?php echo $tab==='products'?'active':''; ?>">
  <div class="card">
    <div class="ct">📦 Produk & Harga Paket</div>
    <div style="font-size:12px; color:var(--muted); margin-bottom: 20px;">Katalog produk yang tersedia untuk dijual. Harga per 30 hari ditampilkan di bawah.</div>
    
    <div style="display:grid; grid-template-columns:repeat(auto-fill, minmax(250px, 1fr)); gap:15px;">
      <?php 
      $allApps_mitra = loadData('applications.json');
      $activeApps_mitra = array_filter($allApps_mitra, function($a) { return !empty($a['is_active']); });
      $PACKAGES_CONFIG_MITRA = loadData('packages.json');
      
      $mitra_target = 'mitra_' . $_SESSION['user_id'];
      
      foreach (['basic', 'pro', 'ultimate'] as $ptype):
        $pkg_config = $PACKAGES_CONFIG_MITRA[$mitra_target] ?? $PACKAGES_CONFIG_MITRA['main'] ?? [];
        $apps_in_pkg = $pkg_config[$ptype] ?? [];
        $price = $pkg_prices[$ptype] ?? 0;
        $gradient = $ptype === 'basic' ? 'linear-gradient(135deg, rgba(0,150,255,0.12), rgba(0,100,200,0.06))' :
                  ($ptype === 'pro' ? 'linear-gradient(135deg, rgba(150,0,255,0.12), rgba(100,0,200,0.06))' :
                   'linear-gradient(135deg, rgba(255,200,0,0.12), rgba(200,150,0,0.06))');
        $badgeColor = $ptype === 'basic' ? '#0099ff' : ($ptype === 'pro' ? '#9966ff' : '#ffcc00');
      ?>
        <div style="background:<?php echo $gradient; ?>; border:1px solid var(--border); border-radius:12px; padding:20px; position:relative; overflow:hidden;">
          <div style="position:absolute; top:10px; right:10px; background:<?php echo $badgeColor; ?>20; color:<?php echo $badgeColor; ?>; border:1px solid <?php echo $badgeColor; ?>40; padding:2px 8px; border-radius:6px; font-size:9px; font-weight:700; text-transform:uppercase;"><?php echo ucfirst($ptype); ?></div>
          <div style="font-size:16px; font-weight:800; margin-bottom:5px;">Paket <?php echo ucfirst($ptype); ?></div>
          <div style="font-size:24px; font-weight:900; color:#00e676; margin-bottom:12px;">Rp <?php echo number_format($price, 0, ',', '.'); ?></div>
          <div style="font-size:10px; color:var(--muted); margin-bottom:10px;">per 30 hari</div>
          <div style="border-top:1px solid var(--border); padding-top:10px;">
            <div style="font-size:10px; color:var(--muted); margin-bottom:8px; text-transform:uppercase; letter-spacing:1px;">Aplikasi yang termasuk:</div>
            <?php if (empty($apps_in_pkg)): ?>
              <div style="font-size:11px; color:var(--muted); font-style:italic;">Belum dikonfigurasi</div>
            <?php else: foreach ($apps_in_pkg as $app_id => $srv_count):
              $app_name_p = $app_id;
              foreach ($activeApps_mitra as $a) { if ($a['id'] === $app_id) { $app_name_p = $a['name']; break; } }
            ?>
              <div style="font-size:11px; margin-bottom:4px; display:flex; justify-content:space-between;">
                <span>✅ <?php echo htmlspecialchars($app_name_p); ?></span>
                <span style="color:var(--muted);"><?php echo $srv_count; ?> server</span>
              </div>
            <?php endforeach; endif; ?>
          </div>
        </div>
      <?php endforeach; ?>
    </div>
    
    <div style="margin-top:15px; padding:12px; background:rgba(0,200,100,0.08); border:1px solid rgba(0,200,100,0.2); border-radius:8px;">
      <div style="font-size:11px; color:#00e676;">💡 <strong>Cara menjual:</strong> Klik tab "Member Saya" → Tambah Member Baru → Pilih paket yang sesuai. Deposit akan otomatis terpotong sesuai harga.</div>
    </div>
  </div>
</div>





<div id="tab-audit" class="tab-content <?php echo $tab==='audit'?'active':''; ?>">
  <div class="card">
    <div class="ct">Histori Log & Transaksi</div>
    <div style="font-size:12px; color:var(--muted); margin-bottom: 20px;">Catatan aktivitas krusial seperti penambahan member, perpanjangan (upgrade), dan refund pengembalian dana yang Anda lakukan.</div>
    <div class="tw" style="overflow: visible;">
      <table class="table">
        <thead>
          <tr>
            <th style="width: 15%">WAKTU</th>
            <th style="width: 15%">AKSI</th>
            <th style="width: 25%">MEMBER (NAMA)</th>
            <th style="width: 25%">KETERANGAN</th>
            <th style="width: 20%">SALDO KOMISI</th>
          </tr>
        </thead>
        <tbody>
          <?php
          $auditFile = DATA_DIR . '/audit.json';
          $auditLogs = file_exists($auditFile) ? json_decode(file_get_contents($auditFile), true) : [];
          
          // Cari waktu reset terakhir untuk mitra ini
          $last_reset_time = null;
          foreach ($auditLogs as $log) {
              if (isset($log['action']) && $log['action'] === 'reset_data_mitra' && isset($log['target_user_id']) && $log['target_user_id'] == $_SESSION['user_id']) {
                  $last_reset_time = new DateTime($log['time']);
              }
          }
          
          $auditLogs = array_reverse($auditLogs); // Show newest first
          
          // Filter logs for this specific mitra only, dan sembunyikan log sebelum reset terakhir
          $mitraLogs = array_filter($auditLogs, function($log) use ($last_reset_time) {
              if (!isset($log['mitra_id']) || $log['mitra_id'] != $_SESSION['user_id']) return false;
              
              if ($last_reset_time) {
                  $logTime = new DateTime($log['time']);
                  if ($logTime <= $last_reset_time) return false;
              }
              return true;
          });
          
          if (empty($mitraLogs)):
          ?>
          <tr><td colspan="5" style="text-align:center; padding: 20px;">Belum ada histori log atau transaksi.</td></tr>
          <?php else: foreach ($mitraLogs as $log): ?>
          <tr>
            <td data-label="WAKTU"><?php echo $log['time'] ?? '-'; ?></td>
            <td data-label="AKSI"><span style="background: rgba(255,255,255,0.1); padding: 4px 8px; border-radius: 4px; font-size: 11px; font-weight: bold;"><?php echo strtoupper(str_replace('_', ' ', $log['action'] ?? '-')); ?></span></td>
            <td data-label="MEMBER (NAMA)"><?php echo htmlspecialchars($log['member_name'] ?? '-'); ?> <br><span style="font-size:9px;color:var(--muted);">ID: <?php echo htmlspecialchars($log['member_id'] ?? '-'); ?></span></td>
            <td data-label="KETERANGAN">
              <?php 
              if ($log['action'] === 'add_member' || $log['action'] === 'upgrade_member') {
                  echo 'Harga/Penjualan: Rp ' . number_format($log['price'] ?? $log['price_added'] ?? 0, 0, ',', '.');
              } elseif ($log['action'] === 'refund_member') {
                  echo '<span style="color:var(--err);">Refund: Rp ' . number_format($log['refund_amount'] ?? 0, 0, ',', '.') . '</span>';
              } elseif ($log['action'] === 'reset_saldo_mitra') {
                  echo '<span style="color:var(--err);">Reset Saldo oleh Owner</span>';
              } else {
                  echo '-';
              }
              ?>
            </td>
            <td data-label="SALDO KOMISI">
              <?php 
              if ($log['action'] === 'reset_saldo_mitra') {
                  echo '<span style="color:var(--err); font-weight:bold;">- Rp ' . number_format($log['amount_reset'] ?? 0, 0, ',', '.') . '</span>';
              } elseif (isset($log['commission'])) {
                  echo '<span style="color:#00e676; font-weight:bold;">+ Rp ' . number_format($log['commission'], 0, ',', '.') . '</span>';
              } else {
                  echo '-';
              }
              ?>
            </td>
          </tr>
          <?php endforeach; endif; ?>
        </tbody>
      </table>
    </div>
  </div>
</div>

</div> <!-- End Container -->

<div class="footer" style="text-align: center; padding: 20px; color: var(--muted); font-size: 12px;">TEKNO APPS Member Manager &copy; <?php echo date('Y'); ?> (Mitra Portal)</div>

<script>
function switchTab(id) {
    document.querySelectorAll('.tab-btn').forEach(b=>b.classList.remove('active'));
    document.querySelectorAll('.tab-content').forEach(c=>c.classList.remove('active'));
    if(event && event.target && event.target.classList.contains('tab-btn')) {
        event.target.classList.add('active');
    } else {
        const btn = document.querySelector(`.tab-btn[onclick="switchTab('${id}')"]`);
        if(btn) btn.classList.add('active');
    }
    const tabContent = document.getElementById('tab-'+id);
    if(tabContent) tabContent.classList.add('active');
    
    // Update URL without reloading the page
    const url = new URL(window.location);
    url.searchParams.set('tab', id);
    window.history.pushState({}, '', url);
}
function toggleMenu(btn) {
    const menu = btn.nextElementSibling;
    const isVisible = menu.style.display === 'block';
    document.querySelectorAll('.act-menu').forEach(m => m.style.display = 'none');
    if (!isVisible) menu.style.display = 'block';
}
window.addEventListener('click', function(e) {
    if (!e.target.matches('.act-btn')) {
        document.querySelectorAll('.act-menu').forEach(m => m.style.display = 'none');
    }
});
function setDays(d) {
    const addDays = document.getElementById('add_days');
    const expiryDays = document.getElementById('expiry_days');
    if(addDays) addDays.value = d;
    if(expiryDays) expiryDays.value = d;
    document.querySelectorAll('.dur-btn').forEach(btn => btn.classList.remove('selected'));
    if(event && event.currentTarget) {
        event.currentTarget.classList.add('selected');
    }
    const customDaysInput = document.getElementById('custom_days_input');
    if(customDaysInput) customDaysInput.value = '';
    recalculatePrice();
}
function setCustomDays(val) {
    let d = parseInt(val);
    if (isNaN(d) || d < 1) d = 1;
    const addDays = document.getElementById('add_days');
    const expiryDays = document.getElementById('expiry_days');
    if(addDays) addDays.value = d;
    if(expiryDays) expiryDays.value = d;
    document.querySelectorAll('.dur-btn').forEach(btn => btn.classList.remove('selected'));
    recalculatePrice();
}
function setPkg(prefix, pkg, price) {
    const pkgInput = document.getElementById(prefix + '_pkg_val');
    if(pkgInput) pkgInput.value = pkg;
    
    document.querySelectorAll('#' + prefix + '_pkg_group .pkg-btn').forEach(btn => btn.classList.remove('selected'));
    const targetBtn = document.querySelector('#' + prefix + '_pkg_group .pkg-btn[data-pkg="' + pkg + '"]');
    if(targetBtn) targetBtn.classList.add('selected');
    
    recalculatePrice();
    renderAppList(prefix, pkg);
}
function toggleSrv(id, show) {
    const srv = document.getElementById(id);
    if(srv) srv.disabled = !show;
}

const PKG_PRICES = <?php echo json_encode($pkg_prices); ?>;

function recalculatePrice() {
    const daysInput = document.getElementById('add_days');
    const pkgInput = document.getElementById('add_pkg_val');
    const manualPriceInput = document.getElementById('add_manual_price');
    
    if (daysInput && pkgInput && manualPriceInput) {
        const days = parseInt(daysInput.value) || 0;
        const pkg = pkgInput.value || 'basic';
        const basePrice = PKG_PRICES[pkg] || 0;
        
        const calculatedPrice = Math.round((basePrice / 30) * days);
        manualPriceInput.placeholder = `Otomatis: Rp ${calculatedPrice.toLocaleString('id-ID')}`;
        if (pkg === 'custom') {
            manualPriceInput.placeholder = 'Harga wajib diisi (misal: 250000)';
        }
    }
}

document.addEventListener('DOMContentLoaded', () => {
    recalculatePrice();
});

// Data from PHP to JS
const appLabelsAll = <?php echo json_encode($APP_LABELS_ALL); ?>;
const appMaxAll = <?php echo json_encode($APP_MAX_ALL); ?>;
const PACKAGES_CONFIG = <?php echo json_encode($PACKAGES_CONFIG); ?>;
const MITRA_ID = <?php echo json_encode($_SESSION['user_id'] ?? null); ?>;

function renderAppList(prefix, pkg) {
    const container = document.getElementById(prefix + '_app_list_container');
    if (!container) return;
    
    const target = 'mitra_' + MITRA_ID;
    const config = PACKAGES_CONFIG[target] || PACKAGES_CONFIG['main'] || {};
    const pkgData = config[pkg] || {};
    
    let html = '';
    for (const aid in appLabelsAll) {
        let isChecked = false;
        let maxSrv = appMaxAll[aid] || 1;
        let srvVal = 1;
        
        if (pkgData[aid]) {
            isChecked = true;
            srvVal = Math.min(pkgData[aid], maxSrv);
        }

        const isCheckedAttr = isChecked ? 'checked' : '';
        const rowStyle = isChecked 
            ? 'background: rgba(0, 230, 118, 0.1); border-left: 3px solid #00e676; padding: 8px 12px; border-radius: 6px; margin-bottom: 6px; transition: all 0.3s ease;' 
            : 'opacity: 0.5; filter: grayscale(100%); padding: 8px 12px; border-radius: 6px; margin-bottom: 6px; transition: all 0.3s ease;';
        const labelColor = isChecked ? '#00e676' : 'var(--text)';
        const srvColor = isChecked ? '#00e676' : 'var(--muted)';
        const srvInputStyle = isChecked 
            ? 'background: rgba(0, 230, 118, 0.15); border-color: rgba(0, 230, 118, 0.3); color: #00e676; font-weight: bold; width: 60px;' 
            : 'background: var(--deep); border-color: var(--border); color: var(--text); font-weight: bold; width: 60px;';
        
        html += `<div class="app-row" style="${rowStyle}">
            <div class="app-chk">
                <input type="checkbox" name="app_${aid}" id="${prefix}_${aid}" ${isCheckedAttr} disabled style="transform: scale(1.2); margin-right: 10px; cursor: not-allowed;" />
                <label for="${prefix}_${aid}" style="font-weight: 600; color: ${labelColor}; cursor: not-allowed;">${appLabelsAll[aid]}</label>
            </div>`;
            
        if (maxSrv > 1) {
            html += `<div class="srv-ctrl">
                <label style="color: ${srvColor}; font-weight: 600;">Server:</label>
                <input type="number" name="srv_${aid}" id="${prefix}_${aid}_srv" value="${srvVal}" min="1" max="${maxSrv}" disabled style="${srvInputStyle} cursor: not-allowed;" />
            </div>`;
        }
        
        html += `</div>`;
    }
    
    container.innerHTML = html;
}

// Initial render
window.addEventListener('load', () => {
    renderAppList('add', 'basic');
    renderAppList('ed', document.getElementById('ed_pkg_val')?.value || 'basic');
});
</script>
<script>
// Dashboard Logic
let syncInterval = null;
let retryCount = 0;
let dashboardCache = null;

function toggleCustomDate() {
    const val = document.getElementById('dash_range').value;
    document.getElementById('custom_date_wrapper').style.display = val === 'custom' ? 'flex' : 'none';
}

function fetchDashboardStats() {
    const range = document.getElementById('dash_range').value;
    const start = document.getElementById('dash_start').value;
    const end = document.getElementById('dash_end').value;
    const statusEl = document.getElementById('sync_status');
    
    statusEl.innerHTML = '<span style="color:#ffaa00;">Syncing...</span>';
    
    const url = '?api_dashboard_stats=1&range=' + range + '&start_date=' + start + '&end_date=' + end;
    
    fetch(url)
        .then(res => res.text())
        .then(text => {
            try {
                const data = JSON.parse(text);
                if (data.status === 'success') {
                dashboardCache = data;
                retryCount = 0;
                
                // Update Summary
                document.getElementById('stat_sales').innerText = 'Rp ' + data.summary.gross_sales.toLocaleString('id-ID');
                document.getElementById('stat_com').innerText = 'Rp ' + data.summary.commission.toLocaleString('id-ID');
                
                // Update Table
                const tbody = document.getElementById('dash_table_body');
                tbody.innerHTML = '';
                
                // Pagination & Data handling
                const dates = Object.keys(data.chart).sort((a,b) => new Date(b) - new Date(a)); // Descending
                
                if (dates.length === 0) {
                    tbody.innerHTML = '<tr><td colspan="4" style="text-align:center;">Tidak ada data pada periode ini.</td></tr>';
                } else {
                    dates.forEach(date => {
                        const row = data.chart[date];
                        if (row.members > 0 || row.sales > 0 || row.commission > 0) {
                            tbody.innerHTML += `<tr>
                                <td data-label="Tanggal">${date}</td>
                                <td data-label="Member Baru">${row.members}</td>
                                <td data-label="Penjualan (Gross)">Rp ${row.sales.toLocaleString('id-ID')}</td>
                                <td data-label="Komisi Didapat" style="color:#00e676; font-weight:bold;">Rp ${row.commission.toLocaleString('id-ID')}</td>
                            </tr>`;
                        }
                    });
                    
                    if (tbody.innerHTML === '') {
                        tbody.innerHTML = '<tr><td colspan="4" style="text-align:center;color:var(--muted);">Tidak ada transaksi pada periode ini.</td></tr>';
                    }
                }
                
                statusEl.innerHTML = '<span style="color:#00e676;">&#x2714; Tersinkronisasi (' + data.last_sync + ')</span>';
            }
            } catch(e) {
                console.error("Failed parsing JSON. Raw response: ", text);
                throw e;
            }
        })
        .catch(err => {
            console.error('Sync error:', err);
            if (retryCount < 3) {
                retryCount++;
                statusEl.innerHTML = '<span style="color:#ff4d4d;">Gagal. Retry ' + retryCount + '/3...</span>';
                setTimeout(fetchDashboardStats, 2000);
            } else {
                statusEl.innerHTML = '<span style="color:#ff4d4d;">Koneksi terputus. Menggunakan cache lokal.</span>';
            }
        });
}

function exportDashboardData(format) {
    if (!dashboardCache) {
        alert('Data belum termuat, silakan tunggu...');
        return;
    }
    
    let csv = 'Tanggal,Member Baru,Penjualan Gross,Komisi\n';
    const dates = Object.keys(dashboardCache.chart).sort();
    dates.forEach(date => {
        const r = dashboardCache.chart[date];
        csv += `${date},${r.members},${r.sales},${r.commission}\n`;
    });
    
    const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
    const link = document.createElement("a");
    const url = URL.createObjectURL(blob);
    link.setAttribute("href", url);
    link.setAttribute("download", "laporan_pendapatan_mitra.csv");
    link.style.visibility = 'hidden';
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
}

// Auto sync every 5 mins (300000 ms)
window.addEventListener('load', () => {
    if (document.getElementById('tab-mitradashboard')) {
        fetchDashboardStats();
        syncInterval = setInterval(fetchDashboardStats, 300000);
    }

});

</script>

</body>
</html>
