<?php

declare(strict_types=1);

use SergiX44\Nutgram\Nutgram;

// مدیریت خطاها
error_reporting(E_ALL);
ini_set('display_errors', '0');
ini_set('log_errors', '1');
// مسیر لاگ داخل پوشه bot (نه پوشه اصلی)
$logFile = __DIR__ . '/../bot.log';
ini_set('error_log', $logFile);

// رفع warning مربوط به session.gc_divisor
// توجه: این warning از php.ini سرور می‌آید و در Startup رخ می‌دهد
// بنابراین نمی‌توان آن را در کد رفع کرد، اما می‌توانیم suppress کنیم
if (ini_get('session.gc_divisor') <= 0) {
    ini_set('session.gc_divisor', '100');
}

// Suppress کردن warning های PHP Startup (که قبل از اجرای کد رخ می‌دهند)
// این warning ها معمولاً از تنظیمات سرور می‌آیند و روی عملکرد تأثیری ندارند
$errorHandler = set_error_handler(function($errno, $errstr, $errfile, $errline) {
    // نادیده گرفتن warning های PHP Startup مربوط به session.gc_divisor
    if ($errno === E_WARNING && str_contains($errstr, 'session.gc_divisor')) {
        return true; // Suppress کردن warning
    }
    // برای سایر خطاها، handler پیش‌فرض را فراخوانی می‌کنیم
    return false;
}, E_WARNING);

// تابع برای لاگ کردن خطاها (قبل از بارگذاری LogService)
function logError(string $message, ?Throwable $e = null): void
{
    // مسیر لاگ داخل پوشه bot (نه پوشه اصلی) - برای fallback
    $logFile = __DIR__ . '/../bot.log';
    $timestamp = date('Y-m-d H:i:s');
    $errorMsg = "[{$timestamp}] {$message}";
    if ($e !== null) {
        $errorMsg .= "\n" . $e->getMessage() . "\n" . $e->getTraceAsString();
    }
    $errorMsg .= "\n";
    @file_put_contents($logFile, $errorMsg, FILE_APPEND);
    @error_log($message);
    
    // اگر LogService موجود باشد، از آن هم استفاده می‌کنیم
    if (isset($GLOBALS['logService']) && $GLOBALS['logService'] instanceof \Bot\Domain\Service\LogService) {
        try {
            $GLOBALS['logService']->error($message, [], exception: $e);
        } catch (\Throwable) {
            // اگر خطا در لاگ رخ داد، نادیده می‌گیریم
        }
    }
}

// Wrapper برای error_log که از LogService استفاده می‌کند
if (!function_exists('error_log_wrapper')) {
    function error_log_wrapper(string $message, int $messageType = 0, ?string $destination = null, ?string $extraHeaders = null): bool
    {
        // استفاده از LogService اگر موجود باشد
        if (isset($GLOBALS['logService']) && $GLOBALS['logService'] instanceof \Bot\Domain\Service\LogService) {
            try {
                // تشخیص سطح لاگ از روی محتوای پیام
                $level = 'INFO';
                if (stripos($message, 'error') !== false || stripos($message, 'خطا') !== false) {
                    $level = 'ERROR';
                } elseif (stripos($message, 'warning') !== false || stripos($message, 'هشدار') !== false) {
                    $level = 'WARNING';
                } elseif (stripos($message, 'debug') !== false) {
                    $level = 'DEBUG';
                }
                
                $GLOBALS['logService']->log($level, $message);
            } catch (\Throwable) {
                // اگر خطا در لاگ رخ داد، به error_log اصلی می‌نویسیم
            }
        }
        
        // همیشه به error_log اصلی هم می‌نویسیم
        return @error_log($message, $messageType, $destination, $extraHeaders);
    }
}

// بارگذاری تنظیمات
try {
    require __DIR__ . '/partials/config.php';
} catch (Throwable $e) {
    logError('خطا در بارگذاری config: ' . $e->getMessage(), $e);
    exit(1);
}

// بارگذاری سرویس‌ها
try {
    require __DIR__ . '/partials/services.php';
} catch (Throwable $e) {
    logError('خطا در بارگذاری services: ' . $e->getMessage(), $e);
    exit(1);
}

// بارگذاری توابع helper و منوها
try {
    require_once __DIR__ . '/partials/helpers.php';
    require_once __DIR__ . '/partials/menus.php';
    require_once __DIR__ . '/partials/dbrelations.php';
} catch (Throwable $e) {
    logError('خطا در بارگذاری helpers/menus/dbrelations: ' . $e->getMessage(), $e);
    exit(1);
}

// ایجاد instance ربات
try {
    $bot = new Nutgram($botToken);
    
    // تنظیم RunningMode به صورت صریح برای جلوگیری از خطای resolve
    // Nutgram به صورت پیش‌فرض Polling را تنظیم می‌کند، اما برای اطمینان
    // می‌توانیم آن را به صورت صریح تنظیم کنیم
    // توجه: این کار اختیاری است و Nutgram به صورت خودکار Polling را تنظیم می‌کند
} catch (Throwable $e) {
    logError('خطا در ایجاد instance ربات: ' . $e->getMessage(), $e);
    exit(1);
}

// ثبت هندلرها
try {
    require __DIR__ . '/partials/handlers/start.php';
    registerStartHandler(
        $bot,
        $userService,
        $forcedJoinService,
        $analyticsService,
        $linkStore,
        $mediaService,
        $adminService,
        $downloadCounter,
        $freeDownloadLimit,
        $forcedJoinChannel,
        $ownerTelegramId,
        $logService,
        $forcedJoinChannelService,
    );

    require __DIR__ . '/partials/handlers/callback-query.php';
    registerCallbackQueryHandler(
        $bot,
        $userService,
        $adminService,
        $mediaService,
        $analyticsService,
        $paymentService,
        $adsService,
        $ownerTelegramId,
        $nextpayApiKey,
        $zarinpalMerchantId,
        $zarinpalSandbox,
        $paymentCallbackBaseUrl,
        $userStates,
        $linkStore,
        $logService,
        $forcedJoinChannelService,
    );

    require __DIR__ . '/partials/handlers/message-input.php';
    registerMessageInputHandler(
        $bot,
        $userService,
        $adminService,
        $mediaService,
        $adsService,
        $ownerTelegramId,
        $userStates,
        $forcedJoinChannelService,
    );

    require __DIR__ . '/partials/handlers/media-upload.php';
    registerMediaUploadHandler(
        $bot,
        $adminService,
        $mediaService,
        $linkStore,
        $ownerTelegramId,
        $userStates,
        $logService,
    );

    require __DIR__ . '/partials/handlers/payment.php';
    registerPaymentHandlers(
        $bot,
        $userService,
        $paymentService,
        $analyticsService,
        $nextpayApiKey,
        $zarinpalMerchantId,
        $zarinpalSandbox,
        $paymentCallbackBaseUrl,
        $adminService,
        $ownerTelegramId,
    );

    require __DIR__ . '/partials/handlers/commands.php';
    registerCommandHandlers(
        $bot,
        $userService,
        $adminService,
        $mediaService,
        $analyticsService,
        $adsService,
        $ownerTelegramId,
        $logService,
    );
} catch (Throwable $e) {
    logError('خطا در ثبت هندلرها: ' . $e->getMessage(), $e);
    exit(1);
}

// حذف flag restart در صورت وجود (اگر restart قبلاً انجام شده باشد)
$restartFlag = __DIR__ . '/../../.restart_in_progress';
if (file_exists($restartFlag)) {
    // بررسی اینکه آیا restart قدیمی است (بیش از 30 ثانیه)
    $restartTime = filemtime($restartFlag);
    if (time() - $restartTime > 30) {
        // اگر restart قدیمی است، flag را حذف کن
        unlink($restartFlag);
    }
}

// بررسی وجود instance های دیگر قبل از شروع
// مسیر PID file داخل پوشه bot (نه پوشه اصلی)
$pidFile = __DIR__ . '/../bot.pid';
$currentPid = getmypid();

// اگر PID file وجود دارد، بررسی کنیم که آیا process دیگری در حال اجراست
if (file_exists($pidFile)) {
    $filePid = (int) trim(file_get_contents($pidFile));
    if ($filePid !== $currentPid && $filePid > 0) {
        // بررسی اینکه آیا process با این PID واقعاً در حال اجراست
        if (function_exists('posix_kill')) {
            if (@posix_kill($filePid, 0)) {
                // Process دیگری در حال اجراست
                logError("⚠️  Another bot instance is running (PID: $filePid). Current PID: $currentPid");
                logError("⚠️  Exiting to avoid conflict. Please stop the other instance first.");
                exit(1);
            }
        }
    }
}

// ذخیره PID فعلی
file_put_contents($pidFile, $currentPid);

// اجرای ربات
try {
    logError('ربات در حال شروع است...');
    $bot->run();
} catch (Throwable $e) {
    $errorMessage = $e->getMessage();
    
    // بررسی خطای conflict
    if (stripos($errorMessage, 'conflict') !== false || 
        stripos($errorMessage, 'terminated by other getUpdates') !== false) {
        logError('⚠️  Conflict detected: Another bot instance is running getUpdates');
        logError('⚠️  Please stop all other instances and restart.');
        // حذف PID file چون این instance نمی‌تواند اجرا شود
        if (file_exists($pidFile)) {
            unlink($pidFile);
        }
    } else {
        logError('خطا در اجرای ربات: ' . $errorMessage, $e);
    }
    exit(1);
}
