<?php
require_once __DIR__ . '/../includes/config.php';
require_once __DIR__ . '/../includes/jwt.php';

header('Content-Type: application/json');

function jsonResponse(int $code, array $data): void
{
    http_response_code($code);
    echo json_encode($data);
    exit;
}

function formatAmount(float $amount): string
{
    return number_format($amount, 2, '.', '');
}

function insertWalletTransaction(
    PDO $pdo,
    string $txnRef,
    int $userId,
    string $walletType,
    string $entrySide,
    float $amount,
    string $transactionType,
    string $status,
    string $relatedType,
    int $relatedId,
    string $description,
    float $balanceBefore,
    float $balanceAfter
): void {
    $stmt = $pdo->prepare("
        INSERT INTO wallet_transactions
        (
            txn_ref,
            user_id,
            wallet_type,
            entry_side,
            amount,
            transaction_type,
            status,
            related_type,
            related_id,
            description,
            balance_before,
            balance_after
        )
        VALUES
        (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    ");
    $stmt->execute([
        $txnRef,
        $userId,
        $walletType,
        $entrySide,
        $amount,
        $transactionType,
        $status,
        $relatedType,
        $relatedId,
        $description,
        $balanceBefore,
        $balanceAfter
    ]);
}

function getTodayDate(PDO $pdo): string
{
    $stmt = $pdo->query("SELECT CURDATE() AS today");
    $row = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$row || empty($row['today'])) {
        throw new Exception('Failed to get server date');
    }

    return (string)$row['today'];
}

function getRewardDayRow(PDO $pdo, int $streakDay): array
{
    $stmt = $pdo->query("
        SELECT MAX(day_number) AS max_day
        FROM daily_login_reward_days
        WHERE is_active = 1
    ");
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
    $maxDay = (int)($row['max_day'] ?? 0);

    if ($maxDay <= 0) {
        throw new Exception('No active daily login rewards configured');
    }

    $rewardDayNumber = min($streakDay, $maxDay);

    $stmt = $pdo->prepare("
        SELECT
            id,
            day_number,
            title,
            cash_amount,
            dragon_coins,
            wallet_type,
            is_active
        FROM daily_login_reward_days
        WHERE is_active = 1
          AND day_number = ?
        LIMIT 1
    ");
    $stmt->execute([$rewardDayNumber]);
    $reward = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$reward) {
        throw new Exception('Daily login reward day not found');
    }

    return $reward;
}

try {
    $userId = verifyToken();

    if (!$userId) {
        jsonResponse(401, [
            'success' => false,
            'message' => 'Unauthorized'
        ]);
    }

    $pdo->beginTransaction();

    $today = getTodayDate($pdo);
    $yesterday = (new DateTimeImmutable($today))
        ->modify('-1 day')
        ->format('Y-m-d');

    $stmt = $pdo->prepare("
        SELECT
            id,
            play_balance,
            withdrawable_balance,
            dragon_coins
        FROM users
        WHERE id = ?
        LIMIT 1
        FOR UPDATE
    ");
    $stmt->execute([$userId]);
    $user = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$user) {
        throw new Exception('User not found');
    }

    $stmt = $pdo->prepare("
        SELECT
            id,
            last_claim_date,
            streak_day,
            total_claims
        FROM user_daily_login_state
        WHERE user_id = ?
        LIMIT 1
        FOR UPDATE
    ");
    $stmt->execute([$userId]);
    $state = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$state) {
        $stmt = $pdo->prepare("
            INSERT INTO user_daily_login_state
            (
                user_id,
                last_claim_date,
                streak_day,
                total_claims
            )
            VALUES
            (?, NULL, 0, 0)
        ");
        $stmt->execute([$userId]);

        $stmt = $pdo->prepare("
            SELECT
                id,
                last_claim_date,
                streak_day,
                total_claims
            FROM user_daily_login_state
            WHERE user_id = ?
            LIMIT 1
            FOR UPDATE
        ");
        $stmt->execute([$userId]);
        $state = $stmt->fetch(PDO::FETCH_ASSOC);
    }

    if (!$state) {
        throw new Exception('Failed to initialize daily login state');
    }

    $lastClaimDate = !empty($state['last_claim_date']) ? (string)$state['last_claim_date'] : null;
    $currentStreakDay = (int)($state['streak_day'] ?? 0);
    $totalClaims = (int)($state['total_claims'] ?? 0);

    if ($lastClaimDate === $today) {
        $pdo->commit();

        jsonResponse(200, [
            'success' => true,
            'already_claimed' => true,
            'streak_day' => $currentStreakDay,
            'message' => 'Daily login reward already claimed today'
        ]);
    }

    $newStreakDay = ($lastClaimDate === $yesterday) ? ($currentStreakDay + 1) : 1;

    $reward = getRewardDayRow($pdo, $newStreakDay);

    $rewardDayNumber = (int)$reward['day_number'];
    $rewardTitle = trim((string)($reward['title'] ?? ('Day ' . $rewardDayNumber . ' Reward')));
    $cashAmount = round((float)($reward['cash_amount'] ?? 0), 2);
    $dragonCoins = (int)($reward['dragon_coins'] ?? 0);
    $walletType = trim((string)($reward['wallet_type'] ?? 'play_balance'));

    if (!in_array($walletType, ['play_balance', 'withdrawable_balance'], true)) {
        throw new Exception('Invalid reward wallet type');
    }

    $stmt = $pdo->prepare("
        INSERT INTO daily_login_claims
        (
            user_id,
            claim_date,
            streak_day,
            reward_day_number,
            cash_amount,
            dragon_coins,
            wallet_type
        )
        VALUES
        (?, ?, ?, ?, ?, ?, ?)
    ");
    $stmt->execute([
        $userId,
        $today,
        $newStreakDay,
        $rewardDayNumber,
        $cashAmount,
        $dragonCoins,
        $walletType
    ]);

    $claimId = (int)$pdo->lastInsertId();
    $txnRefBase = 'DL' . $userId . str_replace('-', '', $today);

    if ($cashAmount > 0) {
        if ($walletType === 'withdrawable_balance') {
            $before = round((float)$user['withdrawable_balance'], 2);
            $after = round($before + $cashAmount, 2);

            $stmt = $pdo->prepare("
                UPDATE users
                SET withdrawable_balance = withdrawable_balance + ?
                WHERE id = ?
            ");
            $stmt->execute([$cashAmount, $userId]);

            $user['withdrawable_balance'] = $after;

            insertWalletTransaction(
                $pdo,
                $txnRefBase . 'C',
                $userId,
                'withdrawable_balance',
                'credit',
                $cashAmount,
                'daily_login_',
                'success',
                'daily_login_claim',
                $claimId,
                'Daily login cash bonus',
                $before,
                $after
            );
        } else {
            $before = round((float)$user['play_balance'], 2);
            $after = round($before + $cashAmount, 2);

            $stmt = $pdo->prepare("
                UPDATE users
                SET play_balance = play_balance + ?
                WHERE id = ?
            ");
            $stmt->execute([$cashAmount, $userId]);

            $user['play_balance'] = $after;

            insertWalletTransaction(
                $pdo,
                $txnRefBase . 'C',
                $userId,
                'play_balance',
                'credit',
                $cashAmount,
                'daily_login_bonus',
                'success',
                'daily_login_claim',
                $claimId,
                'Daily login cash bonus',
                $before,
                $after
            );
        }
    }

    if ($dragonCoins > 0) {
        $before = (float)$user['dragon_coins'];
        $after = $before + $dragonCoins;

        $stmt = $pdo->prepare("
            UPDATE users
            SET dragon_coins = dragon_coins + ?
            WHERE id = ?
        ");
        $stmt->execute([$dragonCoins, $userId]);

        $user['dragon_coins'] = $after;

        insertWalletTransaction(
            $pdo,
            $txnRefBase . 'D',
            $userId,
            'dragon_coins',
            'credit',
            (float)$dragonCoins,
            'daily_login_bonus',
            'success',
            'daily_login_claim',
            $claimId,
            'Daily login dragon coin bonus',
            $before,
            $after
        );
    }

    $stmt = $pdo->prepare("
        UPDATE user_daily_login_state
        SET
            last_claim_date = ?,
            streak_day = ?,
            total_claims = ?
        WHERE user_id = ?
    ");
    $stmt->execute([
        $today,
        $newStreakDay,
        $totalClaims + 1,
        $userId
    ]);

    $pdo->commit();

    jsonResponse(200, [
        'success' => true,
        'already_claimed' => false,
        'streak_day' => $newStreakDay,
        'reward' => [
            'reward_day_number' => $rewardDayNumber,
            'title' => $rewardTitle,
            'cash_amount' => formatAmount($cashAmount),
            'dragon_coins' => $dragonCoins,
            'wallet_type' => $walletType
        ],
        'message' => 'Daily login reward claimed'
    ]);
} catch (Throwable $e) {
    if (isset($pdo) && $pdo->inTransaction()) {
        $pdo->rollBack();
    }

    jsonResponse(400, [
        'success' => false,
        'message' => $e->getMessage()
    ]);
}
