<?php
declare(strict_types=1);

/**
 * Состояние фонового обслуживания хранится отдельно от каталога логов,
 * чтобы отметка не удалялась во время очередной очистки.
 */
function maintenance_dir(): string
{
    return DATA_DIR . '/maintenance';
}

function log_cleanup_state_path(): string
{
    return maintenance_dir() . '/log-cleanup.json';
}

function log_cleanup_lock_path(): string
{
    return maintenance_dir() . '/log-cleanup.lock';
}

/**
 * Полностью очищает локальные журналы сайта, не затрагивая заявки,
 * настройки, контент, загрузки и резервные копии.
 */
function clear_all_site_logs(): array
{
    $result = [
        'deleted_files' => 0,
        'truncated_files' => 0,
        'activity_cleared' => false,
        'security_registry_cleared' => false,
    ];

    // Пользовательские журналы, Telegram-ошибки и rate-limit файлы.
    ensure_dir(LOGS_DIR);
    $iterator = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator(LOGS_DIR, FilesystemIterator::SKIP_DOTS),
        RecursiveIteratorIterator::CHILD_FIRST
    );
    foreach ($iterator as $item) {
        $path = $item->getPathname();
        if ($item->isFile() || $item->isLink()) {
            if (in_array($item->getFilename(), ['.gitkeep', '.htaccess'], true)) {
                continue;
            }
            if (@unlink($path)) {
                $result['deleted_files']++;
            }
        } elseif ($item->isDir()) {
            @rmdir($path);
        }
    }

    // Оставляем каталог в архиве и после развёртывания.
    $gitkeep = LOGS_DIR . '/.gitkeep';
    if (!is_file($gitkeep)) {
        @file_put_contents($gitkeep, '');
    }

    // PHP error_log может создаваться в разных разделах сайта.
    $rootIterator = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator(ROOT_DIR, FilesystemIterator::SKIP_DOTS)
    );
    foreach ($rootIterator as $item) {
        if (!$item->isFile() || $item->getFilename() !== 'error_log') {
            continue;
        }
        $path = $item->getPathname();
        if (@file_put_contents($path, '', LOCK_EX) !== false) {
            $result['truncated_files']++;
        }
    }

    // История посещений и подробные действия по сессиям — тоже журналы.
    if (function_exists('clear_activity_logs')) {
        clear_activity_logs();
        $result['activity_cleared'] = true;
    } else {
        write_json_file(DATA_DIR . '/activity.json', ['sessions' => [], 'actions' => []]);
        $sessionDir = DATA_DIR . '/crm/session-actions';
        if (is_dir($sessionDir)) {
            foreach (glob($sessionDir . '/*.json') ?: [] as $file) {
                if (@unlink($file)) {
                    $result['deleted_files']++;
                }
            }
        }
        $result['activity_cleared'] = true;
    }


    // Временный реестр попыток и дублей не содержит заявок и может очищаться вместе с журналами.
    $securityDir = DATA_DIR . '/security';
    ensure_dir($securityDir);
    $securityLock = @fopen($securityDir . '/booking-submissions.lock', 'c+');
    if (is_resource($securityLock)) {
        try {
            if (@flock($securityLock, LOCK_EX)) {
                $emptySecurity = [
                    'attempts' => [],
                    'successes' => [],
                    'fingerprints' => [],
                    'tokens' => [],
                ];
                if (write_json_file($securityDir . '/booking-submissions.json', $emptySecurity)) {
                    $result['security_registry_cleared'] = true;
                }
            }
        } finally {
            @flock($securityLock, LOCK_UN);
            @fclose($securityLock);
        }
    }

    return $result;
}

/**
 * Запускает очистку максимум один раз за 24 часа.
 * Ошибки обслуживания не должны мешать открытию сайта.
 */
function run_site_log_cleanup_now(): array
{
    $now = time();
    $result = clear_all_site_logs();
    ensure_dir(maintenance_dir());
    write_json_file(log_cleanup_state_path(), [
        'last_run' => $now,
        'last_run_at' => date('c', $now),
        'interval_seconds' => 86400,
        'result' => $result,
    ]);
    return $result;
}

function maybe_run_daily_log_cleanup(): void
{
    try {
        $activityConfig = function_exists('activity_settings') ? activity_settings() : ['auto_cleanup' => true];
        if (empty($activityConfig['auto_cleanup'])) {
            return;
        }

        ensure_dir(maintenance_dir());
        $now = time();
        $state = read_json_file(log_cleanup_state_path(), []);
        $lastRun = max(0, (int)($state['last_run'] ?? 0));
        if ($lastRun > 0 && ($now - $lastRun) < 86400) {
            return;
        }

        $lock = @fopen(log_cleanup_lock_path(), 'c+');
        if ($lock === false) {
            return;
        }

        try {
            if (!@flock($lock, LOCK_EX | LOCK_NB)) {
                return;
            }

            // Повторная проверка после получения блокировки.
            $state = read_json_file(log_cleanup_state_path(), []);
            $lastRun = max(0, (int)($state['last_run'] ?? 0));
            if ($lastRun > 0 && ($now - $lastRun) < 86400) {
                return;
            }

            run_site_log_cleanup_now();
        } finally {
            @flock($lock, LOCK_UN);
            @fclose($lock);
        }
    } catch (Throwable $ignored) {
        // Автообслуживание не должно ломать публичную часть сайта.
    }
}
