<?php
header("Content-Type: application/json");

// ===== GET FOLDER PARAM =====
$folder = $_GET['folder'] ?? null;
if (!$folder) {
    echo json_encode(["error" => "Missing 'folder' parameter. Example: ?folder=kyliejenner"]);
    exit;
}
$folderPath = __DIR__ . '/' . basename($folder); // Prevent directory traversal

// ===== DYNAMIC FOLDER CREATION =====
if (!is_dir($folderPath)) {
    // Create folder
    if (!mkdir($folderPath, 0777, true)) {
        echo json_encode(["error" => "Failed to create folder: $folder"]);
        exit;
    }

    // --- GET USER ID FROM getuser.php ---
    $apiUrl = "https://" . $_SERVER['HTTP_HOST'] . "/manager/scraped/getuser.php?username=" . urlencode($folder);
    $userApiResponse = file_get_contents($apiUrl);
    if ($userApiResponse === false) {
        echo json_encode(["error" => "Failed to retrieve user info from $apiUrl"]);
        exit;
    }

    $userApiData = json_decode($userApiResponse, true);

    // Validate response
    if (!isset($userApiData['userID']) || empty($userApiData['userID'])) {
        echo json_encode([
            "error" => "Could not retrieve userID for username '$folder'.",
            "api_response" => $userApiData
        ]);
        exit;
    }

    $userID = $userApiData['userID'];

    // --- CREATE config.php DYNAMICALLY ---
    $configContent = <<<PHP
<?php
// ===== LOAD SESSIONID FROM sessionid.txt =====
\$sessionFile = __DIR__ . '/../sessionid.txt';
if (!file_exists(\$sessionFile)) {
    die("Missing sessionid.txt file in parent directory.");
}
\$sessionid = trim(file_get_contents(\$sessionFile));
if (empty(\$sessionid)) {
    die("sessionid.txt is empty. Please add your Threads sessionid.");
}

// ===== HEADERS =====
\$headers = [
    "accept: */*",
    "accept-language: en-US,en;q=0.9",
    "content-type: application/x-www-form-urlencoded",
    "priority: u=1, i",
    "sec-ch-prefers-color-scheme: dark",
    "sec-ch-ua: \\"Chromium\\";v=\\"140\\", \\"Not=A?Brand\\";v=\\"24\\", \\"Google Chrome\\";v=\\"140\\"",
    "sec-ch-ua-full-version-list: \\"Chromium\\";v=\\"140.0.7339.128\\", \\"Not=A?Brand\\";v=\\"24.0.0.0\\", \\"Google Chrome\\";v=\\"140.0.7339.128\\"",
    "sec-ch-ua-mobile: ?0",
    "sec-ch-ua-model: \\"\\"",
    "sec-ch-ua-platform: \\"Windows\\"",
    "sec-ch-ua-platform-version: \\"15.0.0\\"",
    "sec-fetch-dest: empty",
    "sec-fetch-mode: cors",
    "sec-fetch-site: same-origin",
    "x-asbd-id: 359341",
    "x-bloks-version-id: 3783b86142c3f9b563a4e7b4277e99523c234b1734f46a286474592c36a615d9",
    "x-csrftoken: dq5eSEB5U8XD8qBr2FmP5HZCcwoVn5oa",
    "x-fb-friendly-name: BarcelonaProfileThreadsTabRefetchableDirectQuery",
    "x-fb-lsd: ABEaAm91qdVTXUVG9TWJfq",
    "x-ig-app-id: 238260118697367",
    "x-root-field-name: xdt_api__v1__text_feed__user_id__profile__connection",
    "cookie: csrftoken=dq5eSEB5U8XD8qBr2FmP5HZCcwoVn5oa; ds_user_id=74214170932; sessionid=" . urlencode(\$sessionid) . ";",
    "Referer: https://www.threads.com/@$folder"
];

// ===== Build dynamic POST body =====
function buildBody(\$afterCursor = null) {
    \$variables = [
        "after" => \$afterCursor,
        "before" => null,
        "first" => 20,
        "last" => null,
        "userID" => "$userID",
        "__relay_internal__pv__BarcelonaIsLoggedInrelayprovider" => true,
        "__relay_internal__pv__BarcelonaHasProfileSelfReplyContextrelayprovider" => false,
        "__relay_internal__pv__BarcelonaHasInlineReplyComposerrelayprovider" => true,
        "__relay_internal__pv__BarcelonaIsReplyApprovalEnabledrelayprovider" => false,
        "__relay_internal__pv__BarcelonaIsReplyApprovalsConsumptionEnabledrelayprovider" => false,
        "__relay_internal__pv__BarcelonaHasEventBadgerelayprovider" => false,
        "__relay_internal__pv__BarcelonaIsSearchDiscoveryEnabledrelayprovider" => false,
        "__relay_internal__pv__BarcelonaHasSelfThreadCountrelayprovider" => false,
        "__relay_internal__pv__IsTagIndicatorEnabledrelayprovider" => true,
        "__relay_internal__pv__BarcelonaHasDeepDiverelayprovider" => false,
        "__relay_internal__pv__BarcelonaHasGhostPostConsumptionrelayprovider" => false,
        "__relay_internal__pv__BarcelonaHasSpoilerStylingInforelayprovider" => true,
        "__relay_internal__pv__BarcelonaOptionalCookiesEnabledrelayprovider" => true,
        "__relay_internal__pv__BarcelonaQuotedPostUFIEnabledrelayprovider" => false,
        "__relay_internal__pv__BarcelonaHasTopicTagsrelayprovider" => true,
        "__relay_internal__pv__BarcelonaIsCrawlerrelayprovider" => false,
        "__relay_internal__pv__BarcelonaHasDisplayNamesrelayprovider" => false,
        "__relay_internal__pv__BarcelonaCanSeeSponsoredContentrelayprovider" => false,
        "__relay_internal__pv__BarcelonaShouldShowFediverseM075Featuresrelayprovider" => false,
        "__relay_internal__pv__BarcelonaImplicitTrendsGKrelayprovider" => false,
        "__relay_internal__pv__BarcelonaIsInternalUserrelayprovider" => false
    ];

    \$variablesEncoded = urlencode(json_encode(\$variables));

    return "av=17841474247966771&__user=0&__a=1&__req=7&__hs=20350.HYP%3Abarcelona_web_pkg.2.1...0&dpr=1&__ccg=EXCELLENT&__rev=1027328602"
        . "&variables={\$variablesEncoded}"
        . "&server_timestamps=true"
        . "&doc_id=24076404572036726";
}
PHP;

    // Save config.php inside folder
    file_put_contents($folderPath . '/config.php', $configContent);

    // Create empty data.txt
    file_put_contents($folderPath . '/data.txt', json_encode([], JSON_PRETTY_PRINT));
}

// ===== LOAD CONFIG FROM FOLDER =====
$configFile = $folderPath . '/config.php';
require $configFile;

// ===== FILE PATHS =====
$OUTPUT_FILE = $folderPath . "/data.txt";

// ===== COUNTRY → TIMEZONE MAPPING =====
$countryToTimezone = [
    'Nigeria' => 'Africa/Lagos',
    'Romania' => 'Europe/Bucharest',
    'USA'     => 'America/New_York',
    'UK'      => 'Europe/London',
    'India'   => 'Asia/Kolkata',
    'Thailand'=> 'Asia/Bangkok',
    'Egypt'   => 'Africa/Cairo',
    'UAE'     => 'Asia/Dubai'
];

// ===== TIMEZONE =====
if (!empty($_GET['tz'])) {
    try {
        $TARGET_TIMEZONE = new DateTimeZone($_GET['tz']);
    } catch (Exception $e) {
        echo json_encode(["error" => "Invalid timezone: " . $_GET['tz']]);
        exit;
    }
    $timezoneLabel = $_GET['tz'];
} elseif (!empty($_GET['country'])) {
    $country = $_GET['country'];
    if (!isset($countryToTimezone[$country])) {
        echo json_encode(["error" => "Unknown country: $country."]);
        exit;
    }
    $timezoneLabel = $countryToTimezone[$country];
    $TARGET_TIMEZONE = new DateTimeZone($timezoneLabel);
} else {
    $TARGET_TIMEZONE = new DateTimeZone('Africa/Lagos');
    $timezoneLabel = 'Africa/Lagos';
}

// ===== DATE RANGE =====
$START_DATE = $_GET['start'] ?? "2025-09-15";
$END_DATE   = $_GET['end'] ?? "2025-09-19";

$url = "https://www.threads.com/graphql/query";

// ===== LOAD EXISTING DATA =====
$existingData = [];
if (file_exists($OUTPUT_FILE)) {
    $jsonContent = file_get_contents($OUTPUT_FILE);
    $existingData = json_decode($jsonContent, true);
    if (!is_array($existingData)) $existingData = [];
}

// ---------- Helper functions ----------
function isDateFullyScraped(array $data, string $targetDate): bool {
    $foundTarget = false;
    $foundOlder  = false;
    foreach ($data as $item) {
        if (!isset($item['date'])) continue;
        if ($item['date'] === $targetDate) $foundTarget = true;
        elseif ($foundTarget && $item['date'] < $targetDate) { 
            $foundOlder = true; 
            break; 
        }
    }
    return ($foundTarget && $foundOlder);
}

function fetchThreads($url, $headers, $afterCursor = null) {
    $body = buildBody($afterCursor);
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST           => true,
        CURLOPT_HTTPHEADER     => $headers,
        CURLOPT_POSTFIELDS     => $body,
    ]);
    $result = curl_exec($ch);
    $error  = curl_error($ch);
    curl_close($ch);

    // ===== DEBUG: SAVE RAW RESPONSE =====
    $debugFile = __DIR__ . '/last_raw_response.json';
    file_put_contents($debugFile, "==== REQUEST BODY ====\n" . $body . "\n\n==== RESPONSE ====\n" . $result);

    if ($error) {
        return ['error' => $error];
    }

    return json_decode($result, true);
}

function getPostsForRange(array $data, string $startDate, string $endDate): array {
    $results = [];
    foreach ($data as $item) {
        if (!isset($item['date'])) continue;
        if ($item['date'] <= $endDate && $item['date'] >= $startDate) {
            $results[] = $item;
        }
    }
    return $results;
}

function getResumeCursor(array $data) {
    if (empty($data)) return null;
    $lastPost = end($data);
    return $lastPost['pagination'] ?? null;
}

function scrapeForwardForNewest(&$data, $url, $headers, $outputFile) {
    if (empty($data)) {
        return ['added' => 0]; // Nothing to compare with
    }

    $originalCount = count($data); // For tracking how many new posts we add

    // Get the first (newest) post in existing data
    $firstPost = reset($data); // since sorted newest → oldest
    $currentNewestDate = $firstPost['date'];
    $currentNewestTime = $firstPost['time'];
    $currentNewestUTC = strtotime($currentNewestDate . ' ' . $currentNewestTime);

    $afterCursor = null; // start from newest
    $foundNewer = false;
    $olderThanBoundary = 0;

    while (true) {
        $response = fetchThreads($url, $headers, $afterCursor);
        if (isset($response['error'])) {
            return ['error' => $response['error']];
        }

        $edges = $response['data']['mediaData']['edges'] ?? [];
        if (empty($edges)) break;

        foreach ($edges as $edge) {
            $items = $edge['node']['thread_items'] ?? [];
            foreach ($items as $item) {
                $post = $item['post'] ?? null;
                if (!$post) continue;

                $caption   = $post['caption']['text'] ?? '';
                $timestamp = (int)($post['taken_at'] ?? 0);
                if (!$timestamp) continue;

                // Always store in UTC
                $utc = new DateTime('@' . $timestamp);
                $utc->setTimezone(new DateTimeZone('UTC'));
                $postDate = $utc->format('Y-m-d');
                $postTime = $utc->format('H:i:s');
                $postUTC  = strtotime($postDate . ' ' . $postTime);

                $postId = $post['id'] ?? null;
                if (!$postId) continue;

                // If post is strictly newer than our current newest, add it
                if ($postUTC > $currentNewestUTC) {
                    $foundNewer = true;
                    $data[] = [
                        'id'      => $postId,
                        'nr'      => 0, // will fix numbering later
                        'caption' => $caption,
                        'date'    => $postDate,
                        'time'    => $postTime
                    ];
                } elseif ($foundNewer) {
                    // Count posts older than our boundary after finding new ones
                    $olderThanBoundary++;
                }
            }
        }

        // Stop once we have 5 older posts after the newest batch
       if ($foundNewer && $olderThanBoundary >= 5) {
    break;
}

        $pageInfo  = $response['data']['mediaData']['page_info'] ?? [];
        $endCursor = $pageInfo['end_cursor'] ?? null;
        if (empty($pageInfo['has_next_page']) || empty($endCursor)) break;

        $afterCursor = $endCursor;
    }

    // Sort newest → oldest
    usort($data, function($a, $b) {
        $dateCompare = strcmp($b['date'], $a['date']);
        if ($dateCompare !== 0) return $dateCompare;
        return strcmp($b['time'], $a['time']);
    });

    // Deduplicate
    $unique = [];
    $cleaned = [];
    foreach ($data as $post) {
        if (!isset($post['id'])) continue;
        if (!isset($unique[$post['id']])) {
            $unique[$post['id']] = true;
            $cleaned[] = $post;
        }
    }

    // Renumber newest → oldest
    $nr = 1;
    foreach ($cleaned as &$p) {
        $p['nr'] = $nr++;
    }
    unset($p);

    // Save to data.txt
    file_put_contents($outputFile, json_encode($cleaned, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
    $data = $cleaned;

    // Return how many posts were added
    return [
        'added' => count($cleaned) - $originalCount
    ];
}

// --- Scrape for a single date ---
function scrapeForDate(&$data, $targetDate, $url, $headers, $outputFile, &$afterCursor, &$existingCount) {
    global $TARGET_TIMEZONE; // Access timezone

    $index = count($data);
    $nr = ($index > 0 ? (int)($data[$index-1]['nr'] ?? $index) : 0) + 1;
    $foundTarget = false;
    $foundOlder = false;
    $shouldSkipFirstPinned = ($afterCursor === null && empty($data));
    $skippedFirst = false;
    $stopAfterPage = false;

    while (true) {
    $response = fetchThreads($url, $headers, $afterCursor);
    if (isset($response['error'])) return ['error' => $response['error']];

    $edges = $response['data']['mediaData']['edges'] ?? [];
    if (empty($edges)) break;

    $olderPostsCount = 0; // count posts older than target date

    foreach ($edges as $edge) {
        $items = $edge['node']['thread_items'] ?? [];
        foreach ($items as $item) {
            $post = $item['post'] ?? null;
            if (!$post) continue;

            if ($shouldSkipFirstPinned && !$skippedFirst) {
                $skippedFirst = true;
                continue;
            }

            $caption   = $post['caption']['text'] ?? '';
            $timestamp = (int)($post['taken_at'] ?? 0);
            if (!$timestamp) continue;

// Always save in UTC
$utc = new DateTime('@' . $timestamp);
$utc->setTimezone(new DateTimeZone('UTC')); 
$postDate = $utc->format('Y-m-d');
$postTime = $utc->format('H:i:s');

            // Add to array
            $postId = $post['id'] ?? null;
            $data[$index] = [
                'id'      => $postId,      // <-- Add this
                'nr'      => $nr,
                'caption' => $caption,
                'date'    => $postDate,
                'time'    => $postTime
            ];
            $index++;
            $nr++;

            // Logic for target date and older posts
            if ($postDate === $targetDate) {
                $foundTarget = true;
            } elseif ($postDate < $targetDate && $foundTarget) {
                $olderPostsCount++;
            }
        }
    }

    // After finishing the current page:
    $pageInfo  = $response['data']['mediaData']['page_info'] ?? [];
    $endCursor = $pageInfo['end_cursor'] ?? null;

    // STOP only if we have 5 or more older posts
    if ($olderPostsCount >= 5) {
        if (!empty($endCursor) && $index > 0) {
            $data[$index - 1]['pagination'] = $endCursor;
        }

        // Sort newest first
        usort($data, function($a, $b) {
            $dateCompare = strcmp($b['date'], $a['date']);
            if ($dateCompare !== 0) return $dateCompare;
            return strcmp($b['time'], $a['time']);
        });

// --- REMOVE DUPLICATES BEFORE SAVING ---
// --- REMOVE DUPLICATES BEFORE SAVING ---
$unique = [];
$cleanedData = [];

foreach ($data as $post) {
    if (!isset($post['id'])) continue; // Skip if no ID (shouldn't happen)
    $key = $post['id']; // Guaranteed unique per Threads post
    if (!isset($unique[$key])) {
        $unique[$key] = true;
        $cleanedData[] = $post;
    }
}

// Sort newest → oldest
usort($cleanedData, function($a, $b) {
    $dateCompare = strcmp($b['date'], $a['date']);
    if ($dateCompare !== 0) return $dateCompare;
    return strcmp($b['time'], $a['time']);
});

// Save clean results
file_put_contents($outputFile, json_encode($cleanedData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));


        return [
            'status' => 'scraped',
            'added'  => $index - $existingCount,
            'older_posts_count' => $olderPostsCount
        ];
    }

    // Otherwise keep scraping deeper
    if (empty($pageInfo['has_next_page']) || empty($endCursor)) break;
    $afterCursor = $endCursor;
}


// ✅ Also sort before final save
usort($data, function($a, $b) {
    $dateCompare = strcmp($b['date'], $a['date']); 
    if ($dateCompare !== 0) return $dateCompare;
    return strcmp($b['time'], $a['time']);
});

// --- REMOVE DUPLICATES BEFORE SAVING ---
$unique = [];
$cleanedData = [];

foreach ($data as $post) {
    if (!isset($post['id'])) continue; // Skip if no ID (shouldn't happen)
    $key = $post['id']; // Guaranteed unique per Threads post
    if (!isset($unique[$key])) {
        $unique[$key] = true;
        $cleanedData[] = $post;
    }
}

// Sort newest → oldest
usort($cleanedData, function($a, $b) {
    $dateCompare = strcmp($b['date'], $a['date']);
    if ($dateCompare !== 0) return $dateCompare;
    return strcmp($b['time'], $a['time']);
});

// Save clean results
file_put_contents($outputFile, json_encode($cleanedData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));

return [
    'status' => 'done',
    'added'  => $index - $existingCount
];

}

// -------------------- MAIN PROCESS --------------------
$dates = [];
$curr = strtotime($END_DATE);
$start = strtotime($START_DATE);
while ($curr >= $start) {
    $dates[] = date('Y-m-d', $curr);
    $curr = strtotime('-1 day', $curr);
}

$data = $existingData;
$afterCursor = getResumeCursor($data);
$neededScraping = false;

// === PREVENT INFINITE FORWARD SCRAPING INTO FUTURE ===
$currentUtc = new DateTime('now', new DateTimeZone('UTC'));

if (!empty($existingData)) {
    $firstPost = reset($existingData); // newest post
    $lastPostDateTime = DateTime::createFromFormat(
        'Y-m-d H:i:s',
        $firstPost['date'] . ' ' . $firstPost['time'],
        new DateTimeZone('UTC')
    );

    // Check if END_DATE is in the future (compared to current UTC)
    $endDateTime = DateTime::createFromFormat(
        'Y-m-d H:i:s',
        $END_DATE . ' 23:59:59',
        new DateTimeZone('UTC')
    );

    if ($endDateTime > $currentUtc) {
        // If our newest post is very recent (less than 1 hour old)
        $minutesDiff = ($currentUtc->getTimestamp() - $lastPostDateTime->getTimestamp()) / 60;

        if ($minutesDiff < 60) {
            // 🚨 Only ONE forward scrape attempt
            $forwardResult = scrapeForwardForNewest($data, $url, $headers, $OUTPUT_FILE);

            if (empty($forwardResult['added'])) {
                // No newer posts found → stop immediately
                $neededScraping = false;
            }
        } else {
            // Do NOT attempt to scrape forward at all
            $neededScraping = false;
        }
    }
}

/* 
-------------------------------------------------
PLACE THIS NEW BLOCK *HERE*, just before the date scraping loop
-------------------------------------------------
*/
$currentUtc = new DateTime('now', new DateTimeZone('UTC'));
$endDateUtc = new DateTime($END_DATE . ' 00:00:00', new DateTimeZone('UTC'));

if ($currentUtc > $endDateUtc) {
    // ✅ A new UTC day has started → scrape forward to ensure last day is complete
    scrapeForwardForNewest($data, $url, $headers, $OUTPUT_FILE);
}

/* 
-------------------------------------------------
THEN your main scraping loop begins
-------------------------------------------------
*/
foreach ($dates as $dateToCheck) {
    if (isDateFullyScraped($data, $dateToCheck)) {
        continue;
    }

    $neededScraping = true;
    $existingCount = count($data);
    $result = scrapeForDate($data, $dateToCheck, $url, $headers, $OUTPUT_FILE, $afterCursor, $existingCount);
    if (isset($result['error'])) {
        echo json_encode($result);
        exit;
    }
}
// -------------------- FINAL RESPONSE --------------------
// ---- Convert UTC data.txt timestamps to target country timezone for output ----


// === FINAL NUMBERING ===
// Sort newest → oldest
usort($data, function($a, $b) {
    $dateCompare = strcmp($b['date'], $a['date']);
    if ($dateCompare !== 0) return $dateCompare;
    return strcmp($b['time'], $a['time']);
});

// Reassign nr sequentially
$nr = 1;
foreach ($data as &$post) {
    $post['nr'] = $nr++;
}
unset($post);

// Save fixed results to data.txt
file_put_contents($OUTPUT_FILE, json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));



// --- FINAL DEDUPLICATION BEFORE OUTPUT ---
$unique = [];
$finalClean = [];

foreach ($data as $post) {
    if (!isset($post['id'])) continue;
    $key = $post['id']; // unique identifier
    if (!isset($unique[$key])) {
        $unique[$key] = true;
        $finalClean[] = $post;
    }
}
$data = $finalClean;

// === FINAL NUMBERING ===
usort($data, function($a, $b) {
    $dateCompare = strcmp($b['date'], $a['date']);
    if ($dateCompare !== 0) return $dateCompare;
    return strcmp($b['time'], $a['time']);
});

$nr = 1;
foreach ($data as &$post) {
    $post['nr'] = $nr++;
}
unset($post);

// Save corrected data.txt
file_put_contents($OUTPUT_FILE, json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));

// ---- Convert UTC timestamps to target timezone for final display ----
foreach ($data as &$post) {
    if (!isset($post['date']) || !isset($post['time'])) continue;
    $utcDateTime = new DateTime($post['date'] . ' ' . $post['time'], new DateTimeZone('UTC'));
    $utcDateTime->setTimezone($TARGET_TIMEZONE);
    $post['date'] = $utcDateTime->format('Y-m-d');
    $post['time'] = $utcDateTime->format('H:i:s');
}
unset($post);

// Now filter by start and end date in target timezone
$finalResults = getPostsForRange($data, $START_DATE, $END_DATE);

echo json_encode([
    'status'          => $neededScraping ? 'scraped' : 'cached',
    'folder'          => $folder,
    'timezone_used'   => $timezoneLabel,
    'message'         => $neededScraping
        ? "Scraping completed for missing dates between $START_DATE and $END_DATE."
        : "All dates between $START_DATE and $END_DATE were already cached.",
    'total_captions'  => count($finalResults),
    'posts'           => $finalResults,
    'saved_to'        => $OUTPUT_FILE
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);