<script setup>
import { ref, onMounted, computed, watch } from 'vue';
import { useToast } from 'vue-toastification';
import JobDetailModal from '@/components/JobDetailModal.vue';

definePageMeta({
  title: "BullMQ Dashboard",
  middleware: ["auth"],
  requiresAuth: true,
  breadcrumb: [
    {
      name: "admin",
      path: "/",
    },
    {
      name: "BullMQ Dashboard",
      path: "/admin",
    }
  ],
});

const toast = useToast();

// --- Mock Data Definitions ---
const dashboardData = ref({
  totalJobs: 12847 + 25, // Adjusted for new jobs
  activeJobs: 23, // Will be dynamically updated by queueSpecificData sum later if needed
  waitingJobs: 156, // Will be dynamically updated
  completedJobs: 12384, // Will be dynamically updated
  failedJobs: 284, // Will be dynamically updated
  successRate: 97.8,
  avgProcessingTime: "2.3s",
  throughputPerHour: 1250,
  queues: ["email-queue", "image-processing", "data-sync", "notifications"]
});

const baseMockJobs = [
  {
    id: "job_001",
    name: "Send Welcome Email",
    queue: "email-queue",
    state: "completed",
    timestamp: new Date("2025-05-31T10:30:00Z").getTime(),
    processedOn: new Date("2025-05-31T10:30:02Z").getTime(),
    finishedOn: new Date("2025-05-31T10:30:05Z").getTime(),
    duration: 5200,
    priority: 5,
    attemptsMade: 1,
    data: { userId: 12345, template: "welcome" },
    progress: 100,
    failedReason: null,
  },
  {
    id: "job_002", 
    name: "Resize Product Image",
    queue: "image-processing",
    state: "active",
    timestamp: new Date("2025-05-31T11:15:00Z").getTime(),
    processedOn: new Date("2025-05-31T11:15:02Z").getTime(),
    finishedOn: null,
    duration: null,
    priority: 8,
    attemptsMade: 1,
    progress: 65,
    data: { imageId: "img_product_abc.jpg", sizes: [100, 300, 600] },
    failedReason: null,
  },
  {
    id: "job_003",
    name: "Sync User Data",
    queue: "data-sync", 
    state: "failed",
    timestamp: new Date("2025-05-31T09:45:00Z").getTime(),
    processedOn: new Date("2025-05-31T09:45:03Z").getTime(),
    finishedOn: new Date("2025-05-31T09:45:10Z").getTime(),
    duration: 10000,
    priority: 3,
    attemptsMade: 3,
    failedReason: "Database connection timeout. Attempted 3 times.",
    data: { source: "crm", destination: "analytics_db" },
    progress: 0,
  },
  {
    id: "job_004",
    name: "Send Newsletter Batch",
    queue: "email-queue",
    state: "waiting",
    timestamp: new Date("2025-05-31T12:00:00Z").getTime(),
    processedOn: null,
    finishedOn: null,
    duration: null,
    priority: 2,
    attemptsMade: 0,
    data: { campaignId: "newsletter_june", segment: "active_users" },
    progress: 0,
    failedReason: null,
  },
   {
    id: "job_005",
    name: "Generate Sales Report",
    queue: "notifications",
    state: "completed",
    timestamp: new Date("2025-05-30T17:00:00Z").getTime(),
    processedOn: new Date("2025-05-30T17:00:05Z").getTime(),
    finishedOn: new Date("2025-05-30T17:05:00Z").getTime(),
    duration: 300000,
    priority: 1,
    attemptsMade: 1,
    data: { period: "2025-Q2", type: "executive_summary" },
    progress: 100,
    failedReason: null,
  }
];

// Generate more jobs for email-queue
const additionalEmailJobs = [];
const jobStates = ["completed", "waiting", "active", "failed"];
const emailJobNames = [
  "Password Reset Request", 
  "Subscription Confirmation", 
  "Order Shipped Notification", 
  "Feature Update Announcement", 
  "Daily Digest Email"
];

for (let i = 0; i < 25; i++) {
  const jobState = jobStates[i % jobStates.length];
  const jobName = emailJobNames[i % emailJobNames.length];
  const now = new Date().getTime();
  const randomPastTime = now - Math.floor(Math.random() * 1000 * 60 * 60 * 24 * 5); // Within last 5 days
  const randomFutureTime = now + Math.floor(Math.random() * 1000 * 60 * 60 * 24 * 2); // Within next 2 days

  let timestamp, processedOn = null, finishedOn = null, progress = 0, failedReason = null, duration = null;
  const priority = Math.floor(Math.random() * 10) + 1;

  switch (jobState) {
    case "completed":
      timestamp = randomPastTime - 120000; // Created 2 mins before processing
      processedOn = randomPastTime - 60000; // Processed 1 min before finishing
      finishedOn = randomPastTime;
      progress = 100;
      duration = (finishedOn - processedOn) + Math.floor(Math.random() * 1000);
      break;
    case "active":
      timestamp = randomPastTime;
      processedOn = new Date().getTime(); // Started now or recently
      progress = Math.floor(Math.random() * 80) + 10; // 10-90%
      break;
    case "waiting":
      timestamp = (i % 5 === 0 && priority <=3) ? randomFutureTime : randomPastTime; // High prio waiting jobs can be scheduled for future
      break;
    case "failed":
      timestamp = randomPastTime - 120000;
      processedOn = randomPastTime - 60000;
      finishedOn = randomPastTime;
      failedReason = "SMTP server unreachable after 2 attempts.";
      duration = (finishedOn - processedOn) + Math.floor(Math.random() * 500);
      break;
  }

  additionalEmailJobs.push({
    id: `job_email_${String(i + 1).padStart(3, '0')}`,
    name: `${jobName} #${i + 1}`,
    queue: "email-queue",
    state: jobState,
    timestamp: timestamp,
    processedOn: processedOn,
    finishedOn: finishedOn,
    duration: duration,
    priority: priority,
    attemptsMade: jobState === 'failed' ? 2 : (jobState === 'completed' || jobState === 'active' ? 1 : 0),
    data: { recipient: `user${i + 1}@example.com`, subject: jobName },
    progress: progress,
    failedReason: failedReason,
  });
}

const mockJobs = ref([...baseMockJobs, ...additionalEmailJobs]);

// Re-calculate sums for dashboardData based on the full mockJobs list
dashboardData.value.totalJobs = mockJobs.value.length;
dashboardData.value.activeJobs = mockJobs.value.filter(j => j.state === 'active').length;
dashboardData.value.waitingJobs = mockJobs.value.filter(j => j.state === 'waiting').length;
dashboardData.value.completedJobs = mockJobs.value.filter(j => j.state === 'completed').length;
dashboardData.value.failedJobs = mockJobs.value.filter(j => j.state === 'failed').length;


const queueSpecificData = ref([ 
  {
    name: "email-queue",
    status: "active",
    workers: 5,
    concurrency: 10,
    metrics: { // Metrics are now calculated from the final mockJobs list
        processed: mockJobs.value.filter(j => j.queue === 'email-queue' && j.state === 'completed').length,
        failed: mockJobs.value.filter(j => j.queue === 'email-queue' && j.state === 'failed').length,
        waiting: mockJobs.value.filter(j => j.queue === 'email-queue' && j.state === 'waiting').length,
        active: mockJobs.value.filter(j => j.queue === 'email-queue' && j.state === 'active').length,
    },
    paused: false,
    processingRate: "150 jobs/min"
  },
  {
    name: "image-processing",
    status: "active", 
    workers: 3,
    concurrency: 5,
    metrics: {
        processed: mockJobs.value.filter(j => j.queue === 'image-processing' && j.state === 'completed').length,
        failed: mockJobs.value.filter(j => j.queue === 'image-processing' && j.state === 'failed').length,
        waiting: mockJobs.value.filter(j => j.queue === 'image-processing' && j.state === 'waiting').length,
        active: mockJobs.value.filter(j => j.queue === 'image-processing' && j.state === 'active').length,
    },
    paused: false,
    processingRate: "45 jobs/min"
  },
  {
    name: "data-sync",
    status: "paused",
    workers: 2,
    concurrency: 2,
     metrics: {
        processed: mockJobs.value.filter(j => j.queue === 'data-sync' && j.state === 'completed').length,
        failed: mockJobs.value.filter(j => j.queue === 'data-sync' && j.state === 'failed').length,
        waiting: mockJobs.value.filter(j => j.queue === 'data-sync' && j.state === 'waiting').length,
        active: mockJobs.value.filter(j => j.queue === 'data-sync' && j.state === 'active').length,
    },
    paused: true,
    processingRate: "25 jobs/min"
  },
    {
    name: "notifications",
    status: "active", 
    workers: 4,
    concurrency: 8,
    metrics: {
        processed: mockJobs.value.filter(j => j.queue === 'notifications' && j.state === 'completed').length,
        failed: mockJobs.value.filter(j => j.queue === 'notifications' && j.state === 'failed').length,
        waiting: mockJobs.value.filter(j => j.queue === 'notifications' && j.state === 'waiting').length,
        active: mockJobs.value.filter(j => j.queue === 'notifications' && j.state === 'active').length,
    },
    paused: false,
    processingRate: "100 jobs/min"
  }
]);
// --- End of Mock Data Definitions ---

const jobs = ref(mockJobs.value); // This should now use the expanded mockJobs
const error = ref(null);
const isLoading = ref(false);

const selectedQueueName = ref(dashboardData.value.queues[0]); // Default to 'email-queue'
const availableQueues = ref(dashboardData.value.queues);

const searchQuery = ref('');
const selectedStatusFilter = ref('all');
const selectedPriorityGroup = ref('all'); // New filter for priority
const currentPage = ref(1);
const itemsPerPage = ref(10);
const selectedJob = ref(null);

// For Queue Drag and Drop
const draggedQueueInfo = ref(null); // { queue: Object, originalIndex: Number }
const dragOverQueueIndex = ref(null); // Index of the queue card being dragged over

// Priority Grouping & Colors
const priorityGroups = {
  high: { label: 'High (1-3)', range: [1, 3], colorClass: 'red', badgeClass: 'bg-red-500 text-white', borderClass: 'border-red-500' },
  medium: { label: 'Medium (4-7)', range: [4, 7], colorClass: 'orange', badgeClass: 'bg-orange-500 text-white', borderClass: 'border-orange-500' },
  low: { label: 'Low (8+)', range: [8, Infinity], colorClass: 'blue', badgeClass: 'bg-sky-500 text-white', borderClass: 'border-sky-500' },
};

function getPriorityGroup(priority) {
  for (const groupKey in priorityGroups) {
    const group = priorityGroups[groupKey];
    if (priority >= group.range[0] && priority <= group.range[1]) {
      return groupKey;
    }
  }
  return 'low'; // Default to low if somehow out of defined ranges (e.g. priority 0 or very high)
}

const priorityGroupTabs = computed(() => {
  return [
    { label: 'All Priorities', value: 'all' },
    ...Object.keys(priorityGroups).map(key => ({
      label: priorityGroups[key].label,
      value: key,
      badgeClass: priorityGroups[key].badgeClass
    }))
  ];
});

function getJobPriorityClass(priority) {
  const groupKey = getPriorityGroup(priority);
  return priorityGroups[groupKey]?.badgeClass || 'bg-gray-400 text-white';
}

function getJobPriorityBorderClass(priority) {
  const groupKey = getPriorityGroup(priority);
  return priorityGroups[groupKey]?.borderClass || 'border-gray-300';
}

function formatDate(timestamp) {
  if (!timestamp) return 'N/A';
  const date = new Date(Number(timestamp));
  if (isNaN(date.getTime())) return 'Invalid Date';
  return date.toLocaleString();
}

function updateJobsDisplay() {
  isLoading.value = true;
  setTimeout(() => {
    let currentJobsToDisplay = []; // Changed variable name for clarity
    if (selectedQueueName.value && selectedQueueName.value !== 'all') {
      currentJobsToDisplay = mockJobs.value.filter(job => job.queue === selectedQueueName.value);
    } else {
      currentJobsToDisplay = [...mockJobs.value]; // Use a copy for 'All Queues'
    }
    // The jobs ref is used by filteredAndSortedJobs, so we don't need to set jobs.value directly here.
    // Instead, filteredAndSortedJobs will react to changes in mockJobs, selectedQueueName, etc.
    // However, to ensure reactivity if `jobs` itself is directly used elsewhere (though it shouldn't be if paginatedJobs is the source):
    jobs.value = [...currentJobsToDisplay]; // This line might be redundant if UI only uses paginatedJobs.
                                         // For safety and consistency, ensure `filteredAndSortedJobs` is the primary source for `paginatedJobs`.
    isLoading.value = false;
    currentPage.value = 1;
  }, 300);
}

async function retryJob(jobId) {
  const job = mockJobs.value.find(j => j.id === jobId);
  if (job && job.state === 'failed') {
    job.state = 'waiting';
    job.attemptsMade = (job.attemptsMade || 0) + 1;
    job.failedReason = null;
    toast.success(`Job #${jobId} sent for retry.`);
    updateJobsDisplay(); // This will refresh the view based on current filters
  } else {
    toast.error(`Job #${jobId} not found or cannot be retried.`);
  }
}

async function removeJob(jobId) {
  const index = mockJobs.value.findIndex(j => j.id === jobId);
  if (index !== -1) {
    mockJobs.value.splice(index, 1);
    // Also update dashboardData counts
    dashboardData.value.totalJobs = mockJobs.value.length;
    dashboardData.value.activeJobs = mockJobs.value.filter(j => j.state === 'active').length;
    dashboardData.value.waitingJobs = mockJobs.value.filter(j => j.state === 'waiting').length;
    dashboardData.value.completedJobs = mockJobs.value.filter(j => j.state === 'completed').length;
    dashboardData.value.failedJobs = mockJobs.value.filter(j => j.state === 'failed').length;
    toast.success(`Job #${jobId} removed.`);
    updateJobsDisplay();
  } else {
    toast.error(`Job #${jobId} not found.`);
  }
}

async function cleanQueue(queueName) {
  const qData = queueSpecificData.value.find(q => q.name === queueName);
  if (!qData) {
    toast.error(`Queue ${queueName} not found.`);
    return;
  }
  const initialJobCount = mockJobs.value.length;
  mockJobs.value = mockJobs.value.filter(job => 
    !(job.queue === queueName && (job.state === 'completed' || job.state === 'failed'))
  );
  const removedCount = initialJobCount - mockJobs.value.length;
  if (removedCount > 0) {
    // Update dashboardData counts
    dashboardData.value.totalJobs = mockJobs.value.length;
    dashboardData.value.completedJobs -= mockJobs.value.filter(j => j.queue === queueName && j.state === 'completed').length; // this is tricky, better re-calculate all
    dashboardData.value.failedJobs -= mockJobs.value.filter(j => j.queue === queueName && j.state === 'failed').length; // same here
    // Recalculate all global counts for simplicity and accuracy after clean
    dashboardData.value.activeJobs = mockJobs.value.filter(j => j.state === 'active').length;
    dashboardData.value.waitingJobs = mockJobs.value.filter(j => j.state === 'waiting').length;
    dashboardData.value.completedJobs = mockJobs.value.filter(j => j.state === 'completed').length;
    dashboardData.value.failedJobs = mockJobs.value.filter(j => j.state === 'failed').length;

    toast.success(`Cleaned ${removedCount} completed/failed jobs from ${queueName}.`);
  } else {
    toast.info(`No completed or failed jobs to clean from ${queueName}.`);
  }
  updateJobsDisplay();
}

async function pauseQueue(queueName) {
  const qData = queueSpecificData.value.find(q => q.name === queueName);
  if (qData) {
    if(qData.status === 'paused'){
      toast.info(`Queue ${queueName} is already paused.`);
      return;
    }
    qData.status = 'paused';
    qData.paused = true;
    toast.success(`Queue ${queueName} paused.`);
  } else {
    toast.error(`Queue ${queueName} not found.`);
  }
}

async function resumeQueue(queueName) {
  const qData = queueSpecificData.value.find(q => q.name === queueName);
  if (qData) {
    if(qData.status === 'active'){
      toast.info(`Queue ${queueName} is already active/resumed.`);
      return;
    }
    qData.status = 'active';
    qData.paused = false;
    toast.success(`Queue ${queueName} resumed.`);
  } else {
    toast.error(`Queue ${queueName} not found.`);
  }
}

// Drag and Drop Handlers for Queues
function onQueueDragStart(event, queue, index) {
  draggedQueueInfo.value = { queue: { ...queue }, originalIndex: index };
  event.dataTransfer.effectAllowed = 'move';
  event.dataTransfer.setData('text/plain', queue.name); // Necessary for Firefox
  // Optional: Add a class to the dragged element for styling
  event.target.classList.add('dragging-queue');
}

function onQueueDragOver(event, targetIndex) {
  event.preventDefault(); // Necessary to allow dropping
  dragOverQueueIndex.value = targetIndex;
  // Optional: Add a class to the drop target for styling
  // event.target.closest('.queue-card-draggable').classList.add('drag-over-queue');
}

function onQueueDragLeave(event) {
  // Optional: Remove drag over styling if not dropping on this element
  // event.target.closest('.queue-card-draggable').classList.remove('drag-over-queue');
  if (dragOverQueueIndex.value === Array.from(event.target.closest('.queue-card-draggable').parentElement.children).indexOf(event.target.closest('.queue-card-draggable'))) {
      dragOverQueueIndex.value = null;
  }
}

function onQueueDrop(event, targetIndex) {
  event.preventDefault();
  if (!draggedQueueInfo.value || draggedQueueInfo.value.originalIndex === targetIndex) {
    dragOverQueueIndex.value = null;
    return; // No drop if nothing is dragged or dropped on itself
  }

  const { queue: draggedItem, originalIndex } = draggedQueueInfo.value;
  
  // Remove the item from its original position
  queueSpecificData.value.splice(originalIndex, 1);
  // Insert the item at the new position
  queueSpecificData.value.splice(targetIndex, 0, draggedItem);
  
  toast.info(`Queue '${draggedItem.name}' moved.`);
  dragOverQueueIndex.value = null;
  // Clean up classes on drag end
}

function onQueueDragEnd(event) {
  // Clean up: remove dragging class and reset refs
  event.target.classList.remove('dragging-queue');
  // const cards = document.querySelectorAll('.drag-over-queue');
  // cards.forEach(card => card.classList.remove('drag-over-queue'));
  draggedQueueInfo.value = null;
  dragOverQueueIndex.value = null;
}

const queueOptions = computed(() => {
  return [{ label: 'All Queues', value: 'all' }, ...availableQueues.value.map(queue => ({
    label: queue,
    value: queue
  }))];
});

const jobStatusOptions = computed(() => {
  const statuses = new Set(['all']);
  mockJobs.value.forEach(job => statuses.add(job.state));
  return Array.from(statuses).map(status => ({
    label: status.charAt(0).toUpperCase() + status.slice(1),
    value: status
  }));
});

const filteredAndSortedJobs = computed(() => {
  let result = [];
  if (selectedQueueName.value && selectedQueueName.value !== 'all') {
    result = mockJobs.value.filter(job => job.queue === selectedQueueName.value);
  } else {
    result = [...mockJobs.value];
  }

  // Filter by priority group
  if (selectedPriorityGroup.value !== 'all') {
    const groupInfo = priorityGroups[selectedPriorityGroup.value];
    if (groupInfo) {
      result = result.filter(job => job.priority >= groupInfo.range[0] && job.priority <= groupInfo.range[1]);
    }
  }

  if (selectedStatusFilter.value !== 'all') {
    result = result.filter(job => job.state === selectedStatusFilter.value);
  }

  if (searchQuery.value.trim() !== '') {
    const lowerSearchQuery = searchQuery.value.toLowerCase().trim();
    result = result.filter(job => {
      const jobIdMatch = String(job.id).toLowerCase().includes(lowerSearchQuery);
      const jobNameMatch = job.name ? job.name.toLowerCase().includes(lowerSearchQuery) : false;
      const jobDataString = job.data ? JSON.stringify(job.data).toLowerCase() : '';
      const jobDataMatch = jobDataString.includes(lowerSearchQuery);
      return jobIdMatch || jobNameMatch || jobDataMatch;
    });
  }
  result.sort((a, b) => Number(b.timestamp) - Number(a.timestamp));
  return result;
});

const totalPages = computed(() => {
  return Math.ceil(filteredAndSortedJobs.value.length / itemsPerPage.value);
});

const paginatedJobs = computed(() => {
  const start = (currentPage.value - 1) * itemsPerPage.value;
  const end = start + itemsPerPage.value;
  return filteredAndSortedJobs.value.slice(start, end);
});

watch(selectedQueueName, (newQueue) => {
  updateJobsDisplay();
});

watch([searchQuery, selectedStatusFilter, selectedPriorityGroup], () => {
  currentPage.value = 1;
});

watch(mockJobs, (newJobs) => {
    // Update queueSpecificData metrics whenever mockJobs changes
    queueSpecificData.value.forEach(q => {
        q.metrics.processed = newJobs.filter(j => j.queue === q.name && j.state === 'completed').length;
        q.metrics.failed = newJobs.filter(j => j.queue === q.name && j.state === 'failed').length;
        q.metrics.waiting = newJobs.filter(j => j.queue === q.name && j.state === 'waiting').length;
        q.metrics.active = newJobs.filter(j => j.queue === q.name && j.state === 'active').length;
    });

    // Update dashboardData counts
    dashboardData.value.totalJobs = newJobs.length;
    dashboardData.value.activeJobs = newJobs.filter(j => j.state === 'active').length;
    dashboardData.value.waitingJobs = newJobs.filter(j => j.state === 'waiting').length;
    dashboardData.value.completedJobs = newJobs.filter(j => j.state === 'completed').length;
    dashboardData.value.failedJobs = newJobs.filter(j => j.state === 'failed').length;
}, { deep: true });

onMounted(() => {
  updateJobsDisplay();
});

</script>

<template>
  <div class="space-y-8 p-4 md:p-6 lg:p-8">
    <LayoutsBreadcrumb />
    
    <div class="flex flex-col sm:flex-row justify-between items-start sm:items-center">
      <h1 class="text-3xl font-bold text-primary mb-4 sm:mb-0">BullMQ Dashboard</h1>
      
      <!-- Global Actions (Placeholder for Add Job, Pause All, etc.) -->
      <div class="flex items-center space-x-2">
        <rs-button variant="primary" size="sm">
          <Icon name="mdi:plus-box-outline" class="mr-1" /> Add Job
        </rs-button>
        <rs-button variant="warning" size="sm">
          <Icon name="mdi:pause-octagon-outline" class="mr-1" /> Pause All Queues
        </rs-button>
        <rs-button variant="danger" size="sm">
          <Icon name="mdi:delete-sweep-outline" class="mr-1" /> Clear All Failed
        </rs-button>
      </div>
    </div>

    <!-- Dashboard Overview Metrics -->
    <div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-4 mb-8">
      <div class="bg-slate-800 text-white p-4 rounded-lg shadow-lg">
        <div class="text-sm font-medium text-slate-300">Total Jobs</div>
        <div class="text-3xl font-bold">{{ dashboardData.totalJobs }}</div>
      </div>
      <div class="bg-sky-600 text-white p-4 rounded-lg shadow-lg">
        <div class="text-sm font-medium text-slate-100">Active</div>
        <div class="text-3xl font-bold">{{ dashboardData.activeJobs }}</div>
      </div>
      <div class="bg-amber-500 text-white p-4 rounded-lg shadow-lg">
        <div class="text-sm font-medium text-slate-100">Waiting</div>
        <div class="text-3xl font-bold">{{ dashboardData.waitingJobs }}</div>
      </div>
      <div class="bg-green-600 text-white p-4 rounded-lg shadow-lg">
        <div class="text-sm font-medium text-slate-100">Completed</div>
        <div class="text-3xl font-bold">{{ dashboardData.completedJobs }}</div>
      </div>
      <div class="bg-red-600 text-white p-4 rounded-lg shadow-lg">
        <div class="text-sm font-medium text-slate-100">Failed</div>
        <div class="text-3xl font-bold">{{ dashboardData.failedJobs }}</div>
      </div>
       <div class="bg-indigo-600 text-white p-4 rounded-lg shadow-lg">
        <div class="text-sm font-medium text-slate-100">Success Rate</div>
        <div class="text-3xl font-bold">{{ dashboardData.successRate }}%</div>
      </div>
    </div>

    <!-- Queue Management Cards -->
    <div class="mb-8">
      <h2 class="text-2xl font-semibold text-gray-800 mb-4">Queue Overview</h2>
      <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
        <rs-card v-for="(q, index) in queueSpecificData" :key="q.name" 
                 :class="{
                   'border-blue-500': q.status === 'active',
                   'border-orange-400': q.status === 'paused',
                   'queue-drop-target-active': dragOverQueueIndex === index && draggedQueueInfo && draggedQueueInfo.originalIndex !== index
                 }"
                 class="border-t-4 shadow-lg hover:shadow-xl transition-all duration-200 ease-in-out queue-card-draggable cursor-grab"
                 draggable="true"
                 @dragstart="onQueueDragStart($event, q, index)"
                 @dragover.prevent="onQueueDragOver($event, index)"
                 @dragleave="onQueueDragLeave($event)"
                 @drop="onQueueDrop($event, index)"
                 @dragend="onQueueDragEnd($event)"
        >
          <template #header>
            <div class="flex justify-between items-center px-4 py-3">
              <h3 class="text-lg font-semibold text-gray-700">{{ q.name }}</h3>
              <rs-badge :variant="q.status === 'active' ? 'success' : 'warning'">{{ q.status }}</rs-badge>
            </div>
          </template>
          <template #body>
            <div class="p-4 space-y-3">
              <div class="grid grid-cols-2 gap-2 text-sm">
                <div><span class="text-gray-500">Active:</span> <strong class="text-gray-800">{{ q.metrics.active }}</strong></div>
                <div><span class="text-gray-500">Waiting:</span> <strong class="text-gray-800">{{ q.metrics.waiting }}</strong></div>
                <div><span class="text-gray-500">Completed:</span> <strong class="text-green-600">{{ q.metrics.processed }}</strong></div>
                <div><span class="text-gray-500">Failed:</span> <strong class="text-red-600">{{ q.metrics.failed }}</strong></div>
              </div>
              <div class="text-xs text-gray-500">
                  Workers: {{q.workers}} | Concurrency: {{q.concurrency}} | Rate: {{q.processingRate}}
              </div>
            </div>
          </template>
          <template #footer>
            <div class="px-4 py-2 border-t bg-gray-50 flex justify-end space-x-2">
              <rs-button size="xs" :variant="q.status === 'active' ? 'warning' : 'success'" 
                         @click="q.status === 'active' ? pauseQueue(q.name) : resumeQueue(q.name)">
                <Icon :name="q.status === 'active' ? 'mdi:pause' : 'mdi:play'" size="16" class="mr-1" />
                {{ q.status === 'active' ? 'Pause' : 'Resume' }}
              </rs-button>
              <rs-button size="xs" variant="danger" @click="cleanQueue(q.name)">
                <Icon name="mdi:broom" size="16" class="mr-1" /> Clean
              </rs-button>
            </div>
          </template>
        </rs-card>
      </div>
    </div>

    <!-- Filter and Job List Section -->
    <div class="flex justify-between items-center mb-4">
        <h2 class="text-2xl font-semibold text-gray-800">Job Management</h2>
         <div class="flex items-center space-x-4">
            <div class="w-72">
              <rs-select v-model="selectedQueueName" 
                        :options="queueOptions"
                        placeholder="Select Queue to View Jobs"
                        :disabled="isLoading || !!error" />
            </div>
         </div>
    </div>

    <!-- Priority Group Tabs -->
    <div class="mb-4 border-b border-gray-200">
        <nav class="-mb-px flex space-x-4" aria-label="Tabs">
            <button v-for="tab in priorityGroupTabs" :key="tab.value"
                    @click="selectedPriorityGroup = tab.value"
                    :class="[
                        tab.value === selectedPriorityGroup 
                            ? (priorityGroups[tab.value]?.borderClass ? priorityGroups[tab.value].borderClass.replace('border-', 'border-b-2 border-') + ' text-' + priorityGroups[tab.value].colorClass + '-600' : 'border-b-2 border-indigo-500 text-indigo-600') 
                            : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300',
                        'whitespace-nowrap py-3 px-1 border-b-2 font-medium text-sm focus:outline-none transition-colors duration-150 ease-in-out'
                    ]"
                    :aria-current="tab.value === selectedPriorityGroup ? 'page' : undefined">
                {{ tab.label }}
            </button>
        </nav>
    </div>

    <rs-card v-if="selectedQueueName"> 
      <template #header>
        <div class="px-4 py-3 border-b">
          <div class="flex flex-col md:flex-row justify-between md:items-center mb-3">
            <h3 class="text-xl font-semibold text-gray-700 mb-2 md:mb-0">
              Jobs in <span class="text-primary">{{ selectedQueueName === 'all' ? 'All Queues' : selectedQueueName }}</span>
              <span v-if="selectedPriorityGroup !== 'all'" class="text-sm font-normal text-gray-500 ml-2">
                (Priority: {{ priorityGroups[selectedPriorityGroup]?.label }})
              </span>
            </h3>
            <div class="flex items-center space-x-2" v-if="selectedQueueName !== 'all'">
              <rs-button variant="success" size="sm" 
                        @click="resumeQueue(selectedQueueName)" 
                        :disabled="isLoading || !!error || queueSpecificData.find(q=>q.name === selectedQueueName)?.status === 'active'">
                <Icon name="mdi:play" size="18" class="mr-1" /> Resume Queue
              </rs-button>
              <rs-button variant="warning" size="sm" 
                        @click="pauseQueue(selectedQueueName)" 
                        :disabled="isLoading || !!error || queueSpecificData.find(q=>q.name === selectedQueueName)?.status === 'paused'">
                <Icon name="mdi:pause" size="18" class="mr-1" /> Pause Queue
              </rs-button>
              <rs-button variant="danger" size="sm" 
                        @click="cleanQueue(selectedQueueName)" 
                        :disabled="isLoading || !!error">
                <Icon name="mdi:broom" size="18" class="mr-1" /> Clean Queue
              </rs-button>
            </div>
          </div>
          <div class="flex flex-col md:flex-row items-center space-y-2 md:space-y-0 md:space-x-4">
            <div class="flex-grow w-full md:w-auto">
               <rs-input type="text" v-model="searchQuery" placeholder="Search Jobs by ID, Name, or Data..." class="w-full" />
            </div>
            <div class="w-full md:w-48">
              <rs-select v-model="selectedStatusFilter"
                        :options="jobStatusOptions"
                        placeholder="Filter by Status"
                        :disabled="isLoading || !!error || paginatedJobs.length === 0 && filteredAndSortedJobs.length === 0" />
            </div>
            <rs-button variant="secondary" size="sm" 
                      @click="updateJobsDisplay" 
                      :disabled="isLoading || !!error" 
                      class="w-full md:w-auto">
              <Icon name="mdi:refresh" size="18" 
                    :class="{ 'animate-spin': isLoading }" 
                    class="mr-1" />
              {{ isLoading ? 'Refreshing...' : 'Refresh Jobs' }}
            </rs-button>
          </div>
        </div>
      </template>

      <template #body>
        <div class="p-4">
          <div v-if="isLoading" class="text-center py-8">
            <div class="animate-spin rounded-full h-12 w-12 border-b-2 border-primary mx-auto"></div>
            <p class="mt-2 text-gray-500">Loading jobs...</p>
          </div>
          <div v-else-if="error" class="bg-red-50 border-l-4 border-red-500 p-4 rounded">
            <div class="flex">
              <div class="flex-shrink-0">
                <Icon name="mdi:alert-circle-outline" class="h-5 w-5 text-red-400" />
              </div>
              <div class="ml-3">
                <p class="text-sm text-red-700">{{ error }}</p>
              </div>
            </div>
          </div>
          <div v-else-if="paginatedJobs.length > 0" class="space-y-4">
            <div v-for="job in paginatedJobs" :key="job.id" 
                 class="bg-white p-4 rounded-lg shadow hover:shadow-lg transition-all duration-200 ease-in-out cursor-pointer border-l-4 flex flex-col"
                 :class="getJobPriorityBorderClass(job.priority)"
                 @click="selectedJob = job">
              <div class="flex flex-col sm:flex-row justify-between items-start flex-grow">
                <div class="mb-2 sm:mb-0 flex-grow">
                  <div class="flex items-center space-x-2 mb-1">
                    <span class="font-semibold text-primary hover:underline">#{{ job.id }}</span>
                    <span class="text-md font-medium text-gray-700">- {{ job.name }}</span>
                    <rs-badge 
                      :variant="job.state === 'completed' ? 'success' : 
                               job.state === 'failed' ? 'danger' :
                               job.state === 'active' ? 'primary' : 'info'" 
                               class="text-xs"
                    >
                      {{ job.state }}
                    </rs-badge>
                  </div>
                  <p class="text-xs text-gray-500">
                    Queue: <span class="font-medium">{{job.queue}}</span> 
                    | Priority: <span :class="getJobPriorityClass(job.priority)" class="px-1.5 py-0.5 rounded-full text-xs font-semibold">{{job.priority}}</span>
                  </p>
                  <p class="text-xs text-gray-500 mt-0.5">
                    Created: {{ formatDate(job.timestamp) }}
                    <span v-if="job.processedOn">| Started: {{ formatDate(job.processedOn) }}</span>
                    <span v-if="job.finishedOn">| Finished: {{ formatDate(job.finishedOn) }}</span>
                    <span v-if="job.duration">| Duration: {{(job.duration / 1000).toFixed(1)}}s</span>
                  </p>
                </div>
                
                <div class="flex space-x-2 mt-2 sm:mt-0 self-start sm:self-center flex-shrink-0">
                  <rs-button v-if="job.state === 'failed'" 
                            variant="warning" size="xs" 
                            @click.stop="retryJob(job.id)" 
                            :disabled="isLoading || !!error">
                    <Icon name="mdi:refresh" size="14" class="mr-1" /> Retry
                  </rs-button>
                  <rs-button variant="danger" size="xs" 
                            @click.stop="removeJob(job.id)" 
                            :disabled="isLoading || !!error">
                    <Icon name="mdi:delete-outline" size="14" class="mr-1" /> Remove
                  </rs-button>
                </div>
              </div>

              <div v-if="job.state === 'active' && job.progress > 0" class="mt-3 border-t border-gray-100 pt-2">
                <div class="flex justify-between text-xs text-gray-600 mb-1">
                    <span>Progress: {{ job.progress }}%</span>
                    <span>Attempts: {{ job.attemptsMade }}</span>
                </div>
                <div class="w-full bg-gray-200 rounded-full h-1.5">
                  <div class="bg-blue-600 h-1.5 rounded-full" 
                       :style="{ width: job.progress + '%' }">
                  </div>
                </div>
              </div>
              
              <div v-if="job.state === 'failed' && job.failedReason" 
                   class="mt-3 p-2 bg-red-50 border-l-4 border-red-400 rounded text-xs text-red-700 whitespace-pre-wrap">
                <strong>Error:</strong> {{ job.failedReason }}
              </div>

              <div v-if="job.data && Object.keys(job.data).length > 0" class="mt-2 pt-2 border-t border-gray-100">
                <details class="text-xs">
                    <summary class="cursor-pointer text-gray-500 hover:text-gray-700">View Data</summary>
                    <pre class="mt-1 p-2 bg-gray-50 rounded text-gray-600 text-[11px] max-h-32 overflow-auto">{{ JSON.stringify(job.data, null, 2) }}</pre>
                </details>
              </div>
            </div>
          </div>
          <div v-else-if="filteredAndSortedJobs.length === 0 && jobs.length > 0 && (searchQuery || selectedStatusFilter !== 'all' || selectedPriorityGroup !== 'all')" class="text-center py-10">
            <Icon name="mdi:filter-variant-remove" size="48" class="text-gray-400 mx-auto mb-2" />
            <p class="text-gray-500">No jobs match your current filters in <strong class="text-gray-700">{{selectedQueueName === 'all' ? 'any queue' : selectedQueueName}}</strong>.</p>
            <p class="text-sm text-gray-400 mt-1">Try adjusting your search or filters.</p>
          </div>
          <div v-else class="text-center py-10">
            <Icon name="mdi:playlist-remove" size="48" class="text-gray-400 mx-auto mb-2" />
            <p class="text-gray-500">No jobs found in <strong class="text-gray-700">{{selectedQueueName === 'all' ? 'any queue' : selectedQueueName}}</strong>.</p>
            <p v-if="selectedQueueName !== 'all'" class="text-sm text-gray-400 mt-1">This queue is currently empty.</p>
          </div>
        </div>
      </template>
      <template #footer v-if="totalPages > 1">
        <div class="px-4 py-3 border-t bg-gray-50 flex flex-col sm:flex-row justify-between items-center space-y-2 sm:space-y-0">
          <div class="text-sm text-gray-600">
            Showing {{ paginatedJobs.length }} of {{ filteredAndSortedJobs.length }} jobs (Page {{ currentPage }} of {{ totalPages }})
          </div>
          <div class="flex space-x-1">
            <rs-button size="xs" variant="secondary" :disabled="currentPage <= 1" @click="currentPage = 1">
                <Icon name="mdi:page-first" size="16" />
            </rs-button>
            <rs-button size="xs" variant="secondary" :disabled="currentPage <= 1" @click="currentPage--">
              <Icon name="mdi:chevron-left" size="16" /> Previous
            </rs-button>
            <rs-button size="xs" variant="secondary" :disabled="currentPage >= totalPages" @click="currentPage++">
              Next <Icon name="mdi:chevron-right" size="16" />
            </rs-button>
             <rs-button size="xs" variant="secondary" :disabled="currentPage >= totalPages" @click="currentPage = totalPages">
                <Icon name="mdi:page-last" size="16" />
            </rs-button>
          </div>
        </div>
      </template>
    </rs-card>

    <div v-else-if="!selectedQueueName && !isLoading" class="text-center py-12">
      <Icon name="mdi:information-outline" size="48" class="text-gray-400 mx-auto mb-2" />
      <p class="text-gray-500">Please select a queue from the dropdown above to view its jobs.</p>
    </div>

    <JobDetailModal v-if="selectedJob" :job="selectedJob" :show="!!selectedJob" @close="selectedJob = null" />

  </div>
</template>

<style scoped>
/* Add any page-specific styles if needed - Tailwind should cover most */
.text-primary {
  color: #3B82F6; /* Example primary color from your design spec */
}

/* Custom scrollbar for pre tag if needed */
pre::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}
pre::-webkit-scrollbar-thumb {
  background: #cbd5e1; /* cool-gray-300 */
  border-radius: 3px;
}
pre::-webkit-scrollbar-thumb:hover {
  background: #94a3b8; /* cool-gray-400 */
}

.dragging-queue {
  opacity: 0.5;
  border: 2px dashed #3B82F6; /* primary color for border */
  transform: scale(0.95);
  box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); /* shadow-lg */
}

.queue-drop-target-active {
  /* Basic style for when an item is dragged over a potential drop target */
  outline: 2px dashed #10B981; /* success color */
  outline-offset: 2px;
  background-color: #f0fdf4; /* Light green background, Tailwind green-50 */
  transform: scale(1.02); /* Slightly enlarge the drop target */
  transition: transform 0.2s ease-out, background-color 0.2s ease-out; 
}

/* Enhanced styling for the specific drop target queue card */
.queue-card-draggable.queue-drop-target-active {
    border-color: #10B981 !important; /* Ensure border color overrides others */
}

.queue-card-draggable {
  transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
}

</style> 