<?php
declare(strict_types=1);

/**
 * /admin/users/delete.php
 * Адмін: видалення користувача + чистка залежностей (best-effort, якщо таблиці/колонки існують).
 *
 * ОНОВЛЕНО:
 * - back URL береться з POST(back) (як у /admin/users/ (або legacy /admin/users.php)), з безпечною валідацією
 * - папка в /upload визначається надійніше: з avatar_path/cover_path або username
 * - безпечні перевірки шляху перед видаленням файлів/папок (щоб не вийти за /upload)
 * - якщо користувача не знайдено — показуємо flash і повертаємось назад
 *
 * Додано:
 * - SEO: X-Robots-Tag noindex (адмінка)
 */

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

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

$pdo = db();

/* =========================
   SEO: адмінка НЕ індексується
========================= */
if (!headers_sent()) {
    header('X-Robots-Tag: noindex, nofollow, noarchive, nosnippet', true);
}

/* =========================
   Safe helpers
========================= */
if (!function_exists('admin_norm_local_url')) {
    function admin_norm_local_url(string $raw): string {
        $raw = trim($raw);
        if ($raw === '') return '';

        // Якщо абсолютний URL — лишаємо тільки path+query
        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;
    }
}

if (!function_exists('admin_users_back_url')) {
    function admin_users_back_url(): string {
        $default = '/admin/users/';

        // 1) 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;
        }

        // 2) 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();

/* ===== upload path helpers ===== */
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('extract_upload_folder_from_webpath')) {
    function extract_upload_folder_from_webpath(string $webPath): string {
        $webPath = trim($webPath);
        if ($webPath === '') return '';

        // якщо прийшло як URL — беремо path
        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 '';

        // /upload/<folder>/...
        $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('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 {
        // /admin/.. => корінь
        return __DIR__ . '/../..' . $webPath;
    }
}

if (!function_exists('delete_web_file_safe')) {
    /**
     * Видаляємо файл ТІЛЬКИ якщо він фізично всередині /upload/<one of allowed folders>/
     */
    function delete_web_file_safe(string $webPath, array $allowedFolders): void {
        $webPath = trim($webPath);
        if ($webPath === '') return;

        // якщо URL — беремо path
        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;

        $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('rm_dir_recursive')) {
    function rm_dir_recursive(string $dir, string $baseDir): void {
        if (!is_dir($dir)) return;
        if (!path_is_inside($dir, $baseDir)) return;

        $it = new RecursiveIteratorIterator(
            new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS),
            RecursiveIteratorIterator::CHILD_FIRST
        );

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

/* =========================
   Request validation
========================= */
if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
    http_response_code(405);
    exit('Method Not Allowed');
}

if (!admin_csrf_verify()) {
    admin_flash_set('danger', admin_tt('csrf_bad', 'CSRF помилка', 'CSRF ошибка', 'CSRF error'));
    header('Location: ' . $backUrl);
    exit;
}

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

/* =========================
   Preload user info (for cleanup)
========================= */
$username   = '';
$avatarPath = '';
$coverPath  = '';

try {
    $cols = ['id'];
    if (admin_column_exists($pdo, 'users', 'username')) $cols[] = 'username';
    if (admin_column_exists($pdo, 'users', 'avatar_path')) $cols[] = 'avatar_path';
    if (admin_column_exists($pdo, 'users', 'cover_path'))  $cols[] = 'cover_path';

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

    if ($u) {
        $username   = (string)($u['username'] ?? '');
        $avatarPath = (string)($u['avatar_path'] ?? '');
        $coverPath  = (string)($u['cover_path'] ?? '');
    } else {
        admin_flash_set('danger', admin_tt('user_not_found', 'Користувача не знайдено', 'Пользователь не найден', 'User not found'));
        header('Location: ' . $backUrl);
        exit;
    }
} catch (Throwable $e) {
    admin_flash_set('danger', admin_tt('admin_error', 'Помилка', 'Ошибка', 'Error'));
    header('Location: ' . $backUrl);
    exit;
}

/* =========================
   Decide upload folders to delete
========================= */
$folderFromAvatar = extract_upload_folder_from_webpath($avatarPath);
$folderFromCover  = extract_upload_folder_from_webpath($coverPath);

$candidates = [];
if ($folderFromAvatar !== '') $candidates[] = $folderFromAvatar;
if ($folderFromCover !== '')  $candidates[] = $folderFromCover;
if ($username !== '')         $candidates[] = $username;

// додатково — sanitized варіанти
foreach ($candidates as $c) {
    $candidates[] = sanitize_user_folder($c, $id);
}

$candidates[] = 'user_' . $id;

$candidates = array_values(array_unique(array_filter(array_map('trim', $candidates), fn($v) => $v !== '')));

$uploadBase = upload_base_dir();
$dirsToDelete = [];

foreach ($candidates as $folder) {
    $folder = sanitize_user_folder($folder, $id); // гарантуємо безпечне ім'я
    $dir = rtrim($uploadBase, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $folder;
    if (is_dir($dir) && path_is_inside($dir, $uploadBase)) {
        $dirsToDelete[] = $dir;
    }
}

/* =========================
   Delete DB + dependencies (transaction)
========================= */
try {
    $pdo->beginTransaction();

    /* ===== extra common tables (if exist) ===== */

    // friends / friend_requests
    foreach (['friends', 'friend_requests'] as $t) {
        if (admin_table_exists($pdo, $t)) {
            foreach (['user_id','friend_id','from_user_id','to_user_id'] as $col) {
                if (admin_column_exists($pdo, $t, $col)) {
                    $pdo->prepare("DELETE FROM `$t` WHERE `$col`=?")->execute([$id]);
                }
            }
        }
    }

    // subscriptions/follows
    foreach (['subscriptions','follows','user_follows'] as $t) {
        if (admin_table_exists($pdo, $t)) {
            foreach (['user_id','target_user_id'] as $col) {
                if (admin_column_exists($pdo, $t, $col)) {
                    $pdo->prepare("DELETE FROM `$t` WHERE `$col`=?")->execute([$id]);
                }
            }
        }
    }

    // messages (dialogs)
    foreach (['messages','private_messages'] as $t) {
        if (admin_table_exists($pdo, $t)) {
            foreach (['from_user_id','to_user_id','user_id'] as $col) {
                if (admin_column_exists($pdo, $t, $col)) {
                    $pdo->prepare("DELETE FROM `$t` WHERE `$col`=?")->execute([$id]);
                }
            }
        }
    }

    // notifications
    foreach (['notifications','user_notifications'] as $t) {
        if (admin_table_exists($pdo, $t) && admin_column_exists($pdo, $t, 'user_id')) {
            $pdo->prepare("DELETE FROM `$t` WHERE user_id=?")->execute([$id]);
        }
    }

    // reactions/likes
    foreach (['post_reactions','reactions','likes','post_likes'] as $t) {
        if (admin_table_exists($pdo, $t) && admin_column_exists($pdo, $t, 'user_id')) {
            $pdo->prepare("DELETE FROM `$t` WHERE user_id=?")->execute([$id]);
        }
    }

    // polls votes
    foreach (['post_poll_votes','poll_votes'] as $t) {
        if (admin_table_exists($pdo, $t) && admin_column_exists($pdo, $t, 'user_id')) {
            $pdo->prepare("DELETE FROM `$t` WHERE user_id=?")->execute([$id]);
        }
    }

    // traffic
    if (admin_table_exists($pdo, 'traffic_hits') && admin_column_exists($pdo, 'traffic_hits', 'user_id')) {
        $pdo->prepare("DELETE FROM traffic_hits WHERE user_id=?")->execute([$id]);
    }

    // sessions
    foreach (['sessions','user_sessions'] as $t) {
        if (admin_table_exists($pdo, $t) && admin_column_exists($pdo, $t, 'user_id')) {
            $pdo->prepare("DELETE FROM `$t` WHERE user_id=?")->execute([$id]);
        }
    }

    // security login log (часто існує)
    foreach (['security_login_log','login_log','auth_log'] as $t) {
        if (admin_table_exists($pdo, $t) && admin_column_exists($pdo, $t, 'user_id')) {
            $pdo->prepare("DELETE FROM `$t` WHERE user_id=?")->execute([$id]);
        }
    }

    /* ===== your existing cleanup ===== */

    // group_members
    if (admin_table_exists($pdo, 'group_members') && admin_column_exists($pdo, 'group_members', 'user_id')) {
        $pdo->prepare("DELETE FROM group_members WHERE user_id=?")->execute([$id]);
    }

    // comments by user
    if (admin_table_exists($pdo, 'comments') && admin_column_exists($pdo, 'comments', 'user_id')) {
        // comment_attachments
        if (admin_table_exists($pdo, 'comment_attachments') && admin_column_exists($pdo, 'comment_attachments', 'comment_id')) {
            $pdo->prepare("
                DELETE ca FROM comment_attachments ca
                JOIN comments c ON c.id = ca.comment_id
                WHERE c.user_id = ?
            ")->execute([$id]);
        }

        // comment reactions (якщо є)
        foreach (['comment_reactions','comment_likes'] as $t) {
            if (admin_table_exists($pdo, $t) && admin_column_exists($pdo, $t, 'comment_id')) {
                $pdo->prepare("
                    DELETE cr FROM `$t` cr
                    JOIN comments c ON c.id = cr.comment_id
                    WHERE c.user_id = ?
                ")->execute([$id]);
            }
        }

        $pdo->prepare("DELETE FROM comments WHERE user_id=?")->execute([$id]);
    }

    // posts by user
    if (admin_table_exists($pdo, 'posts') && admin_column_exists($pdo, 'posts', 'user_id')) {
        // post_attachments
        if (admin_table_exists($pdo, 'post_attachments') && admin_column_exists($pdo, 'post_attachments', 'post_id')) {
            $pdo->prepare("
                DELETE pa FROM post_attachments pa
                JOIN posts p ON p.id = pa.post_id
                WHERE p.user_id = ?
            ")->execute([$id]);
        }

        // comments under those posts
        if (admin_table_exists($pdo, 'comments') && admin_column_exists($pdo, 'comments', 'post_id')) {
            if (admin_table_exists($pdo, 'comment_attachments') && admin_column_exists($pdo, 'comment_attachments', 'comment_id')) {
                $pdo->prepare("
                    DELETE ca FROM comment_attachments ca
                    JOIN comments c ON c.id = ca.comment_id
                    JOIN posts p ON p.id = c.post_id
                    WHERE p.user_id = ?
                ")->execute([$id]);
            }

            // comment reactions under those posts (якщо є)
            foreach (['comment_reactions','comment_likes'] as $t) {
                if (admin_table_exists($pdo, $t) && admin_column_exists($pdo, $t, 'comment_id')) {
                    $pdo->prepare("
                        DELETE cr FROM `$t` cr
                        JOIN comments c ON c.id = cr.comment_id
                        JOIN posts p ON p.id = c.post_id
                        WHERE p.user_id = ?
                    ")->execute([$id]);
                }
            }

            $pdo->prepare("
                DELETE c FROM comments c
                JOIN posts p ON p.id = c.post_id
                WHERE p.user_id = ?
            ")->execute([$id]);
        }

        $pdo->prepare("DELETE FROM posts WHERE user_id=?")->execute([$id]);
    }

    // groups owned by user: НЕ видаляю автоматом

    // finally delete user
    $st = $pdo->prepare("DELETE FROM users WHERE id=? LIMIT 1");
    $st->execute([$id]);

    $pdo->commit();

    /* =========================
       File cleanup AFTER commit
    ========================= */
    $allowedFolders = [];
    foreach ($candidates as $cand) {
        $allowedFolders[] = sanitize_user_folder($cand, $id);
    }
    $allowedFolders = array_values(array_unique(array_filter($allowedFolders)));

    if ($avatarPath !== '') delete_web_file_safe($avatarPath, $allowedFolders);
    if ($coverPath !== '')  delete_web_file_safe($coverPath, $allowedFolders);

    if ($dirsToDelete) {
        foreach (array_unique($dirsToDelete) as $dir) {
            rm_dir_recursive($dir, $uploadBase);
        }
    }

    admin_flash_set('success', admin_tt('admin_deleted', 'Видалено', 'Удалено', 'Deleted'));
} catch (Throwable $e) {
    if ($pdo->inTransaction()) $pdo->rollBack();
    admin_flash_set('danger', admin_tt('admin_delete_error', 'Помилка видалення', 'Ошибка удаления', 'Delete error'));
}

header('Location: ' . $backUrl);
exit;