<?php
error_reporting(E_ALL);
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
/* ============================================================
   task.php
   IMAGE TASK SYSTEM + BACKEND
   ============================================================ */

session_start();
date_default_timezone_set('Africa/Nairobi');

require_once 'db.php';

/* ============================================================
   ERROR REPORTING
   ============================================================ */

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

/* ============================================================
   CHECK LOGIN
   ============================================================ */

if (!isset($_SESSION['user_id'])) {
    header("Location: login.php");
    exit;
}

$user_id = (int)$_SESSION['user_id'];

/* ============================================================
   HELPERS
   ============================================================ */

function jsonResponse($success, $message = '', $data = [])
{
    header('Content-Type: application/json; charset=utf-8');

    echo json_encode([
        'success' => $success,
        'message' => $message,
        'data'    => $data
    ]);

    exit;
}


/*
 * Get today's completed task count.
 */
function getTodayCompletedTasks($conn, $user_id)
{
    $stmt = $conn->prepare("
        SELECT COUNT(*) AS total
        FROM task_records
        WHERE user_id = ?
          AND status = 'completed'
          AND DATE(created_date) = CURDATE()
    ");

    $stmt->bind_param("i", $user_id);
    $stmt->execute();

    $result = $stmt->get_result();
    $row = $result->fetch_assoc();

    $stmt->close();

    return (int)$row['total'];
}


/*
 * Check whether a user has an active investment.
 *
 * The latest/highest active level is used.
 */
function getUserInvestmentLevel($conn, $user_id)
{
    $stmt = $conn->prepare("
        SELECT level
        FROM investments
        WHERE user_id = ?
          AND status = 'active'
        ORDER BY level DESC, id DESC
        LIMIT 1
    ");

    $stmt->bind_param("i", $user_id);
    $stmt->execute();

    $result = $stmt->get_result();
    $row = $result->fetch_assoc();

    $stmt->close();

    if (!$row) {
        return 0;
    }

    return (int)$row['level'];
}


/*
 * Check free-task period.
 *
 * No investment = 3 days from users.created_at.
 */
function isInsideFreePeriod($conn, $user_id)
{
    $stmt = $conn->prepare("
        SELECT created_at
        FROM users
        WHERE id = ?
        LIMIT 1
    ");

    $stmt->bind_param("i", $user_id);
    $stmt->execute();

    $result = $stmt->get_result();
    $row = $result->fetch_assoc();

    $stmt->close();

    if (!$row) {
        return false;
    }

    $created = strtotime($row['created_at']);

    if (!$created) {
        return false;
    }

    $expires = $created + (3 * 24 * 60 * 60);

    return time() < $expires;
}


/*
 * Find uplines.

 * A:
 * referred_by = direct referrer
 *
 * B:
 * referrer's referred_by
 *
 * C:
 * third level referrer
 */
function getUplines($conn, $user_id)
{
    $uplines = [];

    $current = $user_id;

    for ($level = 1; $level <= 3; $level++) {

        $stmt = $conn->prepare("
            SELECT referred_by
            FROM users
            WHERE id = ?
            LIMIT 1
        ");

        $stmt->bind_param("i", $current);
        $stmt->execute();

        $result = $stmt->get_result();
        $row = $result->fetch_assoc();

        $stmt->close();

        if (!$row || empty($row['referred_by'])) {
            break;
        }

        $refValue = trim((string)$row['referred_by']);

        /*
         * referred_by may contain either:
         * - user ID
         * - referral code
         */

        $refUserId = 0;

        if (ctype_digit($refValue)) {

            $possibleId = (int)$refValue;

            $check = $conn->prepare("
                SELECT id
                FROM users
                WHERE id = ?
                LIMIT 1
            ");

            $check->bind_param("i", $possibleId);
            $check->execute();

            $checkResult = $check->get_result();
            $checkRow = $checkResult->fetch_assoc();

            $check->close();

            if ($checkRow) {
                $refUserId = (int)$checkRow['id'];
            }
        }

        /*
         * If it wasn't a numeric user ID,
         * try referral_code.
         */
        if ($refUserId <= 0) {

            $check = $conn->prepare("
                SELECT id
                FROM users
                WHERE referral_code = ?
                LIMIT 1
            ");

            $check->bind_param("s", $refValue);
            $check->execute();

            $checkResult = $check->get_result();
            $checkRow = $checkResult->fetch_assoc();

            $check->close();

            if ($checkRow) {
                $refUserId = (int)$checkRow['id'];
            }
        }

        if ($refUserId <= 0 || $refUserId === $user_id) {
            break;
        }

        $uplines[] = [
            'user_id' => $refUserId,
            'level'   => $level
        ];

        $current = $refUserId;
    }

    return $uplines;
}


/*
 * Get task configuration.
 */
function getTaskConfig($conn, $user_id)
{
    $level = getUserInvestmentLevel($conn, $user_id);

    /*
     * Investment level 1
     */
    if ($level === 1) {

        return [
            'level' => 1,
            'tasks' => 5,
            'reward' => 267,
            'free' => false
        ];
    }

    /*
     * Investment level 2
     */
    if ($level === 2) {

        return [
            'level' => 2,
            'tasks' => 7,
            'reward' => 667,
            'free' => false
        ];
    }

    /*
     * Investment level 3
     */
    if ($level === 3) {

        return [
            'level' => 3,
            'tasks' => 10,
            'reward' => 1500,
            'free' => false
        ];
    }

    /*
     * No investment.
     *
     * User gets 3 tasks per day,
     * but only for the first 3 days.
     */
    if (isInsideFreePeriod($conn, $user_id)) {

        return [
            'level' => 0,
            'tasks' => 3,
            'reward' => 400,
            'free' => true
        ];
    }

    /*
     * Free period expired.
     */
    return [
        'level' => 0,
        'tasks' => 0,
        'reward' => 0,
        'free' => false
    ];
}


/* ============================================================
   API
   ============================================================ */

if (isset($_GET['action'])) {

    $action = $_GET['action'];

    /* ========================================================
       TASK STATUS
       ======================================================== */

    if ($action === 'status') {

        $config = getTaskConfig($conn, $user_id);

        $completed = getTodayCompletedTasks(
            $conn,
            $user_id
        );

        $remaining = max(
            0,
            $config['tasks'] - $completed
        );

        jsonResponse(
            true,
            'Task status',
            [
                'level'     => $config['level'],
                'tasks'     => $config['tasks'],
                'reward'    => $config['reward'],
                'completed' => $completed,
                'remaining' => $remaining,
                'free'      => $config['free']
            ]
        );
    }


    /* ========================================================
       COMPLETE TASK
       ======================================================== */

    if ($action === 'complete') {

        /*
         * Only POST is accepted.
         */
        if ($_SERVER['REQUEST_METHOD'] !== 'POST') {

            jsonResponse(
                false,
                'Invalid request method.'
            );
        }


        /*
         * Read task name.
         */
        $taskName = isset($_POST['task_name'])
            ? trim($_POST['task_name'])
            : 'Popular Image Task';


        if ($taskName === '') {
            $taskName = 'Popular Image Task';
        }


        /*
         * Get current configuration.
         */
        $config = getTaskConfig(
            $conn,
            $user_id
        );


        /*
         * No tasks available.
         */
        if ($config['tasks'] <= 0) {

            jsonResponse(
                false,
                'You do not have any tasks available.'
            );
        }


        /*
         * Count completed today.
         */
        $completed = getTodayCompletedTasks(
            $conn,
            $user_id
        );


        /*
         * Daily limit.
         */
        if ($completed >= $config['tasks']) {

            jsonResponse(
                false,
                'You have completed all your tasks for today.'
            );
        }


        /*
         * Generate unique task ID.
         *
         * The frontend sends a random task ID.
         * We do not trust the reward from frontend.
         */
        $taskId = isset($_POST['task_id'])
            ? trim($_POST['task_id'])
            : '';

        if ($taskId === '') {
            $taskId = uniqid('task_', true);
        }


        /*
         * Prevent duplicate task submission.
         */
        $duplicate = $conn->prepare("
            SELECT id
            FROM task_records
            WHERE user_id = ?
              AND task_name = ?
              AND status = 'completed'
              AND created_date >= DATE_SUB(NOW(), INTERVAL 30 SECOND)
            LIMIT 1
        ");

        $duplicate->bind_param(
            "is",
            $user_id,
            $taskName
        );

        $duplicate->execute();

        $duplicateResult = $duplicate->get_result();

        $duplicate->close();

        if ($duplicateResult->num_rows > 0) {

            jsonResponse(
                false,
                'This task was already submitted.'
            );
        }


        /*
         * Reward is controlled by backend.
         */
        $reward = (int)$config['reward'];


        if ($reward <= 0) {

            jsonResponse(
                false,
                'Invalid task reward.'
            );
        }


        /*
         * Start transaction.
         */
        $conn->begin_transaction();

        try {

            /*
             * Lock user row.
             */
            $userStmt = $conn->prepare("
                SELECT balance
                FROM users
                WHERE id = ?
                FOR UPDATE
            ");

            $userStmt->bind_param(
                "i",
                $user_id
            );

            $userStmt->execute();

            $userResult = $userStmt->get_result();
            $userRow = $userResult->fetch_assoc();

            $userStmt->close();


            if (!$userRow) {

                throw new Exception(
                    'User account not found.'
                );
            }


            /*
             * Re-check today's count after locking.
             */
            $countStmt = $conn->prepare("
                SELECT COUNT(*) AS total
                FROM task_records
                WHERE user_id = ?
                  AND status = 'completed'
                  AND DATE(created_date) = CURDATE()
            ");

            $countStmt->bind_param(
                "i",
                $user_id
            );

            $countStmt->execute();

            $countResult = $countStmt->get_result();
            $countRow = $countResult->fetch_assoc();

            $countStmt->close();

            $completedNow = (int)$countRow['total'];


            if ($completedNow >= $config['tasks']) {

                throw new Exception(
                    'Daily task limit reached.'
                );
            }


            /*
             * Credit balance immediately.
             */
            $balanceStmt = $conn->prepare("
                UPDATE users
                SET balance = balance + ?
                WHERE id = ?
            ");

            $balanceStmt->bind_param(
                "di",
                $reward,
                $user_id
            );

            $balanceStmt->execute();

            $balanceStmt->close();


            /*
             * Create task_records record.
             */
            $recordStmt = $conn->prepare("
                INSERT INTO task_records
                (
                    user_id,
                    task_name,
                    reward,
                    status,
                    created_date,
                    updated_at
                )
                VALUES
                (
                    ?,
                    ?,
                    ?,
                    'completed',
                    NOW(),
                    NOW()
                )
            ");

            $recordStmt->bind_param(
                "isd",
                $user_id,
                $taskName,
                $reward
            );

            $recordStmt->execute();

            $recordId = $recordStmt->insert_id;

            $recordStmt->close();


            /*
             * =================================================
             * UPLINE BONUSES
             *
             * A = 5%
             * B = 2%
             * C = 1%
             * =================================================
             */

            $percentages = [
                1 => 5,
                2 => 2,
                3 => 1
            ];


            $uplines = getUplines(
                $conn,
                $user_id
            );


            foreach ($uplines as $upline) {

                $uplineUserId = (int)$upline['user_id'];
                $uplineLevel   = (int)$upline['level'];

                if (
                    !isset(
                        $percentages[$uplineLevel]
                    )
                ) {
                    continue;
                }

                $percentage =
                    (float)$percentages[$uplineLevel];


                $bonusAmount =
                    round(
                        ($reward * $percentage) / 100,
                        2
                    );


                if ($bonusAmount <= 0) {
                    continue;
                }


                /*
                 * Credit upline balance.
                 */
                $bonusBalanceStmt = $conn->prepare("
                    UPDATE users
                    SET balance = balance + ?
                    WHERE id = ?
                ");

                $bonusBalanceStmt->bind_param(
                    "di",
                    $bonusAmount,
                    $uplineUserId
                );

                $bonusBalanceStmt->execute();

                $bonusBalanceStmt->close();


                /*
                 * Record task bonus.
                 */
                $bonusStmt = $conn->prepare("
                    INSERT INTO task_bonuses
                    (
                        user_id,
                        from_user_id,
                        level,
                        task_id,
                        amount,
                        percentage,
                        created_at
                    )
                    VALUES
                    (
                        ?,
                        ?,
                        ?,
                        ?,
                        ?,
                        ?,
                        NOW()
                    )
                ");

                /*
                 * user_id     = upline receiving bonus
                 * from_user_id= user who completed task
                 * level       = A/B/C numeric level 1/2/3
                 * task_id     = task_records.id
                 */
                $bonusStmt->bind_param(
                    "iiisdd",
                    $uplineUserId,
                    $user_id,
                    $uplineLevel,
                    $recordId,
                    $bonusAmount,
                    $percentage
                );

                /*
                 * task_id column is commonly INT.
                 *
                 * If your task_bonuses.task_id is INT,
                 * the binding above needs task_id as integer.
                 */
                $bonusStmt->close();

                /*
                 * Insert again using the correct INT binding.
                 */
                $bonusStmt = $conn->prepare("
                    INSERT INTO task_bonuses
                    (
                        user_id,
                        from_user_id,
                        level,
                        task_id,
                        amount,
                        percentage,
                        created_at
                    )
                    VALUES
                    (
                        ?,
                        ?,
                        ?,
                        ?,
                        ?,
                        ?,
                        NOW()
                    )
                ");

                $bonusStmt->bind_param(
                    "iiiidd",
                    $uplineUserId,
                    $user_id,
                    $uplineLevel,
                    $recordId,
                    $bonusAmount,
                    $percentage
                );

                $bonusStmt->execute();

                $bonusStmt->close();
            }


            /*
             * Commit everything.
             */
            $conn->commit();


            $newCompleted =
                $completedNow + 1;

            $remaining =
                max(
                    0,
                    $config['tasks'] - $newCompleted
                );


            jsonResponse(
                true,
                'Task completed successfully.',
                [
                    'reward'    => $reward,
                    'completed' => $newCompleted,
                    'remaining' => $remaining,
                    'task_id'   => $recordId
                ]
            );

        } catch (Throwable $e) {

            $conn->rollback();

            jsonResponse(
                false,
                $e->getMessage()
            );
        }
    }


    jsonResponse(
        false,
        'Unknown action.'
    );
}


/* ============================================================
   NORMAL PAGE
   ============================================================ */

$config = getTaskConfig(
    $conn,
    $user_id
);

$completedToday = getTodayCompletedTasks(
    $conn,
    $user_id
);

$remainingToday = max(
    0,
    $config['tasks'] - $completedToday
);

?>
<!DOCTYPE html>
<html lang="en">

<head>

<meta charset="UTF-8">

<meta name="viewport"
      content="width=device-width,
      initial-scale=1.0,
      maximum-scale=1.0,
      user-scalable=no">

<title>Popular images</title>

<style>

/* =====================================================
   RESET
===================================================== */

* {
    box-sizing: border-box;
    -webkit-tap-highlight-color: transparent;
}

html,
body {
    margin: 0;
    padding: 0;
    width: 100%;
    min-height: 100%;
}

html {
    font-size: 8px;
}

body {
    background: #f7f3eb;
    color: #222;

    font-family:
        -apple-system,
        BlinkMacSystemFont,
        "Segoe UI",
        Roboto,
        Helvetica,
        Arial,
        sans-serif;

    overflow-x: hidden;
}


/* =====================================================
   MAIN HEADER
===================================================== */

.header {
    width: 100%;
    height: 74px;

    background: #ffffff;

    display: flex;
    align-items: center;
    justify-content: center;

    position: sticky;
    top: 0;

    z-index: 1000;

    border-bottom: 1px solid #eeeeee;
}


/* =====================================================
   BACK BUTTON
===================================================== */

.back-button {
    position: absolute;

    left: 20px;
    top: 50%;

    transform: translateY(-50%);

    width: 28px;
    height: 28px;

    display: flex;
    align-items: center;
    justify-content: center;

    cursor: pointer;
}

.back-arrow {
    width: 15px;
    height: 15px;

    border-left: 2px solid #2387d8;
    border-bottom: 2px solid #2387d8;

    transform: rotate(45deg);

    margin-left: 5px;
}


/* =====================================================
   HEADER TITLE
===================================================== */

.header-title {
    margin: 0;

    font-size: 18px;
    line-height: 1;

    font-weight: 700;

    color: #292929;

    letter-spacing: -0.3px;
}


/* =====================================================
   TASK INFO
===================================================== */

.task-info {
    width: 100%;

    background: #ffffff;

    padding: 8px 12px;

    text-align: center;

    border-bottom: 1px solid #eeeeee;

    font-size: 10px;

    color: #666;
}

.task-info strong {
    color: #2387d8;
}


/* =====================================================
   GALLERY
===================================================== */

.gallery {
    width: 100%;

    padding: 9px 18px 35px 18px;

    display: grid;

    grid-template-columns:
        repeat(2, minmax(0, 1fr));

    column-gap: 18px;

    row-gap: 24px;

    align-items: start;
}


/* =====================================================
   GALLERY IMAGE
===================================================== */

.image-card {
    width: 100%;

    aspect-ratio: 3 / 4;

    overflow: hidden;

    background: #e9e4da;

    position: relative;

    cursor: pointer;

    transition:
        transform 0.45s ease,
        opacity 0.45s ease;
}

.image-card img {
    display: block;

    width: 100%;
    height: 100%;

    object-fit: cover;

    object-position: center;

    user-select: none;

    -webkit-user-drag: none;

    transition:
        transform 0.6s ease,
        opacity 0.35s ease;
}

.image-card.shuffle-effect img {
    opacity: 0.72;

    transform: scale(0.985);
}

.image-card.loading {
    background: #e8e2d8;
}


/* =====================================================
   DETAIL PAGE
===================================================== */

.detail-page {

    display: none;

    width: 100%;

    min-height: 100vh;

    background: #f7f3eb;
}


/* =====================================================
   DETAIL TOPBAR
===================================================== */

.detail-topbar {

    width: 100%;

    height: 58px;

    background: #ffffff;

    display: flex;

    align-items: center;

    justify-content: center;

    position: sticky;

    top: 0;

    z-index: 3000;

    border-bottom:
        1px solid #e8e8e8;
}


/* =====================================================
   DETAIL BACK
===================================================== */

.detail-back {

    position: absolute;

    left: 12px;

    top: 50%;

    transform:
        translateY(-50%);

    width: 30px;

    height: 30px;

    display: flex;

    align-items: center;

    justify-content: center;

    cursor: pointer;
}

.detail-back-arrow {

    width: 15px;

    height: 15px;

    border-left:
        2px solid #2387d8;

    border-bottom:
        2px solid #2387d8;

    transform:
        rotate(45deg);

    margin-left: 5px;
}


/* =====================================================
   COUNTDOWN
===================================================== */

.countdown-text {

    font-size: 14px;

    font-weight: 600;

    color: #333;

    text-align: center;

    white-space: nowrap;
}

.countdown-time {

    font-weight: 700;

    color: #e53935;

    font-variant-numeric:
        tabular-nums;
}


/* =====================================================
   DETAIL CONTENT
===================================================== */

.detail-content {

    width: 100%;

    padding: 0;

    margin: 0;
}


/* =====================================================
   DETAIL IMAGE
===================================================== */

.detail-image-box {

    width: 100%;

    margin: 0;

    padding: 0;

    background: #e9e4da;

    overflow: hidden;

    position: relative;
}

.detail-image {

    display: block;

    width: 100%;

    height: auto;

    min-height: 250px;

    max-height: 90vh;

    object-fit: cover;

    object-position: center;

    user-select: none;

    -webkit-user-drag: none;
}


/* =====================================================
   SIMILAR TITLE
===================================================== */

.similar-title {

    width: 100%;

    padding:
        11px
        10px
        8px
        10px;

    margin: 0;

    font-size: 11px;

    font-weight: 700;

    color: #252525;

    background: #f7f3eb;
}


/* =====================================================
   RATING OVERLAY
===================================================== */

.rating-overlay {

    position: fixed;

    inset: 0;

    width: 100%;

    height: 100%;

    background:
        rgba(0, 0, 0, 0.62);

    display: none;

    align-items: center;

    justify-content: center;

    z-index: 99990;

    padding: 12px;
}


/* =====================================================
   RATING POPUP
===================================================== */

.rating-popup {

    width: 100%;

    max-width: 430px;

    background: #ffffff;

    border-radius: 22px;

    overflow: hidden;

    text-align: center;

    box-shadow:
        0 15px 45px
        rgba(0,0,0,0.30);

    animation:
        popupIn 0.28s ease;
}


@keyframes popupIn {

    from {

        opacity: 0;

        transform:
            scale(0.88);
    }

    to {

        opacity: 1;

        transform:
            scale(1);
    }
}


/* =====================================================
   RATING BODY
===================================================== */

.rating-body {

    padding:
        30px
        12px
        22px;
}


/* =====================================================
   RATING TITLE
===================================================== */

.rating-title {

    margin: 0;

    font-size: 18px;

    line-height: 1.2;

    font-weight: 700;

    color: #292929;
}


/* =====================================================
   RATING QUESTION
===================================================== */

.rating-question {

    margin:
        25px
        0
        17px;

    font-size: 14px;

    line-height: 1.3;

    color: #333;
}


/* =====================================================
   STARS
===================================================== */

.stars {

    display: flex;

    align-items: center;

    justify-content: center;

    gap: 3px;

    margin-bottom: 7px;
}

.star {

    border: none;

    background: transparent;

    padding: 0;

    margin: 0;

    width: 45px;

    height: 45px;

    display: flex;

    align-items: center;

    justify-content: center;

    cursor: pointer;

    color: #078c69;

    font-size: 38px;

    line-height: 1;

    transition:
        transform 0.15s ease,
        color 0.15s ease;
}

.star:active {

    transform:
        scale(0.85);
}

.star.empty {

    color: #d5d5d5;
}


/* =====================================================
   RATING VALUE
===================================================== */

.rating-value {

    min-height: 15px;

    margin-top: 2px;

    font-size: 9px;

    color: #777;
}


/* =====================================================
   RATING BUTTONS
===================================================== */

.rating-actions {

    width: 100%;

    display: grid;

    grid-template-columns:
        1fr 1fr;

    border-top:
        1px solid #dddddd;
}

.rating-button {

    height: 58px;

    border: none;

    background: #ffffff;

    font-size: 15px;

    color: #222;

    cursor: pointer;
}

.rating-button:first-child {

    border-right:
        1px solid #dddddd;
}

.rating-button:active {

    background: #f5f5f5;
}

.rating-submit {

    color: #222;

    font-weight: 500;
}


/* =====================================================
   SUCCESS OVERLAY
===================================================== */

.success-overlay {

    position: fixed;

    inset: 0;

    width: 100%;

    height: 100%;

    background:
        rgba(0, 0, 0, 0.62);

    display: none;

    align-items: center;

    justify-content: center;

    z-index: 99999;

    padding: 12px;
}


/* =====================================================
   SUCCESS POPUP
===================================================== */

.success-popup {

    width: 100%;

    max-width: 320px;

    background: #ffffff;

    border-radius: 16px;

    padding:
        24px
        18px
        20px;

    text-align: center;

    box-shadow:
        0 15px 40px
        rgba(0,0,0,0.25);

    animation:
        popupIn 0.3s ease;
}


/* =====================================================
   SUCCESS ICON
===================================================== */

.success-icon {

    width: 52px;

    height: 52px;

    margin:
        0 auto
        11px;

    border-radius: 50%;

    background: #22c55e;

    color: #ffffff;

    display: flex;

    align-items: center;

    justify-content: center;

    font-size: 27px;

    font-weight: 700;
}


/* =====================================================
   SUCCESS TITLE
===================================================== */

.success-title {

    margin:
        0 0 6px 0;

    font-size: 18px;

    font-weight: 700;

    color: #222;
}


/* =====================================================
   SUCCESS MESSAGE
===================================================== */

.success-message {

    margin:
        0 0 16px 0;

    font-size: 10px;

    line-height: 1.4;

    color: #666;
}


/* =====================================================
   SUCCESS BUTTON
===================================================== */

.success-button {

    width: 100%;

    height: 42px;

    border: 0;

    border-radius: 9px;

    background: #2387d8;

    color: #ffffff;

    font-size: 11px;

    font-weight: 700;

    cursor: pointer;
}

.success-button:active {

    transform:
        scale(0.98);
}


/* =====================================================
   MOBILE
===================================================== */

@media (max-width: 600px) {

    .header {

        height: 62px;
    }

    .header-title {

        font-size: 17px;

        letter-spacing:
            -0.2px;
    }

    .back-button {

        left: 15px;

        width: 25px;

        height: 25px;
    }

    .back-arrow {

        width: 14px;

        height: 14px;

        border-width:
            2px;
    }

    .gallery {

        padding:
            8px
            12px
            35px
            12px;

        column-gap: 12px;

        row-gap: 20px;
    }

    .detail-topbar {

        height: 52px;
    }

    .detail-back {

        left: 9px;
    }

    .countdown-text {

        font-size: 14px;

        padding-left: 30px;

        padding-right: 30px;
    }

    .similar-title {

        font-size: 10px;

        padding:
            10px
            9px
            7px;
    }

    .detail-image {

        min-height: 220px;

        max-height: none;

        object-fit: cover;
    }

    .rating-overlay {

        padding: 10px;
    }

    .rating-popup {

        max-width: 100%;

        border-radius: 20px;
    }

    .rating-body {

        padding:
            28px
            10px
            20px;
    }

    .rating-title {

        font-size: 17px;
    }

    .rating-question {

        margin:
            23px
            0
            15px;

        font-size: 13px;
    }

    .stars {

        gap: 1px;
    }

    .star {

        width: 42px;

        height: 42px;

        font-size: 36px;
    }

    .rating-value {

        font-size: 8px;
    }

    .rating-button {

        height: 55px;

        font-size: 14px;
    }
}


/* =====================================================
   VERY SMALL PHONES
===================================================== */

@media (max-width: 360px) {

    .header {

        height: 58px;
    }

    .header-title {

        font-size: 16px;
    }

    .gallery {

        padding-left: 10px;

        padding-right: 10px;

        column-gap: 10px;

        row-gap: 17px;
    }

    .countdown-text {

        font-size: 12px;
    }

    .rating-body {

        padding:
            24px
            8px
            17px;
    }

    .rating-title {

        font-size: 16px;
    }

    .rating-question {

        font-size: 12px;

        margin:
            20px
            0
            13px;
    }

    .star {

        width: 38px;

        height: 38px;

        font-size: 33px;
    }

    .rating-value {

        font-size: 8px;
    }

    .rating-button {

        height: 51px;

        font-size: 13px;
    }

    .success-popup {

        max-width: 290px;

        padding:
            22px
            16px
            18px;
    }

    .success-title {

        font-size: 17px;
    }

    .success-message {

        font-size: 9px;
    }

    .success-button {

        height: 39px;

        font-size: 10px;
    }
}


/* =====================================================
   LARGE SCREENS
===================================================== */

@media (min-width: 900px) {

    .gallery {

        padding-left: 36px;

        padding-right: 36px;
    }
}

</style>

</head>

<body>


<!-- =====================================================
     MAIN GALLERY
===================================================== -->

<div id="galleryPage">

<header class="header">

    <div
        class="back-button"
        onclick="goBack()">

        <div
            class="back-arrow">
        </div>

    </div>

    <h1 class="header-title">
        Popular images
    </h1>

</header>


<div class="task-info">

    Today:
    <strong id="completedCount">
        <?php echo $completedToday; ?>
    </strong>
    /
    <strong>
        <?php echo $config['tasks']; ?>
    </strong>

    tasks completed

    &nbsp; • &nbsp;

    Reward:
    <strong>
        <?php echo number_format($config['reward']); ?>
        Tsh
    </strong>

</div>


<main
    id="gallery"
    class="gallery">
</main>

</div>


<!-- =====================================================
     DETAIL PAGE
===================================================== -->

<div
    id="detailPage"
    class="detail-page">

    <div
        class="detail-topbar">

        <div
            class="detail-back"
            onclick="closeDetail()">

            <div
                class="detail-back-arrow">
            </div>

        </div>

        <div
            class="countdown-text">

            Countdown

            <span
                id="countdownTime"
                class="countdown-time">

                00:15

            </span>

            —

            The task will be completed

        </div>

    </div>


    <div
        id="detailContent"
        class="detail-content">
    </div>

</div>


<!-- =====================================================
     RATING POPUP
===================================================== -->

<div
    id="ratingOverlay"
    class="rating-overlay">

    <div
        class="rating-popup">

        <div
            class="rating-body">

            <h2
                class="rating-title">

                Task Completion Rating

            </h2>

            <p
                class="rating-question">

                Please rate this task:

            </p>

            <div
                id="stars"
                class="stars">

                <button
                    type="button"
                    class="star"
                    data-rating="1"
                    onclick="selectRating(1)">

                    ★

                </button>

                <button
                    type="button"
                    class="star"
                    data-rating="2"
                    onclick="selectRating(2)">

                    ★

                </button>

                <button
                    type="button"
                    class="star"
                    data-rating="3"
                    onclick="selectRating(3)">

                    ★

                </button>

                <button
                    type="button"
                    class="star"
                    data-rating="4"
                    onclick="selectRating(4)">

                    ★

                </button>

                <button
                    type="button"
                    class="star"
                    data-rating="5"
                    onclick="selectRating(5)">

                    ★

                </button>

            </div>

            <div
                id="ratingValue"
                class="rating-value">

                5 stars

            </div>

        </div>


        <div
            class="rating-actions">

            <button
                type="button"
                class="rating-button"
                onclick="cancelRating()">

                Cancel

            </button>

            <button
                type="button"
                class="rating-button rating-submit"
                onclick="submitRating()">

                Submit

            </button>

        </div>

    </div>

</div>


<!-- =====================================================
     SUCCESS POPUP
===================================================== -->

<div
    id="successOverlay"
    class="success-overlay">

    <div
        class="success-popup">

        <div
            class="success-icon">

            ✓

        </div>

        <h2
            class="success-title">

            Success!

        </h2>

        <p
            id="successMessage"
            class="success-message">

            The task has been completed
            successfully.

        </p>

        <button
            type="button"
            class="success-button"
            onclick="finishTask()">

            Continue

        </button>

    </div>

</div>


<script>

/* =====================================================
   SETTINGS
===================================================== */

const INITIAL_IMAGES = 1000;

const LOAD_MORE_COUNT = 300;

const SHUFFLE_TIME = 4000;

const COUNTDOWN_SECONDS = 15;


/*
 * Values are supplied by PHP.
 * The frontend NEVER decides the reward.
 */

const DAILY_TASK_LIMIT =
    <?php echo (int)$config['tasks']; ?>;

const TASK_REWARD =
    <?php echo (int)$config['reward']; ?>;

let imageNumber = 1;

let loadingMore = false;

let countdownInterval = null;

let currentSeed = null;

let currentTaskId = null;

let taskCompleted = false;

let selectedRating = 5;


/* =====================================================
   ELEMENTS
===================================================== */

const gallery =
    document.getElementById(
        "gallery"
    );

const galleryPage =
    document.getElementById(
        "galleryPage"
    );

const detailPage =
    document.getElementById(
        "detailPage"
    );

const detailContent =
    document.getElementById(
        "detailContent"
    );

const countdownTime =
    document.getElementById(
        "countdownTime"
    );

const ratingOverlay =
    document.getElementById(
        "ratingOverlay"
    );

const successOverlay =
    document.getElementById(
        "successOverlay"
    );

const successMessage =
    document.getElementById(
        "successMessage"
    );

const ratingValue =
    document.getElementById(
        "ratingValue"
    );

const completedCount =
    document.getElementById(
        "completedCount"
    );

const stars =
    document.querySelectorAll(
        ".star"
    );


/* =====================================================
   IMAGE URL
===================================================== */

function getImageUrl(seed) {

    return (
        "https://picsum.photos/seed/" +
        seed +
        "/900/1200"
    );

}


/* =====================================================
   CREATE GALLERY CARD
===================================================== */

function createCard(seed) {

    const card =
        document.createElement(
            "div"
        );

    card.className =
        "image-card loading";

    card.dataset.seed =
        seed;

    const img =
        document.createElement(
            "img"
        );

    img.alt =
        "Popular image";

    img.loading =
        "lazy";

    img.decoding =
        "async";

    img.src =
        getImageUrl(
            seed
        );

    img.onload =
        function() {

            card.classList.remove(
                "loading"
            );

        };

    img.onerror =
        function() {

            const newSeed =
                Math.floor(
                    Math.random()
                    * 1000000
                );

            img.src =
                getImageUrl(
                    newSeed
                );

        };

    card.onclick =
        function() {

            openDetail(
                seed
            );

        };

    card.appendChild(
        img
    );

    return card;

}


/* =====================================================
   CREATE INITIAL GALLERY
===================================================== */

function createInitialGallery() {

    const fragment =
        document.createDocumentFragment();

    for (
        let i = 0;
        i < INITIAL_IMAGES;
        i++
    ) {

        const seed =
            imageNumber++;

        const card =
            createCard(
                seed
            );

        card.style.order =
            i;

        fragment.appendChild(
            card
        );

    }

    gallery.appendChild(
        fragment
    );

}


/* =====================================================
   ADD MORE IMAGES
===================================================== */

function addMoreImages() {

    if (loadingMore) {

        return;

    }

    loadingMore = true;

    const fragment =
        document.createDocumentFragment();

    const currentCount =
        gallery.children.length;

    for (
        let i = 0;
        i < LOAD_MORE_COUNT;
        i++
    ) {

        const seed =
            imageNumber++;

        const card =
            createCard(
                seed
            );

        card.style.order =
            currentCount + i;

        fragment.appendChild(
            card
        );

    }

    gallery.appendChild(
        fragment
    );

    loadingMore = false;

}


/* =====================================================
   SHUFFLE
===================================================== */

function shuffleCards() {

    if (
        detailPage.style.display ===
        "block"
    ) {

        return;

    }

    const cards =
        Array.from(
            gallery.children
        );

    cards.forEach(
        function(card) {

            card.classList.add(
                "shuffle-effect"
            );

        }
    );

    for (
        let i = cards.length - 1;
        i > 0;
        i--
    ) {

        const j =
            Math.floor(
                Math.random()
                * (i + 1)
            );

        const temp =
            cards[i];

        cards[i] =
            cards[j];

        cards[j] =
            temp;

    }

    cards.forEach(
        function(card, index) {

            card.style.order =
                index;

        }
    );

    setTimeout(
        function() {

            cards.forEach(
                function(card) {

                    card.classList.remove(
                        "shuffle-effect"
                    );

                }
            );

        },
        450
    );

}


setInterval(
    function() {

        shuffleCards();

    },
    SHUFFLE_TIME
);


/* =====================================================
   ENDLESS SCROLL
===================================================== */

window.addEventListener(
    "scroll",

    function() {

        if (
            detailPage.style.display ===
            "block"
        ) {

            return;

        }

        const scrollPosition =
            window.innerHeight +
            window.scrollY;

        const pageHeight =
            document.documentElement
                .scrollHeight;

        if (
            scrollPosition >=
            pageHeight - 1500
        ) {

            addMoreImages();

        }

    },

    {
        passive: true
    }

);


/* =====================================================
   OPEN DETAIL
===================================================== */

function openDetail(seed) {

    /*
     * Don't allow opening another task
     * after today's limit.
     */
    const currentCompleted =
        parseInt(
            completedCount.textContent,
            10
        ) || 0;

    if (
        currentCompleted >=
        DAILY_TASK_LIMIT
    ) {

        alert(
            "You have completed all your tasks for today."
        );

        return;

    }


    currentSeed =
        seed;

    currentTaskId =
        "task_" +
        Date.now() +
        "_" +
        Math.floor(
            Math.random() * 100000
        );


    taskCompleted =
        false;

    galleryPage.style.display =
        "none";

    detailPage.style.display =
        "block";

    window.scrollTo(
        0,
        0
    );

    createDetailImages(
        seed
    );

    selectedRating =
        5;

    updateStars();

    ratingOverlay.style.display =
        "none";

    successOverlay.style.display =
        "none";

    startCountdown();

}


/* =====================================================
   CREATE DETAIL IMAGES
===================================================== */

function createDetailImages(seed) {

    detailContent.innerHTML =
        "";

    const detailSeeds = [

        seed,

        seed + 1,

        seed + 2,

        seed + 3

    ];

    const first =
        createDetailImage(
            detailSeeds[0]
        );

    detailContent.appendChild(
        first
    );

    const title =
        document.createElement(
            "div"
        );

    title.className =
        "similar-title";

    title.textContent =
        "Similar images";

    detailContent.appendChild(
        title
    );

    for (
        let i = 1;
        i < detailSeeds.length;
        i++
    ) {

        const image =
            createDetailImage(
                detailSeeds[i]
            );

        detailContent.appendChild(
            image
        );

    }

}


/* =====================================================
   CREATE DETAIL IMAGE
===================================================== */

function createDetailImage(seed) {

    const box =
        document.createElement(
            "div"
        );

    box.className =
        "detail-image-box";

    const img =
        document.createElement(
            "img"
        );

    img.className =
        "detail-image";

    img.src =
        getImageUrl(
            seed
        );

    img.alt =
        "Popular image";

    img.loading =
        "eager";

    img.decoding =
        "async";

    img.onerror =
        function() {

            const newSeed =
                Math.floor(
                    Math.random()
                    * 1000000
                );

            img.src =
                getImageUrl(
                    newSeed
                );

        };

    box.appendChild(
        img
    );

    return box;

}


/* =====================================================
   START COUNTDOWN
===================================================== */

function startCountdown() {

    if (
        countdownInterval !== null
    ) {

        clearInterval(
            countdownInterval
        );

    }

    let secondsLeft =
        COUNTDOWN_SECONDS;

    updateCountdown(
        secondsLeft
    );

    countdownInterval =
        setInterval(
            function() {

                secondsLeft--;

                updateCountdown(
                    secondsLeft
                );

                if (
                    secondsLeft <= 0
                ) {

                    clearInterval(
                        countdownInterval
                    );

                    countdownInterval =
                        null;

                    showRatingPopup();

                }

            },
            1000
        );

}


/* =====================================================
   UPDATE COUNTDOWN
===================================================== */

function updateCountdown(seconds) {

    if (
        seconds < 0
    ) {

        seconds = 0;

    }

    const minutes =
        Math.floor(
            seconds / 60
        );

    const remainingSeconds =
        seconds % 60;

    const formattedMinutes =
        String(
            minutes
        ).padStart(
            2,
            "0"
        );

    const formattedSeconds =
        String(
            remainingSeconds
        ).padStart(
            2,
            "0"
        );

    countdownTime.textContent =
        formattedMinutes +
        ":" +
        formattedSeconds;

}


/* =====================================================
   SHOW RATING
===================================================== */

function showRatingPopup() {

    selectedRating =
        5;

    updateStars();

    ratingOverlay.style.display =
        "flex";

}


/* =====================================================
   SELECT RATING
===================================================== */

function selectRating(rating) {

    selectedRating =
        rating;

    updateStars();

}


/* =====================================================
   UPDATE STARS
===================================================== */

function updateStars() {

    stars.forEach(
        function(star) {

            const rating =
                Number(
                    star.dataset.rating
                );

            if (
                rating <=
                selectedRating
            ) {

                star.classList.remove(
                    "empty"
                );

            } else {

                star.classList.add(
                    "empty"
                );

            }

        }
    );

    ratingValue.textContent =
        selectedRating +
        (
            selectedRating === 1
                ? " star"
                : " stars"
        );

}


/* =====================================================
   CANCEL RATING
===================================================== */

function cancelRating() {

    ratingOverlay.style.display =
        "none";

}


/* =====================================================
   SUBMIT RATING
===================================================== */

function submitRating() {

    if (taskCompleted) {
        return;
    }

    if (!currentTaskId) {
        alert("Task ID is missing.");
        return;
    }

    taskCompleted = true;

    ratingOverlay.style.display = "none";

    const formData = new FormData();

    formData.append("task_id", currentTaskId);
    formData.append("task_name", "Popular Image Task");
    formData.append("rating", selectedRating);

    fetch("task.php?action=complete", {
        method: "POST",
        body: formData,
        credentials: "same-origin"
    })
    .then(async function(response) {

        const text = await response.text();

        console.log("HTTP STATUS:", response.status);
        console.log("SERVER RESPONSE:", text);

        if (!response.ok) {
            throw new Error(
                "HTTP " +
                response.status +
                ": " +
                text.substring(0, 500)
            );
        }

        let result;

        try {
            result = JSON.parse(text);
        } catch (e) {

            throw new Error(
                "PHP did not return valid JSON.\n\n" +
                text.substring(0, 1000)
            );
        }

        return result;
    })
    .then(function(result) {

        console.log("JSON RESULT:", result);

        if (!result.success) {

            taskCompleted = false;

            alert(
                result.message ||
                "Unable to complete task."
            );

            return;
        }

        if (
            result.data &&
            typeof result.data.completed !== "undefined"
        ) {
            completedCount.textContent =
                result.data.completed;
        }

        const reward =
            result.data &&
            result.data.reward
                ? result.data.reward
                : TASK_REWARD;

        successMessage.textContent =
            "Task completed successfully. " +
            Number(reward).toLocaleString() +
            " Tsh has been added to your balance.";

        successOverlay.style.display = "flex";
    })
    .catch(function(error) {

        taskCompleted = false;

        ratingOverlay.style.display = "none";

        console.error("TASK ERROR:", error);

        alert(
            "Task request failed:\n\n" +
            error.message
        );
    });
}


/* =====================================================
   FINISH TASK
===================================================== */

function finishTask() {

    successOverlay.style.display =
        "none";

    closeDetail();

}


/* =====================================================
   CLOSE DETAIL
===================================================== */

function closeDetail() {

    if (
        countdownInterval !== null
    ) {

        clearInterval(
            countdownInterval
        );

        countdownInterval =
            null;

    }

    ratingOverlay.style.display =
        "none";

    successOverlay.style.display =
        "none";

    detailPage.style.display =
        "none";

    galleryPage.style.display =
        "block";

    taskCompleted =
        false;

    currentSeed =
        null;

    currentTaskId =
        null;

    window.scrollTo(
        0,
        0
    );

}


/* =====================================================
   MAIN BACK
===================================================== */

function goBack() {

    if (
        window.history.length > 1
    ) {

        window.history.back();

    } else {

        window.location.href =
            "index.php";

    }

}


/* =====================================================
   ESC KEY
===================================================== */

document.addEventListener(
    "keydown",

    function(event) {

        if (
            event.key ===
            "Escape"
        ) {

            if (
                ratingOverlay.style.display ===
                "flex"
            ) {

                cancelRating();

                return;

            }

            if (
                successOverlay.style.display ===
                "flex"
            ) {

                return;

            }

            if (
                detailPage.style.display ===
                "block"
            ) {

                closeDetail();

            }

        }

    }
);


/* =====================================================
   START
===================================================== */

createInitialGallery();

</script>

</body>
</html>