<?php
declare(strict_types=1);

$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
$allowed_origins = [
    'http://localhost:5173',
    'http://127.0.0.1:5173',
    'http://172.20.48.1:5173',
    'https://skizagroundsuite.com',
];

if ($origin && in_array($origin, $allowed_origins, true)) {
    header("Access-Control-Allow-Origin: $origin");
    header("Vary: Origin");
} else {
    header("Access-Control-Allow-Origin: https://skizagroundsuite.com");
    header("Vary: Origin");
}

header("Access-Control-Allow-Methods: POST, OPTIONS");
header("Access-Control-Allow-Headers: Authorization, Content-Type, X-Requested-With");
header("Access-Control-Max-Age: 86400");
header("Content-Type: application/json; charset=UTF-8");

if (($_SERVER['REQUEST_METHOD'] ?? '') === 'OPTIONS') {
    http_response_code(204);
    exit;
}

function respond(int $code, array $data): void {
    http_response_code($code);
    echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}

if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
    respond(405, ["status" => "error", "message" => "Only POST allowed"]);
}

require_once __DIR__ . "/vendor/autoload.php";
require_once __DIR__ . "/ocr_utils.php";
require_once __DIR__ . "/gemini_client.php";

$cred = __DIR__ . '/keys/natural-aria-420413-f3902aac9bf0.json';
if (!file_exists($cred)) {
    respond(500, ["status" => "error", "message" => "Missing Vision credential file"]);
}
putenv("GOOGLE_APPLICATION_CREDENTIALS={$cred}");

if (!isset($_FILES['file']) || !isset($_FILES['file']['error'])) {
    respond(400, ["status" => "error", "message" => "Upload an IEBC form image/PDF as 'file'."]);
}

if ($_FILES['file']['error'] !== UPLOAD_ERR_OK) {
    respond(400, ["status" => "error", "message" => "Upload error."]);
}

$ext = strtolower(pathinfo($_FILES['file']['name'] ?? '', PATHINFO_EXTENSION));
$allowed = ["jpg", "jpeg", "png", "webp", "pdf"];

if (!in_array($ext, $allowed, true)) {
    respond(400, ["status" => "error", "message" => "Only JPG/PNG/WEBP/PDF allowed."]);
}

$tmp  = $_FILES['file']['tmp_name'] ?? '';
$size = (int)($_FILES['file']['size'] ?? 0);

if ($tmp === '' || !file_exists($tmp)) {
    respond(400, ["status" => "error", "message" => "Missing uploaded temp file."]);
}

if ($size <= 0) {
    respond(400, ["status" => "error", "message" => "Uploaded file empty."]);
}

// MIME check (more reliable than extension)
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime  = $tmp ? finfo_file($finfo, $tmp) : '';
finfo_close($finfo);

$isPdf = ($mime === 'application/pdf') || ($ext === 'pdf');

if ($isPdf && !getenv('OCR_GCS_BUCKET')) {
    respond(500, [
        "status" => "error",
        "message" => "PDF OCR requires OCR_GCS_BUCKET env var to be set to your GCS bucket name."
    ]);
}

try {
    $rawText = ocr_file($tmp, "vision", $isPdf);
    if (trim($rawText) === "") {
        throw new RuntimeException("Empty OCR text.");
    }
} catch (Throwable $e) {
    respond(500, [
        "status"  => "error",
        "message" => "OCR failed: " . $e->getMessage(),
    ]);
}

$prompt = <<<PROMPT
You are parsing an IEBC election results form (e.g., Form 34A, 35A, 36A) from OCR text.

Return JSON ONLY in this exact structure:

{
  "entries": [
    { "candidate_name": "", "votes": 0 }
  ],
  "rejected_votes": 0,
  "registered_voters": 0,
  "total_valid_votes": 0,
  "presiding_officer": "",
  "notes": ""
}

Rules:
- Output must be STRICT valid JSON (RFC 8259).
- Use double quotes. No markdown fences. No extra text.
- Do NOT invent candidates.

<ocr>
$rawText
</ocr>
PROMPT;

// IMPORTANT: gemini_call_json() currently exits on error.
// If you adopt the “throw instead of exit” change, keep try/catch here.
// Otherwise, you can call directly without try/catch.
$parsed = gemini_call_json($prompt, [
    "max_output_tokens" => 900,
    "temperature"       => 0.1,
]);

$entries = $parsed["entries"] ?? [];
if (!is_array($entries)) $entries = [];

$candidates = [];
$idx = 1;

foreach ($entries as $e) {
    if (!is_array($e)) continue;

    $name = trim((string)($e["candidate_name"] ?? ""));
    if ($name === "") continue;

    $votesRaw = (string)($e["votes"] ?? "0");
    $votesRaw = preg_replace('/[^\d\-]/', '', $votesRaw ?? '') ?? '0';
    $votes = (int)$votesRaw;
    if ($votes < 0) $votes = 0;

    $candidates[] = [
        "id"    => $idx,
        "name"  => $name,
        "votes" => $votes,
    ];
    $idx++;
}

$rejectedVotes   = (int)($parsed["rejected_votes"] ?? 0);
$totalValidVotes = (int)($parsed["total_valid_votes"] ?? 0);

$registeredVoters = $parsed["registered_voters"] ?? 0;
$registeredVoters = is_numeric($registeredVoters) ? (int)$registeredVoters : 0;

$presidingOfficer = trim((string)($parsed["presiding_officer"] ?? ""));
$notes            = trim((string)($parsed["notes"] ?? ""));

$sumVotes = 0;
foreach ($candidates as $c) $sumVotes += (int)$c["votes"];

if ($totalValidVotes > 0 && $sumVotes !== $totalValidVotes) {
    $extra = "Warning: sum(candidate votes)={$sumVotes} != total_valid_votes={$totalValidVotes}. Possible OCR/table mismatch.";
    $notes = $notes !== "" ? ($notes . " | " . $extra) : $extra;
}

respond(200, [
    "status" => "ok",
    "data"   => [
        "candidates"         => $candidates,
        "rejected_votes"     => $rejectedVotes,
        "registered_voters"  => $registeredVoters,
        "presiding_officer"  => $presidingOfficer !== "" ? $presidingOfficer : null,
        "notes"              => $notes !== "" ? $notes : null,
        "total_valid_votes"  => $totalValidVotes,
        "is_pdf"             => $isPdf,
    ],
]);