<?php
declare(strict_types=1);

/**
 * /admin/users/edit.php
 * Адмін: повне редагування користувача:
 * - email, username, ПІБ, стать, дата народження
 * - країна (dropdown ISO-2 + підтримка users.country_code якщо є), місто, освіта, місце роботи, про себе
 * - роль, мова
 * - зміна пароля (без поточного)
 * - зміна аватарки/обкладинки (upload) + видалення (і фізично з сервера)
 * - при зміні username: перенос /upload/<old>/ -> /upload/<new>/ + оновлення avatar_path/cover_path
 * - при зміні username: best-effort оновлення шляхів у типових таблицях вкладень (post_attachments/comment_attachments)
 *
 * Оптимізовано:
 * - safe back URL: бере back з GET/POST (і лише на /admin/users/ або /admin/users.php), інакше fallback на referer
 * - безпечне видалення файлів: тільки всередині /upload/<folder>/(avatar|cover)/
 * - більш надійне перенесення upload-папки при зміні username + захист від колізій папок
 * - валідація дат (реальна дата), роль/мова з whitelist
 */

require_once __DIR__ . '/../../includes/start.php';
require_role(['admin']);

require_once __DIR__ . '/../_helpers.php';
require_once __DIR__ . '/../_sidebar.php';
require_once __DIR__ . '/../_csrf.php';

$pdo = db();

$title = admin_tt('edit_user_full', 'Редагування користувача', 'Редактирование пользователя', 'Edit user');

/* =========================
   SEO: адмінка НЕ індексується
========================= */
$meta_robots = 'noindex, nofollow, noarchive, nosnippet';
$meta_desc   = '';
$cid = (int)($_GET['id'] ?? 0);
if (function_exists('abs_url')) {
    $canonical = abs_url('/admin/users/edit.php?id=' . $cid);
} else {
    $canonical = '/admin/users/edit.php?id=' . $cid;
}
if (!headers_sent()) {
    header('X-Robots-Tag: noindex, nofollow, noarchive, nosnippet', true);
}

/* ===== helpers ===== */
if (!function_exists('h')) {
    function h(?string $s): string { return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }
}
if (!function_exists('starts_with')) {
    function starts_with(string $hay, string $needle): bool {
        return $needle === '' || (strlen($hay) >= strlen($needle) && substr($hay, 0, strlen($needle)) === $needle);
    }
}
if (!function_exists('safe_user_folder')) {
    function safe_user_folder(string $username, int $userId): string {
        $s = preg_replace('~[^a-zA-Z0-9_\-]+~', '_', $username) ?: '';
        $s = trim((string)$s, '_');
        return $s !== '' ? $s : ('user_' . $userId);
    }
}
if (!function_exists('upload_base_dir')) {
    function upload_base_dir(): string {
        $base = realpath(__DIR__ . '/../../upload');
        if ($base && is_dir($base)) return $base;

        $base = __DIR__ . '/../../upload';
        if (!is_dir($base)) @mkdir($base, 0775, true);

        $rp = realpath($base);
        return ($rp && is_dir($rp)) ? $rp : $base;
    }
}
if (!function_exists('path_is_inside')) {
    function path_is_inside(string $path, string $baseDir): bool {
        $base = realpath($baseDir);
        if ($base === false) return false;

        $real = realpath($path);
        if ($real === false) return false;

        $base = rtrim($base, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
        $real = rtrim($real, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;

        return str_starts_with($real, $base);
    }
}
if (!function_exists('web_to_fs_path')) {
    function web_to_fs_path(string $webPath): string {
        return __DIR__ . '/../..' . $webPath;
    }
}
if (!function_exists('extract_upload_folder_from_webpath')) {
    function extract_upload_folder_from_webpath(string $webPath): string {
        $webPath = trim($webPath);
        if ($webPath === '') return '';

        if (preg_match('~^https?://~i', $webPath)) {
            $p = parse_url($webPath);
            $webPath = (string)($p['path'] ?? '');
        }

        if ($webPath === '' || $webPath[0] !== '/') return '';
        if (!str_starts_with($webPath, '/upload/')) return '';

        $rest = substr($webPath, strlen('/upload/'));
        if ($rest === false || $rest === '') return '';

        $parts = explode('/', $rest, 2);
        $folder = trim((string)($parts[0] ?? ''));

        if ($folder === '' || $folder === '.' || $folder === '..') return '';
        if (str_contains($folder, '/') || str_contains($folder, '\\')) return '';
        if (str_contains($folder, '..')) return '';

        return $folder;
    }
}
if (!function_exists('sanitize_user_folder')) {
    function sanitize_user_folder(string $folder, int $userId): string {
        $folder = trim($folder);
        if ($folder === '' || $folder === '.' || $folder === '..') return 'user_' . $userId;

        $folder = preg_replace('~[^\pL\pN_\-\.]+~u', '_', $folder) ?? '';
        $folder = trim($folder, '._');

        if ($folder === '' || $folder === '.' || $folder === '..') return 'user_' . $userId;
        if (str_contains($folder, '..')) return 'user_' . $userId;

        return $folder;
    }
}
if (!function_exists('delete_web_file_safe')) {
    /**
     * Видаляємо файл ТІЛЬКИ якщо:
     * - він під /upload/
     * - його folder входить в allowedFolders
     * - шлях містить /<type>/ (avatar|cover) відразу після folder
     * - фізично файл всередині upload_base_dir()
     */
    function delete_web_file_safe(string $webPath, array $allowedFolders, string $type): void {
        $webPath = trim($webPath);
        if ($webPath === '') return;

        if (preg_match('~^https?://~i', $webPath)) {
            $p = parse_url($webPath);
            $webPath = (string)($p['path'] ?? '');
        }

        if ($webPath === '' || $webPath[0] !== '/') return;
        if (!str_starts_with($webPath, '/upload/')) return;

        $folder = extract_upload_folder_from_webpath($webPath);
        if ($folder === '') return;

        $ok = false;
        foreach ($allowedFolders as $af) {
            if ($af !== '' && $folder === $af) { $ok = true; break; }
        }
        if (!$ok) return;

        $needle = '/upload/' . $folder . '/' . $type . '/';
        if (strpos($webPath, $needle) !== 0) return;

        $fs = web_to_fs_path($webPath);
        if (!is_file($fs)) return;

        $base = upload_base_dir();
        if (!path_is_inside($fs, $base)) return;

        @unlink($fs);
    }
}
if (!function_exists('move_dir_recursive')) {
    function move_dir_recursive(string $src, string $dst): bool {
        if (!is_dir($src)) return true;

        $dstParent = dirname($dst);
        if (!is_dir($dstParent)) @mkdir($dstParent, 0775, true);

        if (@rename($src, $dst)) return true;

        try {
            $srcIt = new RecursiveIteratorIterator(
                new RecursiveDirectoryIterator($src, FilesystemIterator::SKIP_DOTS),
                RecursiveIteratorIterator::SELF_FIRST
            );

            foreach ($srcIt as $item) {
                $target = $dst . DIRECTORY_SEPARATOR . $srcIt->getSubPathName();
                if ($item->isDir()) {
                    if (!is_dir($target)) @mkdir($target, 0775, true);
                } else {
                    if (!is_dir(dirname($target))) @mkdir(dirname($target), 0775, true);
                    @copy((string)$item, $target);
                }
            }

            $delIt = new RecursiveIteratorIterator(
                new RecursiveDirectoryIterator($src, FilesystemIterator::SKIP_DOTS),
                RecursiveIteratorIterator::CHILD_FIRST
            );

            foreach ($delIt as $item) {
                if ($item->isDir()) @rmdir((string)$item);
                else @unlink((string)$item);
            }
            @rmdir($src);

            return is_dir($dst);
        } catch (Throwable $e) {
            return false;
        }
    }
}
if (!function_exists('is_valid_date_ymd')) {
    function is_valid_date_ymd(string $s): bool {
        $s = trim($s);
        if (!preg_match('~^\d{4}-\d{2}-\d{2}$~', $s)) return false;
        $dt = DateTime::createFromFormat('Y-m-d', $s);
        if (!$dt) return false;
        return $dt->format('Y-m-d') === $s;
    }
}
if (!function_exists('admin_norm_local_url')) {
    function admin_norm_local_url(string $raw): string {
        $raw = trim($raw);
        if ($raw === '') return '';

        if (preg_match('~^https?://~i', $raw)) {
            $p = parse_url($raw);
            $path = (string)($p['path'] ?? '');
            $q = isset($p['query']) && (string)$p['query'] !== '' ? ('?' . (string)$p['query']) : '';
            $raw = $path . $q;
        }

        if ($raw === '' || $raw[0] !== '/') return '';
        if (str_starts_with($raw, '//')) return '';

        return $raw;
    }
}

/* ===== countries full ISO list (code => EN name) ===== */
$COUNTRIES = [
    'AF'=>'Afghanistan','AL'=>'Albania','DZ'=>'Algeria','AS'=>'American Samoa','AD'=>'Andorra','AO'=>'Angola','AI'=>'Anguilla','AQ'=>'Antarctica','AG'=>'Antigua and Barbuda','AR'=>'Argentina','AM'=>'Armenia','AW'=>'Aruba','AU'=>'Australia','AT'=>'Austria','AZ'=>'Azerbaijan',
    'BS'=>'Bahamas','BH'=>'Bahrain','BD'=>'Bangladesh','BB'=>'Barbados','BY'=>'Belarus','BE'=>'Belgium','BZ'=>'Belize','BJ'=>'Benin','BM'=>'Bermuda','BT'=>'Bhutan','BO'=>'Bolivia','BA'=>'Bosnia and Herzegovina','BW'=>'Botswana','BV'=>'Bouvet Island','BR'=>'Brazil','IO'=>'British Indian Ocean Territory','BN'=>'Brunei','BG'=>'Bulgaria','BF'=>'Burkina Faso','BI'=>'Burundi',
    'KH'=>'Cambodia','CM'=>'Cameroon','CA'=>'Canada','CV'=>'Cape Verde','KY'=>'Cayman Islands','CF'=>'Central African Republic','TD'=>'Chad','CL'=>'Chile','CN'=>'China','CX'=>'Christmas Island','CC'=>'Cocos (Keeling) Islands','CO'=>'Colombia','KM'=>'Comoros','CG'=>'Congo','CD'=>'Congo (DRC)','CK'=>'Cook Islands','CR'=>'Costa Rica','CI'=>"Côte d’Ivoire",'HR'=>'Croatia','CU'=>'Cuba','CY'=>'Cyprus','CZ'=>'Czechia',
    'DK'=>'Denmark','DJ'=>'Djibouti','DM'=>'Dominica','DO'=>'Dominican Republic',
    'EC'=>'Ecuador','EG'=>'Egypt','SV'=>'El Salvador','GQ'=>'Equatorial Guinea','ER'=>'Eritrea','EE'=>'Estonia','SZ'=>'Eswatini','ET'=>'Ethiopia',
    'FK'=>'Falkland Islands','FO'=>'Faroe Islands','FJ'=>'Fiji','FI'=>'Finland','FR'=>'France','GF'=>'French Guiana','PF'=>'French Polynesia','TF'=>'French Southern Territories',
    'GA'=>'Gabon','GM'=>'Gambia','GE'=>'Georgia','DE'=>'Germany','GH'=>'Ghana','GI'=>'Gibraltar','GR'=>'Greece','GL'=>'Greenland','GD'=>'Grenada','GP'=>'Guadeloupe','GU'=>'Guam','GT'=>'Guatemala','GG'=>'Guernsey','GN'=>'Guinea','GW'=>'Guinea-Bissau','GY'=>'Guyana',
    'HT'=>'Haiti','HM'=>'Heard Island and McDonald Islands','VA'=>'Vatican City','HN'=>'Honduras','HK'=>'Hong Kong','HU'=>'Hungary',
    'IS'=>'Iceland','IN'=>'India','ID'=>'Indonesia','IR'=>'Iran','IQ'=>'Iraq','IE'=>'Ireland','IM'=>'Isle of Man','IL'=>'Israel','IT'=>'Italy',
    'JM'=>'Jamaica','JP'=>'Japan','JE'=>'Jersey','JO'=>'Jordan',
    'KZ'=>'Kazakhstan','KE'=>'Kenya','KI'=>'Kiribati','KP'=>'North Korea','KR'=>'South Korea','KW'=>'Kuwait','KG'=>'Kyrgyzstan',
    'LA'=>'Laos','LV'=>'Latvia','LB'=>'Lebanon','LS'=>'Lesotho','LR'=>'Liberia','LY'=>'Libya','LI'=>'Liechtenstein','LT'=>'Lithuania','LU'=>'Luxembourg',
    'MO'=>'Macao','MG'=>'Madagascar','MW'=>'Malawi','MY'=>'Malaysia','MV'=>'Maldives','ML'=>'Mali','MT'=>'Malta','MH'=>'Marshall Islands','MQ'=>'Martinique','MR'=>'Mauritania','MU'=>'Mauritius','YT'=>'Mayotte','MX'=>'Mexico','FM'=>'Micronesia','MD'=>'Moldova','MC'=>'Monaco','MN'=>'Mongolia','ME'=>'Montenegro','MS'=>'Montserrat','MA'=>'Morocco','MZ'=>'Mozambique','MM'=>'Myanmar',
    'NA'=>'Namibia','NR'=>'Nauru','NP'=>'Nepal','NL'=>'Netherlands','NC'=>'New Caledonia','NZ'=>'New Zealand','NI'=>'Nicaragua','NE'=>'Niger','NG'=>'Nigeria','NU'=>'Niue','NF'=>'Norfolk Island','MK'=>'North Macedonia','MP'=>'Northern Mariana Islands','NO'=>'Norway',
    'OM'=>'Oman',
    'PK'=>'Pakistan','PW'=>'Palau','PS'=>'Palestine','PA'=>'Panama','PG'=>'Papua New Guinea','PY'=>'Paraguay','PE'=>'Peru','PH'=>'Philippines','PN'=>'Pitcairn Islands','PL'=>'Poland','PT'=>'Portugal','PR'=>'Puerto Rico',
    'QA'=>'Qatar',
    'RE'=>'Réunion','RO'=>'Romania','RU'=>'Russia','RW'=>'Rwanda',
    'BL'=>'Saint Barthélemy','SH'=>'Saint Helena','KN'=>'Saint Kitts and Nevis','LC'=>'Saint Lucia','MF'=>'Saint Martin','PM'=>'Saint Pierre and Miquelon','VC'=>'Saint Vincent and the Grenadines','WS'=>'Samoa','SM'=>'San Marino','ST'=>'São Tomé and Príncipe','SA'=>'Saudi Arabia','SN'=>'Senegal','RS'=>'Serbia','SC'=>'Seychelles','SL'=>'Sierra Leone','SG'=>'Singapore','SX'=>'Sint Maarten','SK'=>'Slovakia','SI'=>'Slovenia','SB'=>'Solomon Islands','SO'=>'Somalia','ZA'=>'South Africa','GS'=>'South Georgia and the South Sandwich Islands','SS'=>'South Sudan','ES'=>'Spain','LK'=>'Sri Lanka','SD'=>'Sudan','SR'=>'Suriname','SJ'=>'Svalbard and Jan Mayen','SE'=>'Sweden','CH'=>'Switzerland','SY'=>'Syria',
    'TW'=>'Taiwan','TJ'=>'Tajikistan','TZ'=>'Tanzania','TH'=>'Thailand','TL'=>'Timor-Leste','TG'=>'Togo','TK'=>'Tokelau','TO'=>'Tonga','TT'=>'Trinidad and Tobago','TN'=>'Tunisia','TR'=>'Turkey','TM'=>'Turkmenistan','TC'=>'Turks and Caicos Islands','TV'=>'Tuvalu',
    'UG'=>'Uganda','UA'=>'Ukraine','AE'=>'United Arab Emirates','GB'=>'United Kingdom','US'=>'United States','UM'=>'U.S. Minor Outlying Islands','UY'=>'Uruguay','UZ'=>'Uzbekistan',
    'VU'=>'Vanuatu','VE'=>'Venezuela','VN'=>'Vietnam','VG'=>'British Virgin Islands','VI'=>'U.S. Virgin Islands',
    'WF'=>'Wallis and Futuna',
    'EH'=>'Western Sahara',
    'YE'=>'Yemen',
    'ZM'=>'Zambia','ZW'=>'Zimbabwe',
];

function country_canonical_en(string $code, array $COUNTRIES): string {
    $code = strtoupper(trim($code));
    return (string)($COUNTRIES[$code] ?? '');
}

/* ===== safe back url ===== */
function admin_users_back_url(): string {
    $default = '/admin/users/';

    // 1) back з GET
    $getBack = admin_norm_local_url((string)($_GET['back'] ?? ''));
    if ($getBack !== '') {
        $path = (string)parse_url($getBack, PHP_URL_PATH);
        if ($path === '/admin/users/' || $path === '/admin/users.php') return $getBack;
    }

    // 2) back з POST
    $postBack = admin_norm_local_url((string)($_POST['back'] ?? ''));
    if ($postBack !== '') {
        $path = (string)parse_url($postBack, PHP_URL_PATH);
        if ($path === '/admin/users/' || $path === '/admin/users.php') return $postBack;
    }

    // 3) referer fallback
    $ref = admin_norm_local_url((string)($_SERVER['HTTP_REFERER'] ?? ''));
    if ($ref !== '') {
        $path = (string)parse_url($ref, PHP_URL_PATH);
        if ($path === '/admin/users/' || $path === '/admin/users.php') return $ref;
    }

    return $default;
}
$backUrl = admin_users_back_url();

function self_url(int $id, string $backUrl): string {
    $u = '/admin/users/edit.php?id=' . $id;
    $b = admin_norm_local_url($backUrl);
    if ($b !== '') $u .= '&back=' . rawurlencode($b);
    return $u;
}

/* ===== upload handler ===== */
if (!function_exists('handle_image_upload_admin')) {
    function handle_image_upload_admin(PDO $pdo, int $userId, string $safeUser, string $type, int $maxBytes, string &$ok, string &$err): void {
        if (!isset($_FILES['file'])) {
            $err = admin_tt('no_file', 'Файл не вибрано.', 'Файл не выбран.', 'No file selected.');
            return;
        }

        $f = $_FILES['file'];

        $upErr = (int)($f['error'] ?? UPLOAD_ERR_NO_FILE);
        if ($upErr !== UPLOAD_ERR_OK) {
            $map = [
                UPLOAD_ERR_INI_SIZE   => admin_tt('up_ini', 'Файл завеликий.', 'Файл слишком большой.', 'File is too large.'),
                UPLOAD_ERR_FORM_SIZE  => admin_tt('up_form', 'Файл завеликий.', 'Файл слишком большой.', 'File is too large.'),
                UPLOAD_ERR_PARTIAL    => admin_tt('up_part', 'Файл завантажено частково.', 'Файл загружен частично.', 'File was partially uploaded.'),
                UPLOAD_ERR_NO_FILE    => admin_tt('up_none', 'Файл не вибрано.', 'Файл не выбран.', 'No file selected.'),
                UPLOAD_ERR_NO_TMP_DIR => admin_tt('up_tmp', 'Немає тимчасової папки.', 'Нет временной папки.', 'Missing temp folder.'),
                UPLOAD_ERR_CANT_WRITE => admin_tt('up_write', 'Не вдалося записати файл.', 'Не удалось записать файл.', 'Failed to write file.'),
                UPLOAD_ERR_EXTENSION  => admin_tt('up_ext', 'Завантаження зупинено розширенням.', 'Загрузка остановлена расширением.', 'Upload stopped by extension.'),
            ];
            $err = $map[$upErr] ?? admin_tt('up_fail', 'Помилка завантаження.', 'Ошибка загрузки.', 'Upload error.');
            return;
        }

        if (!is_uploaded_file($f['tmp_name'] ?? '')) {
            $err = admin_tt('no_tmp', 'Помилка файлу.', 'Ошибка файла.', 'File error.');
            return;
        }

        $size = (int)($f['size'] ?? 0);
        if ($size <= 0) { $err = admin_tt('empty_file', 'Порожній файл.', 'Пустой файл.', 'Empty file.'); return; }
        if ($size > $maxBytes) { $err = admin_tt('too_large', 'Файл завеликий.', 'Файл слишком большой.', 'File is too large.'); return; }

        $tmp = (string)($f['tmp_name'] ?? '');
        $fi = new finfo(FILEINFO_MIME_TYPE);
        $mime = (string)$fi->file($tmp);

        $allowed = [
            'image/jpeg' => 'jpg',
            'image/png'  => 'png',
            'image/webp' => 'webp',
            'image/gif'  => 'gif',
        ];
        if (!isset($allowed[$mime])) {
            $err = admin_tt('bad_type', 'Непідтримуваний тип файлу.', 'Неподдерживаемый тип файла.', 'Unsupported file type.');
            return;
        }

        // Додатково перевіряємо, що це реально зображення
        if (@getimagesize($tmp) === false) {
            $err = admin_tt('bad_img', 'Файл не є коректним зображенням.', 'Файл не является корректным изображением.', 'File is not a valid image.');
            return;
        }

        $ext = $allowed[$mime];

        $baseDir = upload_base_dir();
        $dir = rtrim($baseDir, '/') . '/' . $safeUser . '/' . $type;

        if (!is_dir($dir) && !@mkdir($dir, 0775, true)) {
            $err = admin_tt('dir_fail', 'Не вдалося створити каталог.', 'Не удалось создать каталог.', 'Failed to create directory.');
            return;
        }

        $name = date('Ymd_His') . '_' . bin2hex(random_bytes(6)) . '.' . $ext;
        $destFs = $dir . '/' . $name;

        if (!@move_uploaded_file($tmp, $destFs)) {
            $err = admin_tt('save_fail', 'Не вдалося зберегти файл.', 'Не удалось сохранить файл.', 'Failed to save file.');
            return;
        }
        @chmod($destFs, 0644);

        $destWeb = '/upload/' . $safeUser . '/' . $type . '/' . $name;
        $col = ($type === 'avatar') ? 'avatar_path' : 'cover_path';

        $st = $pdo->prepare("SELECT {$col}, username FROM users WHERE id=? LIMIT 1");
        $st->execute([$userId]);
        $row = $st->fetch(PDO::FETCH_ASSOC) ?: [];
        $old = trim((string)($row[$col] ?? ''));
        $uName = (string)($row['username'] ?? '');
        $curFolder = sanitize_user_folder(safe_user_folder($uName, $userId), $userId);

        $st = $pdo->prepare("UPDATE users SET {$col}=? WHERE id=? LIMIT 1");
        $st->execute([$destWeb, $userId]);

        if ($old !== '') {
            $oldFolder = sanitize_user_folder(extract_upload_folder_from_webpath($old), $userId);
            $allowedFolders = array_values(array_unique(array_filter([$curFolder, $oldFolder, sanitize_user_folder($safeUser, $userId)])));
            delete_web_file_safe($old, $allowedFolders, $type);
        }

        $ok = ($type === 'avatar')
            ? admin_tt('avatar_updated', 'Аватарку оновлено!', 'Аватар обновлён!', 'Avatar updated!')
            : admin_tt('cover_updated', 'Обкладинку оновлено!', 'Обложка обновлена!', 'Cover updated!');
    }
}

/* ===== input ===== */
$id = (int)($_GET['id'] ?? 0);
if ($id <= 0) {
    admin_flash_set('danger', admin_tt('admin_bad_id', 'Невірний ID', 'Неверный ID', 'Bad ID'));
    header('Location: ' . $backUrl);
    exit;
}

/* ===== columns ===== */
$hasEmail       = admin_column_exists($pdo, 'users', 'email');
$hasUsername    = admin_column_exists($pdo, 'users', 'username');
$hasRole        = admin_column_exists($pdo, 'users', 'role');
$hasLang        = admin_column_exists($pdo, 'users', 'lang');

$hasAbout       = admin_column_exists($pdo, 'users', 'about');

$hasCity        = admin_column_exists($pdo, 'users', 'city');

$hasCountry     = admin_column_exists($pdo, 'users', 'country');
$hasCountryCode = admin_column_exists($pdo, 'users', 'country_code');
$hasEducation   = admin_column_exists($pdo, 'users', 'education');
$hasWorkplace   = admin_column_exists($pdo, 'users', 'workplace');
$hasWork        = admin_column_exists($pdo, 'users', 'work'); // fallback

$hasFullName    = admin_column_exists($pdo, 'users', 'full_name');
$hasFirstName   = admin_column_exists($pdo, 'users', 'first_name');
$hasLastName    = admin_column_exists($pdo, 'users', 'last_name');
$hasNameCol     = admin_column_exists($pdo, 'users', 'name'); // legacy

$hasGender      = admin_column_exists($pdo, 'users', 'gender');
$hasBirthdate   = admin_column_exists($pdo, 'users', 'birthdate');
$hasBirthDate   = admin_column_exists($pdo, 'users', 'birth_date');

$birthCol = $hasBirthdate ? 'birthdate' : ($hasBirthDate ? 'birth_date' : '');
$workCol  = $hasWorkplace ? 'workplace' : ($hasWork ? 'work' : '');

$hasAvatar    = admin_column_exists($pdo, 'users', 'avatar_path');
$hasCover     = admin_column_exists($pdo, 'users', 'cover_path');
$hasPass      = admin_column_exists($pdo, 'users', 'pass_hash');
$hasUpdatedAt = admin_column_exists($pdo, 'users', 'updated_at');

/* ===== load user ===== */
$user = null;
try {
    $cols = ['id'];
    if ($hasEmail)     $cols[] = 'email';
    if ($hasUsername)  $cols[] = 'username';
    if ($hasRole)      $cols[] = 'role';
    if ($hasLang)      $cols[] = 'lang';

    if ($hasFullName)  $cols[] = 'full_name';
    if ($hasFirstName) $cols[] = 'first_name';
    if ($hasLastName)  $cols[] = 'last_name';
    if ($hasNameCol)   $cols[] = 'name';

    if ($hasGender)    $cols[] = 'gender';
    if ($birthCol !== '') $cols[] = $birthCol;

    if ($hasCountry)     $cols[] = 'country';
    if ($hasCountryCode) $cols[] = 'country_code';
    if ($hasCity)        $cols[] = 'city';
    if ($hasEducation)   $cols[] = 'education';
    if ($workCol !== '') $cols[] = $workCol;

    if ($hasAbout)  $cols[] = 'about';
    if ($hasAvatar) $cols[] = 'avatar_path';
    if ($hasCover)  $cols[] = 'cover_path';

    if ($hasPass)   $cols[] = 'pass_hash';

    $st = $pdo->prepare("SELECT " . implode(',', array_unique($cols)) . " FROM users WHERE id=? LIMIT 1");
    $st->execute([$id]);
    $user = $st->fetch(PDO::FETCH_ASSOC) ?: null;
} catch (Throwable $e) {
    $user = null;
}

if (!$user) {
    admin_flash_set('danger', admin_tt('admin_not_found', 'Не знайдено', 'Не найдено', 'Not found'));
    header('Location: ' . $backUrl);
    exit;
}

/* ===== state ===== */
$err = '';
$ok  = '';

$username = (string)($user['username'] ?? '');
$safeUser = safe_user_folder($username, $id);

$email = (string)($user['email'] ?? '');
$lang  = (string)($user['lang'] ?? 'uk');
$role  = (string)($user['role'] ?? 'user');

$about = (string)($user['about'] ?? '');
$city  = (string)($user['city'] ?? '');

$country = (string)($user['country'] ?? '');
$countryCode = $hasCountryCode ? strtoupper(trim((string)($user['country_code'] ?? ''))) : '';
if ($countryCode === '' && $country !== '' && preg_match('~^[A-Za-z]{2}$~', trim($country))) {
    $countryCode = strtoupper(trim($country));
}

$education = (string)($user['education'] ?? '');
$workplace = ($workCol !== '' && isset($user[$workCol])) ? (string)$user[$workCol] : '';

$gender = $hasGender ? (string)($user['gender'] ?? '') : '';
$birth  = ($birthCol !== '' && isset($user[$birthCol])) ? (string)$user[$birthCol] : '';

$avatarPath = $hasAvatar ? trim((string)($user['avatar_path'] ?? '')) : '';
$coverPath  = $hasCover  ? trim((string)($user['cover_path']  ?? '')) : '';

$fullNameInput = '';
if ($hasFullName) {
    $fullNameInput = trim((string)($user['full_name'] ?? ''));
} elseif ($hasNameCol) {
    $fullNameInput = trim((string)($user['name'] ?? ''));
} elseif ($hasFirstName || $hasLastName) {
    $fullNameInput = trim((string)($user['first_name'] ?? '') . ' ' . (string)($user['last_name'] ?? ''));
    $fullNameInput = trim(preg_replace('~\s+~u', ' ', $fullNameInput) ?? '');
}

/* ===== POST ===== */
if (($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') {
    if (!admin_csrf_verify()) {
        $err = admin_tt('csrf_bad', 'CSRF помилка', 'CSRF ошибка', 'CSRF error');
    } else {
        $action = (string)($_POST['action'] ?? 'save_user');

        try {
            if ($action === 'save_user') {
                $newEmail = $hasEmail ? mb_strtolower(trim((string)($_POST['email'] ?? ''))) : $email;
                $newUser  = $hasUsername ? trim((string)($_POST['username'] ?? '')) : $username;

                $newRole  = $hasRole ? trim((string)($_POST['role'] ?? 'user')) : $role;
                $newLang  = $hasLang ? trim((string)($_POST['lang'] ?? 'uk')) : $lang;

                $newFull  = trim((string)($_POST['full_name'] ?? ''));
                $newFull  = trim(preg_replace('~\s+~u', ' ', $newFull) ?? '');

                $newGender = $hasGender ? trim((string)($_POST['gender'] ?? '')) : $gender;
                $newBirth  = ($birthCol !== '') ? trim((string)($_POST['birthdate'] ?? '')) : $birth;

                $newAbout  = $hasAbout ? trim((string)($_POST['about'] ?? '')) : $about;
                $newCity   = $hasCity ? trim((string)($_POST['city'] ?? '')) : $city;

                $newCountryCode = strtoupper(trim((string)($_POST['country_code'] ?? '')));
                if ($newCountryCode !== '' && !preg_match('~^[A-Z]{2}$~', $newCountryCode)) $newCountryCode = '';
                $newCountryCanonical = ($newCountryCode !== '' ? country_canonical_en($newCountryCode, $COUNTRIES) : '');

                $newEducation = $hasEducation ? trim((string)($_POST['education'] ?? '')) : $education;
                $newWorkplace = ($workCol !== '') ? trim((string)($_POST['workplace'] ?? '')) : $workplace;

                $p1 = $hasPass ? (string)($_POST['new_password'] ?? '') : '';
                $p2 = $hasPass ? (string)($_POST['new_password2'] ?? '') : '';

                $allowedLang = ['uk','ru','en'];
                $allowedRoles = ['user','moderator','admin'];
                if ($role !== '' && !in_array($role, $allowedRoles, true)) $allowedRoles[] = $role;

                /* validations */
                if ($hasEmail && ($newEmail === '' || !filter_var($newEmail, FILTER_VALIDATE_EMAIL))) {
                    $err = admin_tt('bad_email', 'Невірний email.', 'Неверный email.', 'Invalid email.');
                } elseif ($hasUsername && ($newUser === '' || !preg_match('~^[a-zA-Z0-9_\-]{3,32}$~', $newUser))) {
                    $err = admin_tt('bad_username', 'Невірний нікнейм (3-32 символи: латиниця/цифри/_/-).', 'Неверный никнейм (3-32 символа: латиница/цифры/_/-).', 'Invalid username (3-32: latin/digits/_/-).');
                } elseif (($hasFullName || $hasNameCol || $hasFirstName || $hasLastName) && $newFull === '') {
                    $err = admin_tt('bad_fullname', 'ПІБ обовʼязкове.', 'ФИО обязательно.', 'Full name is required.');
                } elseif ($hasGender && !in_array($newGender, ['f','m'], true)) {
                    $err = admin_tt('bad_gender', 'Оберіть стать.', 'Выберите пол.', 'Choose gender.');
                } elseif ($birthCol !== '' && ($newBirth === '' || !is_valid_date_ymd($newBirth))) {
                    $err = admin_tt('bad_birth', 'Невірна дата народження.', 'Неверная дата рождения.', 'Invalid birth date.');
                } elseif ($newCountryCode !== '' && !isset($COUNTRIES[$newCountryCode])) {
                    $err = admin_tt('bad_country', 'Оберіть країну зі списку.', 'Выберите страну из списка.', 'Select a country from the list.');
                } elseif ($hasLang && !in_array($newLang, $allowedLang, true)) {
                    $err = admin_tt('bad_lang', 'Невірна мова.', 'Неверный язык.', 'Invalid language.');
                } elseif ($hasRole && !in_array($newRole, $allowedRoles, true)) {
                    $err = admin_tt('bad_role', 'Невірна роль.', 'Неверная роль.', 'Invalid role.');
                } elseif ($hasPass && ($p1 !== '' || $p2 !== '')) {
                    if (mb_strlen($p1) < 6) {
                        $err = admin_tt('bad_pass_len', 'Новий пароль закороткий (мін. 6).', 'Новый пароль слишком короткий (мин. 6).', 'New password is too short (min 6).');
                    } elseif ($p1 !== $p2) {
                        $err = admin_tt('bad_pass_match', 'Паролі не співпадають.', 'Пароли не совпадают.', 'Passwords do not match.');
                    }
                }

                /* uniqueness checks */
                if ($err === '' && $hasEmail && mb_strtolower($email) !== $newEmail) {
                    $st = $pdo->prepare("SELECT id FROM users WHERE email=? AND id<>? LIMIT 1");
                    $st->execute([$newEmail, $id]);
                    if ($st->fetchColumn()) {
                        $err = admin_tt('email_taken', 'Цей email вже зайнятий.', 'Этот email уже занят.', 'Email is already taken.');
                    }
                }
                if ($err === '' && $hasUsername && $username !== $newUser) {
                    $st = $pdo->prepare("SELECT id FROM users WHERE username=? AND id<>? LIMIT 1");
                    $st->execute([$newUser, $id]);
                    if ($st->fetchColumn()) {
                        $err = admin_tt('user_taken', 'Цей нікнейм вже зайнятий.', 'Этот никнейм уже занят.', 'Username is already taken.');
                    }
                }

                if ($err === '') {
                    $oldUsername = $username;
                    $oldSafe = sanitize_user_folder(safe_user_folder($oldUsername, $id), $id);
                    $newSafe = sanitize_user_folder(safe_user_folder($newUser, $id), $id);

                    $newAvatarPath = $avatarPath;
                    $newCoverPath  = $coverPath;

                    $moved = false;
                    $moveSrc = '';
                    $moveDst = '';

                    // Переносимо папку /upload/<oldSafe>/ -> /upload/<newSafe>/ (якщо реально міняється)
                    if ($hasUsername && $oldUsername !== $newUser && $oldSafe !== $newSafe) {
                        $base = upload_base_dir();
                        $src = rtrim($base, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $oldSafe;
                        $dst = rtrim($base, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $newSafe;

                        if (is_dir($src)) {
                            if (is_dir($dst)) {
                                $err = admin_tt(
                                    'dst_exists',
                                    'Папка нового username вже існує в upload. Перевір колізію.',
                                    'Папка нового username уже существует в upload. Проверь коллизию.',
                                    'Target upload folder already exists. Check collision.'
                                );
                            } else {
                                if (!path_is_inside($src, $base) || !path_is_inside(dirname($dst), $base)) {
                                    $err = admin_tt('path_bad', 'Небезпечний шлях.', 'Небезопасный путь.', 'Unsafe path.');
                                } else {
                                    $movedOk = move_dir_recursive($src, $dst);
                                    if (!$movedOk) {
                                        $err = admin_tt(
                                            'move_fail',
                                            'Не вдалося перенести папку upload користувача. Перевір права доступу.',
                                            'Не удалось перенести папку upload пользователя. Проверь права доступа.',
                                            'Failed to move user upload folder. Check permissions.'
                                        );
                                    } else {
                                        $moved = true;
                                        $moveSrc = $src;
                                        $moveDst = $dst;
                                    }
                                }
                            }
                        }
                    }

                    if ($err === '') {
                        // Підміняємо префікс у шляхах avatar/cover (таких, що починаються з /upload/<oldSafe>/)
                        if ($oldSafe !== $newSafe) {
                            $oldPrefix = '/upload/' . $oldSafe . '/';
                            $newPrefix = '/upload/' . $newSafe . '/';

                            if ($newAvatarPath !== '' && starts_with($newAvatarPath, $oldPrefix)) {
                                $newAvatarPath = $newPrefix . substr($newAvatarPath, strlen($oldPrefix));
                            }
                            if ($newCoverPath !== '' && starts_with($newCoverPath, $oldPrefix)) {
                                $newCoverPath = $newPrefix . substr($newCoverPath, strlen($oldPrefix));
                            }
                        }

                        // DB update
                        $pdo->beginTransaction();

                        $sets = [];
                        $params = [];

                        if ($hasEmail)    { $sets[] = 'email=?';    $params[] = $newEmail; }
                        if ($hasUsername) { $sets[] = 'username=?'; $params[] = $newUser; }
                        if ($hasRole)     { $sets[] = 'role=?';     $params[] = $newRole; }
                        if ($hasLang)     { $sets[] = 'lang=?';     $params[] = $newLang; }

                        if ($hasAbout) { $sets[] = 'about=?'; $params[] = ($newAbout !== '' ? $newAbout : null); }
                        if ($hasCity)  { $sets[] = 'city=?';  $params[] = ($newCity !== '' ? $newCity : null); }

                        // country sync
                        if ($hasCountryCode) {
                            $sets[] = 'country_code=?';
                            $params[] = ($newCountryCode !== '' ? $newCountryCode : null);
                        }
                        if ($hasCountry) {
                            $sets[] = 'country=?';
                            $params[] = ($newCountryCanonical !== '' ? $newCountryCanonical : null);
                        }

                        if ($hasEducation) { $sets[] = 'education=?'; $params[] = ($newEducation !== '' ? $newEducation : null); }
                        if ($workCol !== '') { $sets[] = $workCol . '=?'; $params[] = ($newWorkplace !== '' ? $newWorkplace : null); }

                        if ($hasGender) { $sets[] = 'gender=?'; $params[] = ($newGender !== '' ? $newGender : null); }
                        if ($birthCol !== '') { $sets[] = $birthCol . '=?'; $params[] = ($newBirth !== '' ? $newBirth : null); }

                        if ($hasFullName) { $sets[] = 'full_name=?'; $params[] = ($newFull !== '' ? $newFull : null); }
                        if ($hasNameCol)  { $sets[] = 'name=?';      $params[] = ($newFull !== '' ? $newFull : null); }

                        if (($hasFirstName || $hasLastName) && !$hasFullName) {
                            $parts = preg_split('~\s+~u', $newFull, -1, PREG_SPLIT_NO_EMPTY) ?: [];
                            $first = '';
                            $last  = '';
                            if ($parts) { $first = (string)array_shift($parts); $last = trim(implode(' ', $parts)); }
                            if ($hasFirstName) { $sets[] = 'first_name=?'; $params[] = ($first !== '' ? $first : null); }
                            if ($hasLastName)  { $sets[] = 'last_name=?';  $params[] = ($last  !== '' ? $last  : null); }
                        }

                        if ($hasAvatar) { $sets[] = 'avatar_path=?'; $params[] = ($newAvatarPath !== '' ? $newAvatarPath : null); }
                        if ($hasCover)  { $sets[] = 'cover_path=?';  $params[] = ($newCoverPath  !== '' ? $newCoverPath  : null); }

                        if ($hasPass && $p1 !== '' && $p1 === $p2) {
                            $sets[] = 'pass_hash=?';
                            $params[] = password_hash($p1, PASSWORD_DEFAULT);
                        }

                        if ($hasUpdatedAt) {
                            $sets[] = 'updated_at=NOW()';
                        }

                        if (!$sets) {
                            $pdo->rollBack();
                            $err = admin_tt('nothing', 'Немає полів для збереження', 'Нет полей для сохранения', 'No fields to save');
                        } else {
                            $params[] = $id;
                            $sql = "UPDATE users SET " . implode(', ', $sets) . " WHERE id=? LIMIT 1";
                            $st = $pdo->prepare($sql);
                            $st->execute($params);

                            // best-effort update typical attachment path columns if folder changed
                            if ($oldSafe !== $newSafe) {
                                $oldPrefix = '/upload/' . $oldSafe . '/';
                                $newPrefix = '/upload/' . $newSafe . '/';

                                $tables = [
                                    'post_attachments' => ['path','file_path','url','src','thumb_path','thumb_url'],
                                    'comment_attachments' => ['path','file_path','url','src','thumb_path','thumb_url'],
                                ];

                                foreach ($tables as $t => $colsUpd) {
                                    if (!admin_table_exists($pdo, $t)) continue;
                                    foreach ($colsUpd as $c) {
                                        if (!admin_column_exists($pdo, $t, $c)) continue;
                                        $q = "UPDATE `$t`
                                              SET `$c` = CONCAT(?, SUBSTRING(`$c`, ?))
                                              WHERE `$c` LIKE ?";
                                        // CONCAT(newPrefix, SUBSTRING(col, len(oldPrefix)+1))
                                        $pdo->prepare($q)->execute([$newPrefix, strlen($oldPrefix) + 1, $oldPrefix . '%']);
                                    }
                                }
                            }

                            $pdo->commit();

                            admin_flash_set('success', admin_tt('saved', 'Збережено', 'Сохранено', 'Saved'));
                            header('Location: ' . self_url($id, $backUrl));
                            exit;
                        }
                    }

                    // якщо DB впав після переносу — пробуємо повернути папку назад (best-effort)
                    if ($err !== '' && $moved && $moveSrc !== '' && $moveDst !== '' && is_dir($moveDst) && !is_dir($moveSrc)) {
                        @rename($moveDst, $moveSrc);
                    }
                }
            }
            elseif ($action === 'upload_avatar') {
                if (!$hasAvatar) {
                    $err = admin_tt('no_avatar_col', 'У БД немає поля avatar_path.', 'В БД нет поля avatar_path.', 'DB column avatar_path is missing.');
                } else {
                    handle_image_upload_admin($pdo, $id, sanitize_user_folder($safeUser, $id), 'avatar', 10 * 1024 * 1024, $ok, $err);
                    if ($err === '' && $ok !== '') {
                        admin_flash_set('success', $ok);
                        header('Location: ' . self_url($id, $backUrl));
                        exit;
                    }
                }
            }
            elseif ($action === 'upload_cover') {
                if (!$hasCover) {
                    $err = admin_tt('no_cover_col', 'У БД немає поля cover_path.', 'В БД нет поля cover_path.', 'DB column cover_path is missing.');
                } else {
                    handle_image_upload_admin($pdo, $id, sanitize_user_folder($safeUser, $id), 'cover', 12 * 1024 * 1024, $ok, $err);
                    if ($err === '' && $ok !== '') {
                        admin_flash_set('success', $ok);
                        header('Location: ' . self_url($id, $backUrl));
                        exit;
                    }
                }
            }
            elseif ($action === 'delete_avatar') {
                if ($hasAvatar) {
                    $st = $pdo->prepare("SELECT avatar_path, username FROM users WHERE id=? LIMIT 1");
                    $st->execute([$id]);
                    $row = $st->fetch(PDO::FETCH_ASSOC) ?: [];
                    $old = trim((string)($row['avatar_path'] ?? ''));
                    $uName = (string)($row['username'] ?? '');

                    $su = sanitize_user_folder(safe_user_folder($uName, $id), $id);
                    $oldFolder = sanitize_user_folder(extract_upload_folder_from_webpath($old), $id);
                    $allowedFolders = array_values(array_unique(array_filter([$su, $oldFolder])));

                    if ($old !== '') delete_web_file_safe($old, $allowedFolders, 'avatar');

                    $st = $pdo->prepare("UPDATE users SET avatar_path=NULL WHERE id=? LIMIT 1");
                    $st->execute([$id]);

                    admin_flash_set('success', admin_tt('avatar_deleted', 'Аватарку видалено.', 'Аватар удалён.', 'Avatar removed.'));
                    header('Location: ' . self_url($id, $backUrl));
                    exit;
                }
            }
            elseif ($action === 'delete_cover') {
                if ($hasCover) {
                    $st = $pdo->prepare("SELECT cover_path, username FROM users WHERE id=? LIMIT 1");
                    $st->execute([$id]);
                    $row = $st->fetch(PDO::FETCH_ASSOC) ?: [];
                    $old = trim((string)($row['cover_path'] ?? ''));
                    $uName = (string)($row['username'] ?? '');

                    $su = sanitize_user_folder(safe_user_folder($uName, $id), $id);
                    $oldFolder = sanitize_user_folder(extract_upload_folder_from_webpath($old), $id);
                    $allowedFolders = array_values(array_unique(array_filter([$su, $oldFolder])));

                    if ($old !== '') delete_web_file_safe($old, $allowedFolders, 'cover');

                    $st = $pdo->prepare("UPDATE users SET cover_path=NULL WHERE id=? LIMIT 1");
                    $st->execute([$id]);

                    admin_flash_set('success', admin_tt('cover_deleted', 'Обкладинку видалено.', 'Обложка удалена.', 'Cover removed.'));
                    header('Location: ' . self_url($id, $backUrl));
                    exit;
                }
            }
            else {
                $err = admin_tt('unknown_action', 'Невідома дія.', 'Неизвестное действие.', 'Unknown action.');
            }

            /* refresh user (щоб форма показувала актуальне) */
            $st = $pdo->prepare("SELECT * FROM users WHERE id=? LIMIT 1");
            $st->execute([$id]);
            $user = $st->fetch(PDO::FETCH_ASSOC) ?: $user;

            $username = (string)($user['username'] ?? $username);
            $safeUser = safe_user_folder($username, $id);

            $email = (string)($user['email'] ?? $email);
            $lang  = (string)($user['lang'] ?? $lang);
            $role  = (string)($user['role'] ?? $role);

            $about = (string)($user['about'] ?? $about);
            $city  = (string)($user['city'] ?? $city);

            $country = (string)($user['country'] ?? $country);
            $countryCode = $hasCountryCode ? strtoupper(trim((string)($user['country_code'] ?? $countryCode))) : $countryCode;

            $education = (string)($user['education'] ?? $education);
            $workplace = ($workCol !== '' && isset($user[$workCol])) ? (string)$user[$workCol] : $workplace;

            $gender = $hasGender ? (string)($user['gender'] ?? $gender) : $gender;
            $birth  = ($birthCol !== '' && isset($user[$birthCol])) ? (string)($user[$birthCol] ?? $birth) : $birth;

            $avatarPath = $hasAvatar ? trim((string)($user['avatar_path'] ?? $avatarPath)) : '';
            $coverPath  = $hasCover  ? trim((string)($user['cover_path']  ?? $coverPath))  : '';

            if ($hasFullName) {
                $fullNameInput = trim((string)($user['full_name'] ?? $fullNameInput));
            } elseif ($hasNameCol) {
                $fullNameInput = trim((string)($user['name'] ?? $fullNameInput));
            } elseif ($hasFirstName || $hasLastName) {
                $fullNameInput = trim((string)($user['first_name'] ?? '') . ' ' . (string)($user['last_name'] ?? ''));
                $fullNameInput = trim(preg_replace('~\s+~u', ' ', $fullNameInput) ?? '');
            }
        } catch (Throwable $e) {
            $err = admin_tt('save_error', 'Помилка. Перевір дані.', 'Ошибка. Проверь данные.', 'Error. Please check data.');
        }
    }
}

require __DIR__ . '/../../includes/header.php';
?>

<div class="row g-3">
  <div class="col-lg-9">

    <div class="d-flex align-items-center justify-content-between mb-2">
      <div>
        <h1 class="h4 mb-0"><?= h($title) ?></h1>
        <div class="text-muted small">
          ID: <?= (int)$id ?>
          <?php if ($hasUsername && $username !== ''): ?>
            · <a href="/profile/?u=<?= h(rawurlencode($username)) ?>" target="_blank" rel="noopener">/profile/?u=<?= h($username) ?></a>
          <?php endif; ?>
        </div>
      </div>
      <a class="btn btn-sm btn-outline-secondary" href="<?= h($backUrl) ?>"><?= h(admin_tt('back', 'Назад', 'Назад', 'Back')) ?></a>
    </div>

    <?php if ($ok !== ''): ?>
      <div class="alert alert-success"><?= h($ok) ?></div>
    <?php endif; ?>
    <?php if ($err !== ''): ?>
      <div class="alert alert-danger"><?= h($err) ?></div>
    <?php endif; ?>

    <?php if ($hasAvatar): ?>
    <!-- AVATAR -->
    <div class="card card-app p-3 mb-3">
      <div class="fw-semibold mb-2"><?= h(admin_tt('avatar', 'Аватарка', 'Аватар', 'Avatar')) ?></div>

      <div class="d-flex align-items-center gap-3 flex-wrap">
        <div style="width:96px;height:96px;border-radius:18px;overflow:hidden;background:#f1f3f5;border:1px solid rgba(0,0,0,.08);display:flex;align-items:center;justify-content:center;">
          <?php if ($avatarPath !== ''): ?>
            <img src="<?= h($avatarPath) ?>" alt="" style="width:100%;height:100%;object-fit:cover;">
          <?php else: ?>
            <div style="font-size:28px;opacity:.55;">👤</div>
          <?php endif; ?>
        </div>

        <div class="flex-grow-1" style="min-width:260px;">
          <form method="post" enctype="multipart/form-data" class="d-flex gap-2 align-items-end flex-wrap">
            <?= admin_csrf_field() ?>
            <input type="hidden" name="action" value="upload_avatar">
            <input type="hidden" name="back" value="<?= h($backUrl) ?>">
            <div class="flex-grow-1" style="min-width:240px;">
              <label class="form-label mb-1"><?= h(admin_tt('upload_avatar', 'Завантажити нову аватарку (до 10MB)', 'Загрузить новый аватар (до 10MB)', 'Upload new avatar (up to 10MB)')) ?></label>
              <input class="form-control" type="file" name="file" accept="image/*" required>
            </div>
            <button class="btn btn-primary" type="submit"><?= h(admin_tt('upload', 'Завантажити', 'Загрузить', 'Upload')) ?></button>
          </form>

          <?php if ($avatarPath !== ''): ?>
            <form method="post" class="mt-2" onsubmit="return confirm('<?= h(admin_tt('confirm_del_avatar', 'Видалити аватарку?', 'Удалить аватар?', 'Delete avatar?')) ?>');">
              <?= admin_csrf_field() ?>
              <input type="hidden" name="action" value="delete_avatar">
              <input type="hidden" name="back" value="<?= h($backUrl) ?>">
              <button class="btn btn-outline-danger btn-sm" type="submit"><?= h(admin_tt('del_avatar', 'Видалити аватарку', 'Удалить аватар', 'Delete avatar')) ?></button>
            </form>
          <?php endif; ?>
        </div>
      </div>
    </div>
    <?php endif; ?>

    <?php if ($hasCover): ?>
    <!-- COVER -->
    <div class="card card-app p-3 mb-3">
      <div class="fw-semibold mb-2"><?= h(admin_tt('cover', 'Обкладинка', 'Обложка', 'Cover')) ?></div>

      <div style="border-radius:16px;overflow:hidden;background:#f1f3f5;border:1px solid rgba(0,0,0,.08);">
        <?php if ($coverPath !== ''): ?>
          <img src="<?= h($coverPath) ?>" alt="" style="width:100%;height:220px;object-fit:cover;display:block;">
        <?php else: ?>
          <div style="height:220px;display:flex;align-items:center;justify-content:center;opacity:.55;">
            <div style="font-size:28px;">🖼️</div>
          </div>
        <?php endif; ?>
      </div>

      <form method="post" enctype="multipart/form-data" class="mt-3 d-flex gap-2 align-items-end flex-wrap">
        <?= admin_csrf_field() ?>
        <input type="hidden" name="action" value="upload_cover">
        <input type="hidden" name="back" value="<?= h($backUrl) ?>">
        <div class="flex-grow-1" style="min-width:240px;">
          <label class="form-label mb-1"><?= h(admin_tt('upload_cover', 'Завантажити нову обкладинку (до 12MB)', 'Загрузить новую обложку (до 12MB)', 'Upload new cover (up to 12MB)')) ?></label>
          <input class="form-control" type="file" name="file" accept="image/*" required>
        </div>
        <button class="btn btn-primary" type="submit"><?= h(admin_tt('upload', 'Завантажити', 'Загрузить', 'Upload')) ?></button>
      </form>

      <?php if ($coverPath !== ''): ?>
        <form method="post" class="mt-2" onsubmit="return confirm('<?= h(admin_tt('confirm_del_cover', 'Видалити обкладинку?', 'Удалить обложку?', 'Delete cover?')) ?>');">
          <?= admin_csrf_field() ?>
          <input type="hidden" name="action" value="delete_cover">
          <input type="hidden" name="back" value="<?= h($backUrl) ?>">
          <button class="btn btn-outline-danger btn-sm" type="submit"><?= h(admin_tt('del_cover', 'Видалити обкладинку', 'Удалить обложку', 'Delete cover')) ?></button>
        </form>
      <?php endif; ?>
    </div>
    <?php endif; ?>

    <!-- PROFILE INFO -->
    <div class="card card-app p-3 mb-3">
      <div class="fw-semibold mb-2"><?= h(admin_tt('profile_info', 'Дані профілю', 'Данные профиля', 'Profile info')) ?></div>

      <form method="post" autocomplete="off">
        <?= admin_csrf_field() ?>
        <input type="hidden" name="action" value="save_user">
        <input type="hidden" name="back" value="<?= h($backUrl) ?>">

        <?php if ($hasEmail): ?>
        <div class="mb-3">
          <label class="form-label fw-bold">Email</label>
          <input class="form-control" type="email" name="email" value="<?= h($email) ?>" required>
        </div>
        <?php endif; ?>

        <?php if ($hasUsername): ?>
        <div class="mb-3">
          <label class="form-label fw-bold"><?= h(admin_tt('username', 'Нікнейм', 'Никнейм', 'Username')) ?></label>
          <input class="form-control" name="username" value="<?= h($username) ?>" maxlength="32" required>
          <div class="form-text"><?= h(admin_tt('u_hint', '3–32 символи: латиниця/цифри/_/-', '3–32 символа: латиница/цифры/_/-', '3–32 chars: latin/digits/_/-')) ?></div>
        </div>
        <?php endif; ?>

        <?php if ($hasFullName || $hasNameCol || $hasFirstName || $hasLastName): ?>
        <div class="mb-3">
          <label class="form-label fw-bold"><?= h(admin_tt('full_name', 'ПІБ', 'ФИО', 'Full name')) ?></label>
          <input class="form-control" name="full_name" value="<?= h($fullNameInput) ?>" maxlength="190" required>
        </div>
        <?php endif; ?>

        <?php if ($hasGender): ?>
        <div class="mb-3">
          <label class="form-label fw-bold"><?= h(admin_tt('gender', 'Стать', 'Пол', 'Gender')) ?></label>
          <select class="form-select" name="gender" required>
            <option value=""><?= h(admin_tt('select', 'Оберіть', 'Выберите', 'Select')) ?></option>
            <option value="f" <?= $gender === 'f' ? 'selected' : '' ?>><?= h(admin_tt('female', 'Жіноча', 'Женский', 'Female')) ?></option>
            <option value="m" <?= $gender === 'm' ? 'selected' : '' ?>><?= h(admin_tt('male', 'Чоловіча', 'Мужской', 'Male')) ?></option>
          </select>
        </div>
        <?php endif; ?>

        <?php if ($birthCol !== ''): ?>
        <div class="mb-3">
          <label class="form-label fw-bold"><?= h(admin_tt('birthdate', 'Дата народження', 'Дата рождения', 'Birth date')) ?></label>
          <input class="form-control" type="date" name="birthdate" value="<?= h($birth) ?>" required>
        </div>
        <?php endif; ?>

        <?php if ($hasCountryCode || $hasCountry): ?>
        <div class="mb-3">
          <label class="form-label fw-bold"><?= h(admin_tt('country', 'Країна', 'Страна', 'Country')) ?></label>

          <select class="form-select" name="country_code">
            <option value=""><?= h(admin_tt('country_none', 'Не вказувати', 'Не указывать', 'Not specified')) ?></option>
            <?php foreach ($COUNTRIES as $cc => $nameEn): ?>
              <?php $cc = strtoupper((string)$cc); ?>
              <option value="<?= h($cc) ?>" <?= ($cc === $countryCode ? 'selected' : '') ?>>
                <?= h($nameEn) ?> (<?= h($cc) ?>)
              </option>
            <?php endforeach; ?>
          </select>

          <div class="form-text">
            <?= h(admin_tt(
              'country_hint',
              'Країна зберігається уніфіковано (ISO-код). Якщо є country_code — пишемо туди, і синхронізуємо country англійською.',
              'Страна сохраняется унифицировано (ISO-код). Если есть country_code — пишем туда и синхронизируем country на английском.',
              'Country is saved as ISO code. If country_code exists, we store it there and sync country in English.'
            )) ?>
          </div>
        </div>
        <?php endif; ?>

        <?php if ($hasCity): ?>
        <div class="mb-3">
          <label class="form-label fw-bold"><?= h(admin_tt('city', 'Місто', 'Город', 'City')) ?></label>
          <input class="form-control" name="city" value="<?= h($city) ?>" maxlength="120">
        </div>
        <?php endif; ?>

        <?php if ($hasEducation): ?>
        <div class="mb-3">
          <label class="form-label fw-bold"><?= h(admin_tt('education', 'Освіта', 'Образование', 'Education')) ?></label>
          <input class="form-control" name="education" value="<?= h($education) ?>" maxlength="255">
        </div>
        <?php endif; ?>

        <?php if ($workCol !== ''): ?>
        <div class="mb-3">
          <label class="form-label fw-bold"><?= h(admin_tt('workplace', 'Місце роботи', 'Место работы', 'Workplace')) ?></label>
          <input class="form-control" name="workplace" value="<?= h($workplace) ?>" maxlength="255">
        </div>
        <?php endif; ?>

        <?php if ($hasAbout): ?>
        <div class="mb-3">
          <label class="form-label fw-bold"><?= h(admin_tt('about', 'Про себе', 'О себе', 'About')) ?></label>
          <textarea class="form-control" name="about" rows="5" style="resize:vertical;"><?= h($about) ?></textarea>
        </div>
        <?php endif; ?>

        <?php if ($hasLang): ?>
        <div class="mb-3">
          <label class="form-label fw-bold"><?= h(admin_tt('language', 'Мова', 'Язык', 'Language')) ?></label>
          <select class="form-select" name="lang">
            <option value="uk" <?= $lang==='uk'?'selected':'' ?>>Українська</option>
            <option value="ru" <?= $lang==='ru'?'selected':'' ?>>Русский</option>
            <option value="en" <?= $lang==='en'?'selected':'' ?>>English</option>
          </select>
        </div>
        <?php endif; ?>

        <?php if ($hasRole): ?>
        <div class="mb-3">
          <label class="form-label fw-bold"><?= h(admin_tt('role', 'Роль', 'Роль', 'Role')) ?></label>
          <select class="form-select" name="role">
            <?php
              $cur = (string)$role;
              $roles = ['user','moderator','admin'];
              if ($cur !== '' && !in_array($cur, $roles, true)) $roles[] = $cur;
              foreach ($roles as $r) {
                $sel = ($cur === $r) ? 'selected' : '';
                echo '<option value="'.h($r).'" '.$sel.'>'.h($r).'</option>';
              }
            ?>
          </select>
        </div>
        <?php endif; ?>

        <?php if ($hasPass): ?>
          <hr class="my-3">
          <div class="fw-semibold mb-2"><?= h(admin_tt('change_pass', 'Зміна паролю', 'Смена пароля', 'Change password')) ?></div>

          <div class="mb-3">
            <label class="form-label"><?= h(admin_tt('new_pass', 'Новий пароль', 'Новый пароль', 'New password')) ?></label>
            <input class="form-control" type="password" name="new_password" autocomplete="new-password">
            <div class="form-text"><?= h(admin_tt('pass_hint', 'Якщо залишити порожнім — пароль не зміниться.', 'Если оставить пустым — пароль не изменится.', 'Leave empty to keep current password.')) ?></div>
          </div>

          <div class="mb-3">
            <label class="form-label"><?= h(admin_tt('new_pass2', 'Повторіть новий пароль', 'Повторите новый пароль', 'Repeat new password')) ?></label>
            <input class="form-control" type="password" name="new_password2" autocomplete="new-password">
          </div>
        <?php endif; ?>

        <button class="btn btn-primary"><?= h(admin_tt('save', 'Зберегти', 'Сохранить', 'Save')) ?></button>
      </form>
    </div>

  </div>

  <div class="col-lg-3">
    <?php admin_sidebar('users'); ?>
  </div>
</div>

<?php require __DIR__ . '/../../includes/footer.php'; ?>