<?php
declare(strict_types=1);

namespace App\Controllers;

use App\Core\Controller;
use App\Core\Database;

final class AdminJobsController extends Controller
{
    private function ensureTable($db): void
    {
        $st = $db->query("SELECT COUNT(*) FROM information_schema.tables WHERE table_schema=DATABASE() AND table_name='jobs'");
        if ((int)$st->fetchColumn() <= 0) throw new \RuntimeException("jobs table missing");
    }

    public function index(): void
    {
        require_admin_area();
        $db = Database::getInstance();
        $this->ensureTable($db);

        $status = trim((string)($_GET['status'] ?? ''));
        $q = trim((string)($_GET['q'] ?? ''));

        $where=[]; $params=[];
        if ($status !== '') { $where[]="status=:s"; $params[':s']=$status; }
        if ($q !== '') { $where[]="(job_key LIKE :q OR payload_json LIKE :q OR result_text LIKE :q)"; $params[':q']='%'.$q.'%'; }

        $sql="SELECT * FROM jobs";
        if($where) $sql.=" WHERE ".implode(" AND ",$where);
        $sql.=" ORDER BY id DESC LIMIT 400";

        $st=$db->prepare($sql);
        $st->execute($params);
        $rows=$st->fetchAll()?:[];

        $kpi=['queued'=>0,'running'=>0,'done'=>0,'failed'=>0,'all'=>0];
        try{
            $kpi['all']=(int)$db->query("SELECT COUNT(*) FROM jobs")->fetchColumn();
            foreach(['queued','running','done','failed'] as $s){
                $x=$db->prepare("SELECT COUNT(*) FROM jobs WHERE status=:s");
                $x->execute([':s'=>$s]);
                $kpi[$s]=(int)$x->fetchColumn();
            }
        }catch(\Throwable $e){}

        $this->view('admin/jobs/index', compact('rows','status','q','kpi'));
    }

    public function enqueue(): void
    {
        require_admin_area();
        $db=Database::getInstance();
        $this->ensureTable($db);

        if(($_SERVER['REQUEST_METHOD']??'GET')!=='POST'){ http_response_code(405); return; }

        $key=trim((string)($_POST['job_key']??''));
        $payload=trim((string)($_POST['payload_json']??''));
        $runAfter=trim((string)($_POST['run_after']??''));

        if($key===''){
            if(function_exists('flash_set')) flash_set('danger','Missing job_key');
            header('Location: '.base_path('admin/jobs')); exit;
        }

        $db->prepare("INSERT INTO jobs(job_key,payload_json,status,run_after) VALUES(:k,:p,'queued',:ra)")
           ->execute([':k'=>$key, ':p'=>($payload!==''?$payload:null), ':ra'=>($runAfter!==''?$runAfter:null)]);

        if(function_exists('flash_set')) flash_set('success','Job queued');
        header('Location: '.base_path('admin/jobs'));
        exit;
    }

    public function delete(): void
    {
        require_admin_area();
        $db=Database::getInstance();
        $this->ensureTable($db);

        $id=(int)($_GET['id']??0);
        if($id>0){
            $db->prepare("DELETE FROM jobs WHERE id=:id")->execute([':id'=>$id]);
            if(function_exists('flash_set')) flash_set('success','Deleted');
        }
        header('Location: '.base_path('admin/jobs'));
        exit;
    }

    public function runWorker(): void
    {
        require_admin_area();

        $cli = BASE_PATH . '/admin/cli/run_jobs.php';
        $out='';
        $ok=false;

        if (is_file($cli)) {
            $out = (string)shell_exec('php '.escapeshellarg($cli).' 2>&1');
            $ok=true;
        }

        if (session_status() !== PHP_SESSION_ACTIVE) session_start();
        $_SESSION['_jobs_last_output'] = mb_substr($out, 0, 4000);

        if(function_exists('flash_set')){
            flash_set($ok?'success':'danger', $ok?'Worker executed':'run_jobs.php not found');
        }

        header('Location: '.base_path('admin/jobs'));
        exit;
    }

    public function output(): void
    {
        require_admin_area();
        if (session_status() !== PHP_SESSION_ACTIVE) session_start();
        header('Content-Type: text/plain; charset=utf-8');
        echo (string)($_SESSION['_jobs_last_output'] ?? '');
    }
}
