<?php
// app/controllers/jobs.php

declare(strict_types=1);

use ScMedia\Http\Router;

final class JobsController extends BaseController {
  public static function register(Router $router, Container $container): void {
    $self = new self($container);
    $router->add('GET', '/api/jobs/status', fn() => $self->status());
    $router->add('GET', '/api/jobs/recent', fn() => $self->recent());
    $router->add('GET', '/api/jobs/get', fn() => $self->getJob());
    $router->add('POST', '/api/jobs/cancel', fn() => $self->cancel());
    $router->add('POST', '/api/jobs/watchdog', fn() => $self->watchdog());
  }

  private function status(): void {
    $db = $this->db();
    $settings = $this->settings();

    $running = $db->fetchOne("SELECT COUNT(*) AS c FROM jobs WHERE status='running'");
    $queued = $db->fetchOne("SELECT COUNT(*) AS c FROM jobs WHERE status='queued'");
    $errors = $db->fetchOne("SELECT COUNT(*) AS c FROM jobs WHERE status='error'");
    $active = $db->fetchOne("
      SELECT id, type, title, status, progress_current, progress_total, progress_pct, cancel_requested
      FROM jobs
      WHERE status='running'
      ORDER BY started_at ASC
      LIMIT 1
    ");
    $activeList = $db->fetchAll("
      SELECT id, type, title, status, progress_current, progress_total, progress_pct, cancel_requested, started_at
      FROM jobs
      WHERE status='running'
      ORDER BY started_at ASC
      LIMIT 50
    ");

    $bg = $settings->getAll()['background'] ?? [];

    json_response(['ok' => true, 'data' => [
      'paused' => !empty($bg['paused']),
      'running' => (int)($running['c'] ?? 0),
      'queued' => (int)($queued['c'] ?? 0),
      'errors' => (int)($errors['c'] ?? 0),
      'active' => $active ? [
        'id' => (int)$active['id'],
        'type' => (string)$active['type'],
        'title' => (string)$active['title'],
        'status' => (string)$active['status'],
        'progress' => (int)($active['progress_current'] ?? 0),
        'progress_total' => (int)($active['progress_total'] ?? 0),
        'progress_pct' => (int)($active['progress_pct'] ?? 0),
        'cancel_requested' => !empty($active['cancel_requested']),
      ] : null,
      'active_list' => array_map(function($row) {
        return [
          'id' => (int)$row['id'],
          'type' => (string)$row['type'],
          'title' => (string)$row['title'],
          'status' => (string)$row['status'],
          'progress' => (int)($row['progress_current'] ?? 0),
          'progress_total' => (int)($row['progress_total'] ?? 0),
          'progress_pct' => (int)($row['progress_pct'] ?? 0),
          'cancel_requested' => !empty($row['cancel_requested']),
          'started_at' => $row['started_at'] ?? null,
        ];
      }, $activeList),
    ]]);
  }

  private function recent(): void {
    $db = $this->db();
    $limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 20;
    if ($limit < 1) $limit = 20;
    if ($limit > 200) $limit = 200;
    $rows = $db->fetchAll("
      SELECT id, type, title, status, error_message, finished_at
      FROM jobs
      WHERE status IN ('done','error','canceled')
      ORDER BY finished_at DESC
      LIMIT {$limit}
    ");
    $out = [];
    foreach ($rows as $r) {
      $out[] = [
        'id' => (int)$r['id'],
        'type' => (string)$r['type'],
        'title' => (string)$r['title'],
        'status' => (string)$r['status'],
        'error_message' => $r['error_message'] ?? null,
        'finished_at' => $r['finished_at'] ?? null,
      ];
    }
    json_response(['ok' => true, 'data' => ['items' => $out]]);
  }

  private function getJob(): void {
    $db = $this->db();
    $id = (int)($_GET['id'] ?? 0);
    if ($id <= 0) {
      json_response(['ok' => false, 'error' => 'id required'], 400);
    }

    $job = $db->fetchOne("SELECT * FROM jobs WHERE id=:id", [':id' => $id]);
    if (!$job) {
      json_response(['ok' => false, 'error' => 'job not found'], 404);
    }

    $rows = $db->fetchAll("
      SELECT ts, level, message
      FROM job_logs
      WHERE job_id=:id
      ORDER BY id ASC
      LIMIT 5000
    ", [':id' => $id]);

    $lines = [];
    foreach ($rows as $r) {
      $ts = (string)($r['ts'] ?? '');
      $lvl = (string)($r['level'] ?? 'info');
      $msg = (string)($r['message'] ?? '');
      $lines[] = "{$ts} [{$lvl}] {$msg}";
    }

    $out = [
      'id' => (int)$job['id'],
      'type' => (string)$job['type'],
      'title' => (string)$job['title'],
      'status' => (string)$job['status'],
      'cancel_requested' => !empty($job['cancel_requested']),
      'progress' => (int)($job['progress_current'] ?? 0),
      'progress_total' => (int)($job['progress_total'] ?? 0),
      'progress_pct' => (int)($job['progress_pct'] ?? 0),
      'error_message' => $job['error_message'] ?? null,
      'created_at' => $job['created_at'] ?? null,
      'started_at' => $job['started_at'] ?? null,
      'finished_at' => $job['finished_at'] ?? null,
      'last_heartbeat' => $job['last_heartbeat'] ?? null,
      'log_text' => implode("\n", $lines),
    ];

    json_response(['ok' => true, 'job' => $out]);
  }

  private function cancel(): void {
    /** @var \ScMedia\Services\JobsService $jobs */
    $jobs = $this->services()['jobs'];
    $body = read_json_body();
    $id = (int)($body['id'] ?? 0);
    if ($id <= 0) {
      json_response(['ok' => false, 'error' => 'id required'], 400);
    }
    $jobs->requestCancel($id);
    json_response(['ok' => true]);
  }

  private function watchdog(): void {
    /** @var \ScMedia\Services\JobsService $jobs */
    $jobs = $this->services()['jobs'];
    $body = read_json_body();
    $minutes = isset($body['minutes']) ? (int)$body['minutes'] : 10;
    $count = $jobs->markStalled($minutes);
    json_response(['ok' => true, 'data' => ['stalled_marked' => $count]]);
  }
}
