<?php
// header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json");

// Rate limiting (rudimentary example)
session_start();
$limit = 3; // max requests
$window = 1; // window in seconds

if (!isset($_SESSION['userid'])) {
    throw new Exception('Unauthorized');
}

try {

    if (isset($_POST['getImages'])) {
        // Fetching and validating inputs
        $imageUrl = $_POST['imageUrl'] ?? null;
        $credentials = $_POST['credentials'] ?? null;
        $count = isset($_POST['imagesCount']) ? intval($_POST['imagesCount']) : 1;

        // Input validation
        if (empty($imageUrl)) {
            http_response_code(400); // Bad Request
            echo json_encode([
                "error" => "Missing image URL.",
                "details" => $_POST
            ]);
            exit;
        }

        $validation = isSafeImageUrl($imageUrl);
        if (!$validation['status']) {
            http_response_code(400);
            echo json_encode(['error' => $validation['message']]);
            exit;
        }

        // Initialize cURL
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);

        // Set credentials if provided
        if (!empty($credentials)) {
            curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
            curl_setopt($ch, CURLOPT_USERPWD, $credentials);
        }

        $imageBuffers = [];
        for ($i = 0; $i < $count; $i++) {
            curl_setopt($ch, CURLOPT_URL, $imageUrl);

            $response = curl_exec($ch);

            if ($response === false) {
                $error_msg = curl_error($ch);
                $error_no = curl_errno($ch);

                http_response_code(500); // Internal Server Error
                echo json_encode([
                    "error" => "Error fetching image.",
                    "curl_error_no" => $error_no,
                    "curl_error_msg" => $error_msg
                ]);
                curl_close($ch);
                exit;
            }

            $imageBuffers[] = base64_encode($response);
        }

        curl_close($ch);

        // Successful response
        http_response_code(200); // OK
        echo json_encode([
            "success" => true,
            "images" => $imageBuffers,
            "count" => count($imageBuffers)
        ]);
        exit;
    }

    if (isset($_POST['singleImage'])) {
        $userName = isset($_POST['username']) ? $_POST['username'] : '';
        $password = isset($_POST['password']) ? $_POST['password'] : '';
        $imageUrl = isset($_POST['imageUrl']) ? $_POST['imageUrl'] : '';
        $validation = isSafeImageUrl($imageUrl);
        if (!$validation['status']) {
            http_response_code(400);
            echo json_encode(['error' => $validation['message']]);
            exit;
        }

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $imageUrl);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 40);
        curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC | CURLAUTH_DIGEST);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
           'Authorization: Basic ' . base64_encode($userName . ':' . $password)
        ));

        $header_response = curl_exec($ch);

        if ($header_response === false) {
            $error = curl_error($ch);
            http_response_code(500);
            echo json_encode(["error" => "Could not fetch image headers. Error: $error"]);
            exit;
        }

        $content_type = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
        if (strpos($content_type, 'image') === false) {
            $basicAuthMessage=getImageFromUrlUsingBasicAuth($imageUrl);
            if($basicAuthMessage['status']){
                    echo json_encode(["image" => base64_encode($header_response)]);
                    exit;
            }
            http_response_code(400);
            echo json_encode(["error" => "The URL does not point to an image. header response: $header_response"]);
            exit;
        }

        curl_close($ch);
        echo json_encode(["image" => base64_encode($header_response)]);
        exit;
    }
} catch (\Throwable $th) {
    http_response_code(500);
    echo json_encode(["error" => "Server error occurred in server.php"]);
    exit;
}

function isSafeImageUrl(string $imageUrl): array
{
    if (!filter_var($imageUrl, FILTER_VALIDATE_URL)) {
        return ['status' => false, 'message' => 'Invalid URL format.'];
    }

    $parsedUrl = parse_url($imageUrl);
    $scheme = strtolower($parsedUrl['scheme'] ?? '');
    if (!in_array($scheme, ['http', 'https'])) {
        return ['status' => false, 'message' => 'Only HTTP and HTTPS protocols are allowed.'];
    }

    $host = $parsedUrl['host'] ?? '';
    if (empty($host)) {
        return ['status' => false, 'message' => 'Invalid host in URL.'];
    }

    $ip = gethostbyname($host);
    if (
        filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false ||
        in_array($ip, ['127.0.0.1', '::1'])
    ) {
        return ['status' => false, 'message' => 'Access to private/internal IPs is not allowed.'];
    }

    return ['status' => true];
}

function getImageFromUrlUsingBasicAuth(string $imageUrl):array
{
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $imageUrl);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);
    curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);

    $BasicResponse = curl_exec($ch);
    if ($BasicResponse === false) {
        $error = curl_error($ch);
        curl_close($ch);
        return ['status' => false, 'message' => 'Could not fetch image headers.'];
    }

    $content_type = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
    if (strpos($content_type, 'image') === false) {
        curl_close($ch);
        return ['status' => false, 'message' => 'The URL does not point to an image.'];
    }

    curl_close($ch);
    // Return the single image as a base64 encoded string
    return ['status' => true, 'message' => json_encode(["image" => base64_encode($BasicResponse)])];
}