<?php
class JobController extends Controller
{
    public function index(Request $request): void
    {
        $this->view('jobs/index', [
            'title' => lang('admin.system_jobs'),
            'breadcrumbs' => [['label' => lang('admin.administration'), 'url' => '/admin/jobs'], ['label' => lang('admin.system_jobs')]],
        ]);
    }

    public function datatable(Request $request): void
    {
        $db = $this->db();
        $rows = $db->fetchAll("SELECT * FROM system_jobs ORDER BY id");
        $data = [];
        foreach ($rows as $r) {
            $statusBadge = match($r['last_run_status']) {
                'success' => '<span class="badge bg-success">Success</span>',
                'failed' => '<span class="badge bg-danger">Failed</span>',
                'partial' => '<span class="badge bg-warning">Partial</span>',
                default => '<span class="badge bg-secondary">Never Run</span>',
            };
            $actions = '<div class="btn-group btn-group-sm">';
            $actions .= '<button class="btn btn-outline-' . ($r['is_active'] ? 'warning' : 'success') . ' btn-toggle-job" data-id="' . $r['id'] . '">' . ($r['is_active'] ? '<i class="fas fa-pause"></i>' : '<i class="fas fa-play"></i>') . '</button>';
            $actions .= '<button class="btn btn-outline-primary btn-run-job" data-id="' . $r['id'] . '" title="Run Now"><i class="fas fa-bolt"></i></button>';
            $actions .= '<a href="/admin/jobs/' . $r['id'] . '/runs" class="btn btn-outline-info" title="History"><i class="fas fa-history"></i></a>';
            $actions .= '</div>';
            $data[] = [
                'code' => e($r['job_code']),
                'name' => e($r['job_name']),
                'type' => e($r['job_type']),
                'active' => $r['is_active'] ? '<span class="badge bg-success">Active</span>' : '<span class="badge bg-secondary">Disabled</span>',
                'last_run' => $r['last_run_at'] ? format_datetime($r['last_run_at']) : '-',
                'last_status' => $statusBadge,
                'runs' => number_format($r['run_count']),
                'actions' => $actions,
            ];
        }
        $this->json(['draw' => (int)$request->post('draw', 1), 'recordsTotal' => count($data), 'recordsFiltered' => count($data), 'data' => $data]);
    }

    public function toggle(Request $request): void
    {
        $id = (int)$request->routeParam('id');
        if (!CSRF::validate($request->csrfToken())) { $this->json(['success' => false, 'message' => 'Invalid CSRF'], 403); return; }
        $db = $this->db();
        $job = $db->fetchOne("SELECT id, is_active, job_code FROM system_jobs WHERE id = ?", [$id]);
        if (!$job) { $this->json(['success' => false, 'message' => 'Job not found'], 404); return; }
        $db->update('system_jobs', ['is_active' => $job['is_active'] ? 0 : 1, 'updated_at' => date('Y-m-d H:i:s')], 'id = ?', [$id]);
        $this->audit('update', 'system_jobs', $id, ($job['is_active'] ? 'Disabled' : 'Enabled') . ' job: ' . $job['job_code']);
        $this->json(['success' => true, 'message' => 'Job status toggled']);
    }

    public function run(Request $request): void
    {
        $id = (int)$request->routeParam('id');
        if (!CSRF::validate($request->csrfToken())) { $this->json(['success' => false, 'message' => 'Invalid CSRF'], 403); return; }
        $db = $this->db();
        $job = $db->fetchOne("SELECT * FROM system_jobs WHERE id = ?", [$id]);
        if (!$job) { $this->json(['success' => false, 'message' => 'Job not found'], 404); return; }

        $runId = $db->insert('system_job_runs', [
            'job_id' => $id,
            'started_at' => date('Y-m-d H:i:s'),
            'status' => 'running',
            'triggered_by' => 'manual',
            'triggered_by_user' => Auth::id(),
        ]);

        try {
            $procName = 'sp_' . str_replace('-', '_', $job['job_code']);
            if ($job['job_code'] === 'daily_maintenance') {
                $db->execute("CALL sp_daily_maintenance()");
            } elseif ($job['job_code'] === 'overdue_invoices') {
                $db->execute("CALL sp_mark_overdue_invoices()");
            } elseif ($job['job_code'] === 'overdue_installments') {
                $db->execute("CALL sp_mark_overdue_installments()");
            } elseif ($job['job_code'] === 'expire_cards') {
                $db->execute("CALL sp_expire_cards()");
            } elseif ($job['job_code'] === 'expire_carnets') {
                $db->execute("CALL sp_expire_carnets()");
            } elseif ($job['job_code'] === 'expire_guest_passes') {
                $db->execute("CALL sp_expire_guest_passes()");
            } elseif ($job['job_code'] === 'end_freezes') {
                $db->execute("CALL sp_end_expired_freezes()");
            } elseif ($job['job_code'] === 'end_suspensions') {
                $db->execute("CALL sp_end_expired_suspensions()");
            } elseif ($job['job_code'] === 'process_notifications') {
                $db->execute("CALL sp_process_notification_queue()");
            } elseif ($job['job_code'] === 'clean_sessions') {
                $db->execute("CALL sp_clean_expired_sessions()");
            } elseif ($job['job_code'] === 'expire_offers') {
                $db->execute("CALL sp_expire_special_offers()");
            } elseif ($job['job_code'] === 'waitlist_offers_expire') {
                $db->execute("CALL sp_expire_waiting_list_offers()");
            } else {
                $db->update('system_job_runs', ['status' => 'failed', 'completed_at' => date('Y-m-d H:i:s'), 'error_message' => 'No handler defined'], 'id = ?', [$runId]);
                $this->json(['success' => false, 'message' => 'No handler for this job']);
                return;
            }

            $db->update('system_job_runs', ['status' => 'success', 'completed_at' => date('Y-m-d H:i:s')], 'id = ?', [$runId]);
            $db->update('system_jobs', ['last_run_at' => date('Y-m-d H:i:s'), 'last_run_status' => 'success', 'run_count' => $job['run_count'] + 1], 'id = ?', [$id]);
            $this->audit('execute', 'system_jobs', $id, 'Manually executed job: ' . $job['job_code']);
            $this->json(['success' => true, 'message' => 'Job executed successfully']);
        } catch (\Exception $e) {
            $db->update('system_job_runs', ['status' => 'failed', 'completed_at' => date('Y-m-d H:i:s'), 'error_message' => $e->getMessage()], 'id = ?', [$runId]);
            $db->update('system_jobs', ['last_run_at' => date('Y-m-d H:i:s'), 'last_run_status' => 'failed', 'fail_count' => $job['fail_count'] + 1], 'id = ?', [$id]);
            $this->json(['success' => false, 'message' => 'Job failed: ' . $e->getMessage()]);
        }
    }

    public function runs(Request $request): void
    {
        $id = (int)$request->routeParam('id');
        $db = $this->db();
        $job = $db->fetchOne("SELECT * FROM system_jobs WHERE id = ?", [$id]);
        if (!$job) { $this->abort(404); return; }
        $runs = $db->fetchAll("SELECT * FROM system_job_runs WHERE job_id = ? ORDER BY started_at DESC LIMIT 100", [$id]);
        $this->view('jobs/runs', [
            'title' => 'Job Runs: ' . $job['job_name'],
            'breadcrumbs' => [['label' => lang('admin.administration'), 'url' => '/admin/jobs'], ['label' => lang('admin.system_jobs'), 'url' => '/admin/jobs'], ['label' => 'Runs']],
            'job' => $job, 'runs' => $runs,
        ]);
    }
}