<?php
declare(strict_types=1);
// worker_a3.php - işleme fonksiyonları (runner burayı require eder)

require __DIR__ . '/db.php';
require __DIR__ . '/config.php';
require __DIR__ . '/a3_lib.php';

function a3_items_total(): int {
  // a3_lib.php içindeki global $items
  global $items;
  return is_array($items) ? count($items) : 0;
}

function run_job(array $job): void {
  global $pdo, $GOOGLE_AUTH_JSON, $A3_CONCURRENCY, $A3_CONNECT_TIMEOUT, $A3_TOTAL_TIMEOUT, $A3_COOKIE_FILE, $A3_MAX_RETRIES, $A3_RETRY_WAITS, $A3_MAX_WAIT;

  $job_id = (int)$job['id'];
  $params = json_decode((string)$job['params_json'], true);
  if (!is_array($params)) throw new RuntimeException("params_json bozuk");

  // running
  $pdo->prepare("UPDATE a3_jobs SET status='running', started_at=NOW(), last_error=NULL WHERE id=?")->execute([$job_id]);

  $mode = (string)($params['mode'] ?? '');

  // replay: eski sonuçları sadece sheet'e bas
  if ($mode === 'replay') {
    $cell = (string)($params['c'] ?? 'H6');
    $spreadsheetId = a3_spreadsheet_id((string)($params['g'] ?? ''));

    $source_id = (int)($params['source_job_id'] ?? 0);
    if ($source_id <= 0) throw new RuntimeException("source_job_id eksik");

    $st2 = $pdo->prepare("SELECT result_json FROM a3_jobs WHERE id=? AND status='done'");
    $st2->execute([$source_id]);
    $src = $st2->fetch(PDO::FETCH_ASSOC);
    if (!$src || empty($src['result_json'])) throw new RuntimeException("Kaynak job sonucu bulunamadı");

    $srcRes = json_decode((string)$src['result_json'], true);
    if (!is_array($srcRes) || empty($srcRes['results'])) throw new RuntimeException("Kaynak result_json bozuk");

    $write = a3_write_results_to_sheet($srcRes['results'], $cell, $spreadsheetId, $GOOGLE_AUTH_JSON);

    $pdo->prepare("UPDATE a3_jobs
      SET status='done', finished_at=NOW(), result_json=?, sheet_ok=?, sheet_error=?, progress=?, total=?
      WHERE id=?")->execute([
        json_encode(["replayed_from"=>$source_id, "results"=>$srcRes["results"], "sheet_ok"=>!empty($write["sheet_ok"]), "sheet_error"=>$write["sheet_error"] ?? null], JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES),
        $write['sheet_ok'] ? 1 : 0,
        $write['sheet_error'],
        (int)($write['count'] ?? 0),
        (int)($write['total'] ?? 0),
        $job_id
      ]);
    return;
  }

  // normal fetch+write (run_a3_job zaten sheet'e yazar)
  $cfg = [
    "google_auth_json" => $GOOGLE_AUTH_JSON,
    "spreadsheet_id"   => a3_spreadsheet_id((string)($params['g'] ?? '')),
    "concurrency"      => (int)$A3_CONCURRENCY,
    "connect_timeout"  => (int)$A3_CONNECT_TIMEOUT,
    "total_timeout"    => (int)$A3_TOTAL_TIMEOUT,
    "cookie_file"      => (string)$A3_COOKIE_FILE,
    "max_retries"      => (int)$A3_MAX_RETRIES,
    "retry_waits"      => $A3_RETRY_WAITS,
    "max_wait"         => (int)$A3_MAX_WAIT,
  ];

  $total = a3_items_total();
  if ($total > 0) {
    $pdo->prepare("UPDATE a3_jobs SET total=? WHERE id=?")->execute([$total, $job_id]);
  }

  $cell = (string)($params['c'] ?? 'H6');
  $spreadsheetId = a3_spreadsheet_id((string)($params['g'] ?? ''));
  $sheetBuffer = [];
  $lastFlush = microtime(true);

  $res = run_a3_job($params, $cfg, function(int $done, int $total, array $meta = null) use ($pdo, $job_id, &$sheetBuffer, &$lastFlush, $cell, $spreadsheetId) {
    global $GOOGLE_AUTH_JSON, $SHEET_WRITE_DURING_RUN, $SHEET_FLUSH_EVERY, $SHEET_FLUSH_SECONDS;

    $last_b = $meta['b'] ?? null;
    $last_g = $meta['g'] ?? null;
    $pdo->prepare("UPDATE a3_jobs SET progress=?, total=?, last_b=?, last_g=? WHERE id=?")
        ->execute([$done, $total, $last_b, $last_g, $job_id]);

    // Uzun süren / çok retry alan işlerde: başarılı sonuçları beklemeden sheet'e yaz (buffer ile)
    if (!empty($SHEET_WRITE_DURING_RUN) && !empty($meta) && !empty($meta['ok']) && isset($meta['ihh_verisi'])) {
      $sheetBuffer[] = ["b" => $meta["b"], "ihh_verisi" => $meta["ihh_verisi"]];

      $now = microtime(true);
      $shouldFlushByCount = (is_int($SHEET_FLUSH_EVERY) && $SHEET_FLUSH_EVERY > 0 && count($sheetBuffer) >= $SHEET_FLUSH_EVERY);
      $shouldFlushByTime  = (is_int($SHEET_FLUSH_SECONDS) && $SHEET_FLUSH_SECONDS > 0 && ($now - $lastFlush) >= $SHEET_FLUSH_SECONDS);

      if ($shouldFlushByCount || $shouldFlushByTime) {
        $w = a3_write_results_to_sheet($sheetBuffer, $cell, $spreadsheetId, $GOOGLE_AUTH_JSON);
        // sheet hatası olsa bile işi durdurma; sadece DB'ye not düş
        if (empty($w['sheet_ok'])) {
          $pdo->prepare("UPDATE a3_jobs SET sheet_ok=0, sheet_error=? WHERE id=?")
              ->execute([(string)($w['sheet_error'] ?? 'sheet write failed'), $job_id]);
        } else {
          $pdo->prepare("UPDATE a3_jobs SET sheet_ok=1, sheet_error=NULL WHERE id=?")
              ->execute([$job_id]);
        }
        $sheetBuffer = [];
        $lastFlush = $now;
      }
    }
  });

    // kalan buffer varsa flush et
  if (!empty($sheetBuffer)) {
    a3_write_results_to_sheet($sheetBuffer, $cell, $spreadsheetId, $GOOGLE_AUTH_JSON);
    $sheetBuffer = [];
  }

  $write = a3_write_results_to_sheet($res, $cell, $spreadsheetId, $GOOGLE_AUTH_JSON);

  $payload = [
    "results" => $res,
    "sheet_ok" => !empty($write['sheet_ok']),
    "sheet_error" => $write['sheet_error'] ?? null,
  ];

  $pdo->prepare("UPDATE a3_jobs
    SET status='done', finished_at=NOW(), result_json=?, sheet_ok=?, sheet_error=?, progress=?, total=?
    WHERE id=?")->execute([
      json_encode($payload, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES),
      !empty($write['sheet_ok']) ? 1 : 0,
      (string)($write['sheet_error'] ?? ''),
      count($res),
      count($res),
      $job_id
    ]);
}

function run_job_id(int $job_id): void {
  global $pdo;
  $st = $pdo->prepare("SELECT * FROM a3_jobs WHERE id=?");
  $st->execute([$job_id]);
  $job = $st->fetch(PDO::FETCH_ASSOC);
  if (!$job) throw new RuntimeException("job not found: ".$job_id);
  run_job($job);
}
