<?php
declare(strict_types=1);

require_once __DIR__ . '/user_auth_lib.php';
require_once __DIR__ . '/ip.php';
require_once __DIR__ . '/telegram_lib.php';

const MOCKER_TELEGRAM_REGISTER_BONUS_COINS = 150;

function mocker_telegram_auth_pending_cleanup(PDO $pdo): void
{
    $cutoff = time() - 3600;
    $pdo->prepare('DELETE FROM telegram_auth_pending WHERE expires_at < :t')->execute([':t' => $cutoff]);
}

function mocker_telegram_auth_fetch_user_by_tg(PDO $pdo, int $tgUid): ?array
{
    if ($tgUid <= 0) {
        return null;
    }
    $st = $pdo->prepare(
        'SELECT id, username, email, coins, profile_completed_at FROM users WHERE telegram_user_id = :tid LIMIT 1'
    );
    $st->execute([':tid' => $tgUid]);
    $row = $st->fetch(PDO::FETCH_ASSOC);

    return $row ?: null;
}

/**
 * @return array{row: array, is_new: bool}
 */
function mocker_telegram_auth_upsert_from_telegram(
    PDO $pdo,
    int $tgUid,
    ?string $tgUsername,
    ?string $firstName
): array {
    $tgUsername = $tgUsername !== null ? trim($tgUsername) : '';
    $firstName = $firstName !== null ? trim($firstName) : '';
    if ($tgUsername === '' && $firstName !== '') {
        $tgUsername = $firstName;
    }

    $row = mocker_telegram_auth_fetch_user_by_tg($pdo, $tgUid);
    $isNew = false;
    $now = time();
    $clientIp = mocker_client_ip();

    if (!$row) {
        $username = mocker_generate_username_from_telegram(
            $pdo,
            $tgUsername !== '' ? $tgUsername : null,
            $tgUid,
            $firstName !== '' ? $firstName : null
        );
        $email = mocker_telegram_pending_email($tgUid);
        $passwordHash = password_hash(bin2hex(random_bytes(24)), PASSWORD_DEFAULT);
        $ins = $pdo->prepare(
            'INSERT INTO users (
                username, email, password_hash, coins, created_at, last_login_at, last_seen_at,
                register_ip, last_login_ip, telegram_user_id, telegram_username, telegram_verified_at
             ) VALUES (
                :u, :e, :p, :c, :t, :t, :t2, :rip, :lip, :tid, :tu, :tv
             )'
        );
        $ins->execute([
            ':u' => $username,
            ':e' => $email,
            ':p' => $passwordHash,
            ':c' => MOCKER_TELEGRAM_REGISTER_BONUS_COINS,
            ':t' => $now,
            ':t2' => $now,
            ':rip' => $clientIp !== '' ? $clientIp : null,
            ':lip' => $clientIp !== '' ? $clientIp : null,
            ':tid' => $tgUid,
            ':tu' => $tgUsername !== '' ? $tgUsername : null,
            ':tv' => $now,
        ]);
        $isNew = true;
        $row = mocker_telegram_auth_fetch_user_by_tg($pdo, $tgUid);
        if (!$row) {
            throw new RuntimeException('user_create_failed');
        }
    } else {
        $uid = (int) $row['id'];
        $upd = $pdo->prepare(
            'UPDATE users SET
                last_login_at = :t,
                last_seen_at = :t2,
                last_login_ip = :lip,
                telegram_username = COALESCE(:tu, telegram_username),
                telegram_verified_at = COALESCE(telegram_verified_at, :tv)
             WHERE id = :id'
        );
        $upd->execute([
            ':t' => $now,
            ':t2' => $now,
            ':lip' => $clientIp !== '' ? $clientIp : null,
            ':tu' => $tgUsername !== '' ? $tgUsername : null,
            ':tv' => $now,
            ':id' => $uid,
        ]);
        $row = mocker_telegram_auth_fetch_user_by_tg($pdo, $tgUid);
        if (!$row) {
            throw new RuntimeException('user_update_failed');
        }
    }

    return ['row' => $row, 'is_new' => $isNew];
}

function mocker_telegram_auth_json_success(PDO $pdo, array $row, bool $isNew): void
{
    $userPayload = mocker_user_auth_payload($pdo, $row);
    echo json_encode(
        [
            'ok' => true,
            'pending' => false,
            'isNew' => $isNew,
            'needsProfileCompletion' => !empty($userPayload['needsProfileCompletion']),
            'user' => array_merge($userPayload, [
                'bonus' => $isNew ? MOCKER_TELEGRAM_REGISTER_BONUS_COINS : 0,
            ]),
            'csrfToken' => mocker_csrf_token(),
        ],
        JSON_UNESCAPED_UNICODE
    );
}

/**
 * Bot /start ile site giriş/kayıt doğrulaması.
 */
function mocker_telegram_auth_handle_bot_start(
    PDO $pdo,
    string $token,
    int $tgUid,
    array $from,
    int $chatId
): bool {
    $hash = mocker_telegram_hash_token($token);
    $now = time();

    $st = $pdo->prepare(
        'SELECT mode, expires_at, completed_user_id, poll_key_hash
         FROM telegram_auth_pending WHERE token_hash = :h LIMIT 1'
    );
    $st->execute([':h' => $hash]);
    $pending = $st->fetch(PDO::FETCH_ASSOC);
    if (!$pending) {
        return false;
    }

    if ((int) ($pending['completed_user_id'] ?? 0) > 0) {
        if ($chatId > 0) {
            mocker_telegram_send_message($chatId, 'Bu doğrulama bağlantısı zaten kullanıldı. Siteden yeni bağlantı al.');
        }

        return true;
    }

    if ((int) ($pending['expires_at'] ?? 0) <= $now) {
        $pdo->prepare('DELETE FROM telegram_auth_pending WHERE token_hash = :h')->execute([':h' => $hash]);
        if ($chatId > 0) {
            mocker_telegram_send_message($chatId, 'Doğrulama kodunun süresi doldu. Siteden tekrar dene.');
        }

        return true;
    }

    if ($tgUid <= 0) {
        return true;
    }

    $tgUsername = isset($from['username']) ? trim((string) $from['username']) : '';
    $firstName = isset($from['first_name']) ? trim((string) $from['first_name']) : '';
    if ($tgUsername === '' && $firstName !== '') {
        $tgUsername = $firstName;
    }

    $mode = (string) ($pending['mode'] ?? 'login');
    $existing = mocker_telegram_auth_fetch_user_by_tg($pdo, $tgUid);

    if ($mode === 'register' && $existing) {
        if ($chatId > 0) {
            mocker_telegram_send_message(
                $chatId,
                'Bu Telegram hesabı zaten kayıtlı. Giriş yap sekmesinden «Telegram ile giriş yap» kullanabilirsin.'
            );
        }

        return true;
    }

    if ($mode === 'login' && !$existing) {
        if ($chatId > 0) {
            mocker_telegram_send_message(
                $chatId,
                'Bu Telegram hesabıyla kayıt bulunamadı. Sitede «Kayıt ol» → «Telegram ile kayıt ol» ile hesap oluştur.'
            );
        }

        return true;
    }

    try {
        $pdo->beginTransaction();
        $result = mocker_telegram_auth_upsert_from_telegram($pdo, $tgUid, $tgUsername, $firstName);
        $row = $result['row'];
        $uid = (int) $row['id'];

        $upd = $pdo->prepare(
            'UPDATE telegram_auth_pending SET
                completed_user_id = :uid,
                telegram_user_id = :tid,
                completed_at = :t,
                completed_is_new = :new
             WHERE token_hash = :h AND completed_user_id IS NULL'
        );
        $upd->execute([
            ':uid' => $uid,
            ':tid' => $tgUid,
            ':t' => $now,
            ':new' => $result['is_new'] ? 1 : 0,
            ':h' => $hash,
        ]);
        if ($upd->rowCount() < 1) {
            $pdo->rollBack();
            if ($chatId > 0) {
                mocker_telegram_send_message($chatId, 'Doğrulama zaten tamamlanmış. Siteye dönüp sayfayı yenile.');
            }

            return true;
        }
        $pdo->commit();
    } catch (Throwable $e) {
        if ($pdo->inTransaction()) {
            $pdo->rollBack();
        }
        if ($chatId > 0) {
            mocker_telegram_send_message($chatId, 'Bir hata oluştu. Lütfen siteden tekrar dene.');
        }

        return true;
    }

    if ($chatId > 0) {
        $line = $tgUsername !== '' ? ('@' . ltrim($tgUsername, '@')) : 'Hesabın';
        $verb = $mode === 'register' ? 'Kayıt' : 'Giriş';
        mocker_telegram_send_message(
            $chatId,
            "{$verb} doğrulandı ({$line}). Mocker sitesine dön; oturumun birkaç saniye içinde açılır."
        );
    }

    return true;
}
