<template>
  <section class="resource-page system-jobs-page">
    <div class="page-header compact-header">
      <div>
        <span class="eyebrow">OPERATIONS CONTROL</span>
        <h2>System Jobs</h2>
        <p>Monitor background workers and cancel stuck script execution jobs from one audited control surface.</p>
      </div>
      <div class="page-actions">
        <button class="ghost-button compact" type="button" @click="$emit('refresh')">
          <i class="mdi mdi-refresh" aria-hidden="true"></i>Refresh
        </button>
      </div>
    </div>

    <div class="system-job-metrics">
      <article>
        <span class="eyebrow">RUNNING</span>
        <strong>{{ runningCount }}</strong>
        <small>active job(s)</small>
      </article>
      <article>
        <span class="eyebrow">CANCELLABLE</span>
        <strong>{{ cancellableCount }}</strong>
        <small>script execution job(s)</small>
      </article>
      <article>
        <span class="eyebrow">BACKGROUND</span>
        <strong>{{ backgroundCount }}</strong>
        <small>managed worker(s)</small>
      </article>
      <article>
        <span class="eyebrow">AUDIT</span>
        <strong>{{ actions.length }}</strong>
        <small>recent action(s)</small>
      </article>
    </div>

    <ResourceTable
      class="system-jobs-table"
      :columns="jobColumns"
      :rows="pagedJobs"
      :total="filteredJobs.length"
      :search="filters.search"
      :page="filters.page"
      :page-count="pageCount"
      :page-size="filters.pageSize"
      :sort="filters.sort"
      :direction="filters.direction"
      search-placeholder="Search job, worker, category, status..."
      item-label="jobs"
      empty-text="No system jobs match the current filters."
      @update:search="filters.search = $event"
      @update:page="filters.page = $event"
      @update:pageSize="filters.pageSize = $event"
      @sort="setSort"
    >
      <template #toolbar-leading>
        <label class="table-density-select system-job-filter">
          <span>Type</span>
          <select v-model="filters.type">
            <option value="">All</option>
            <option value="execution">Execution</option>
            <option value="background">Background</option>
          </select>
        </label>
        <label class="table-density-select system-job-filter">
          <span>Status</span>
          <select v-model="filters.status">
            <option value="">Any</option>
            <option value="running">Running</option>
            <option value="queued">Queued</option>
            <option value="idle">Idle</option>
            <option value="failed">Failed</option>
            <option value="canceled">Canceled</option>
          </select>
        </label>
      </template>
      <template #cell-name="{ row }">
        <strong>{{ row.name }}</strong>
        <small>{{ row.description }}</small>
      </template>
      <template #cell-type="{ row }"><span :class="['status-pill', row.type]">{{ row.type }}</span></template>
      <template #cell-status="{ row }"><span :class="['status-pill', row.status]">{{ row.status }}</span></template>
      <template #cell-startedAt="{ row }">{{ shortDate(row.startedAt || row.createdAt || row.metadata?.lastRunAt) || '-' }}</template>
      <template #cell-hosts="{ row }">
        <span v-if="row.type === 'execution'">{{ row.runningHosts || 0 }} running / {{ row.hostCount || 0 }} total</span>
        <span v-else>{{ row.metadata?.lastSummary ? summaryText(row.metadata.lastSummary) : 'worker task' }}</span>
      </template>
      <template #cell-actions="{ row }">
        <div class="table-actions">
          <button v-if="row.canRunNow" class="ghost-button compact" type="button" :disabled="loading" @click="$emit('run', row.id)">
            <i class="mdi mdi-play-circle-outline" aria-hidden="true"></i>Run now
          </button>
          <button v-if="row.canCancel" class="ghost-button compact danger-text" type="button" :disabled="loading" @click="openCancel(row)">
            <i class="mdi mdi-cancel" aria-hidden="true"></i>Cancel
          </button>
          <span v-if="!row.canRunNow && !row.canCancel" class="status-pill neutral">view only</span>
        </div>
      </template>
    </ResourceTable>

    <article class="glass-panel system-job-audit">
      <div class="section-title">
        <div>
          <span class="eyebrow">AUDIT TRAIL</span>
          <h3>Job management actions</h3>
          <p>Every run-now and cancel operation is recorded with actor, status, message, and metadata.</p>
        </div>
      </div>
      <div class="data-table-wrap">
        <table class="data-table resource-table">
          <thead>
            <tr><th>Time</th><th>Action</th><th>Target</th><th>Status</th><th>Actor</th><th>Message</th></tr>
          </thead>
          <tbody>
            <tr v-for="action in actions.slice(0, 40)" :key="action.id">
              <td>{{ shortDate(action.createdAt) }}</td>
              <td><strong>{{ action.action }}</strong></td>
              <td><code>{{ action.targetId }}</code></td>
              <td><span :class="['status-pill', action.status]">{{ action.status }}</span></td>
              <td>{{ action.actorName || action.actorUserId || '-' }}</td>
              <td>{{ action.message || '-' }}</td>
            </tr>
          </tbody>
        </table>
        <div v-if="!actions.length" class="widget-empty">No job management actions have been recorded yet.</div>
      </div>
    </article>

    <BaseModal
      :open="Boolean(cancelTarget)"
      title="Cancel execution job"
      eyebrow="JOB MANAGEMENT"
      :description="cancelTarget ? `Cancel ${cancelTarget.name}. Running PowerShell processes will be signaled and queued hosts will be marked canceled.` : ''"
      @close="cancelTarget = null"
    >
      <form class="form-grid" @submit.prevent="submitCancel">
        <label class="full">
          <span>Reason</span>
          <textarea v-model="cancelReason" rows="3" placeholder="Stuck remoting session, bad target selection, operator requested stop..."></textarea>
        </label>
        <div class="form-actions modal-actions full">
          <button class="ghost-button" type="button" @click="cancelTarget = null">
            <i class="mdi mdi-close" aria-hidden="true"></i>Close
          </button>
          <button class="primary-action danger-action" type="submit">
            <i class="mdi mdi-cancel" aria-hidden="true"></i>Cancel job
          </button>
        </div>
      </form>
    </BaseModal>
  </section>
</template>

<script setup>
import { computed, reactive, ref, watch } from 'vue';
import BaseModal from '../components/ui/BaseModal.vue';
import ResourceTable from '../components/ui/ResourceTable.vue';

const props = defineProps({
  jobs: { type: Array, default: () => [] },
  actions: { type: Array, default: () => [] },
  loading: Boolean
});

const emit = defineEmits(['refresh', 'run', 'cancel']);

const filters = reactive({ search: '', type: '', status: '', page: 1, pageSize: 8, sort: 'status', direction: 'asc' });
const cancelTarget = ref(null);
const cancelReason = ref('');
const jobColumns = [
  { key: 'name', label: 'Job / Worker' },
  { key: 'type', label: 'Type' },
  { key: 'category', label: 'Category' },
  { key: 'status', label: 'Status' },
  { key: 'startedAt', label: 'Started / Last Run' },
  { key: 'hosts', label: 'Scope', sortable: false },
  { key: 'actions', label: 'Actions', sortable: false }
];

const filteredJobs = computed(() => {
  const term = filters.search.trim().toLowerCase();
  return props.jobs.filter((job) => {
    if (filters.type && job.type !== filters.type) return false;
    if (filters.status && job.status !== filters.status) return false;
    if (!term) return true;
    return [job.name, job.description, job.category, job.status, job.id]
      .filter(Boolean)
      .some((value) => String(value).toLowerCase().includes(term));
  }).sort((a, b) => {
    const left = sortableValue(a, filters.sort);
    const right = sortableValue(b, filters.sort);
    const result = left.localeCompare(right, undefined, { numeric: true, sensitivity: 'base' });
    return filters.direction === 'asc' ? result : -result;
  });
});
const pageCount = computed(() => Math.max(1, Math.ceil(filteredJobs.value.length / filters.pageSize)));
const pagedJobs = computed(() => {
  const start = (Math.min(filters.page, pageCount.value) - 1) * filters.pageSize;
  return filteredJobs.value.slice(start, start + filters.pageSize);
});
const runningCount = computed(() => props.jobs.filter((job) => ['queued', 'running'].includes(job.status)).length);
const cancellableCount = computed(() => props.jobs.filter((job) => job.canCancel).length);
const backgroundCount = computed(() => props.jobs.filter((job) => job.type === 'background').length);

watch(() => [filters.search, filters.type, filters.status, filters.pageSize], () => { filters.page = 1; });

function setSort(key) {
  if (filters.sort === key) filters.direction = filters.direction === 'asc' ? 'desc' : 'asc';
  else {
    filters.sort = key;
    filters.direction = 'asc';
  }
}

function openCancel(row) {
  cancelTarget.value = row;
  cancelReason.value = '';
}

function submitCancel() {
  if (!cancelTarget.value) return;
  emit('cancel', { id: cancelTarget.value.id, reason: cancelReason.value.trim() });
  cancelTarget.value = null;
}

function sortableValue(row, key) {
  if (key === 'startedAt') return row.startedAt || row.createdAt || row.metadata?.lastRunAt || '';
  return String(row[key] || '');
}

function shortDate(value) {
  if (!value) return '';
  return new Date(value).toLocaleString();
}

function summaryText(summary = {}) {
  return Object.entries(summary).map(([key, value]) => `${key}: ${value}`).join(', ') || 'completed';
}
</script>
