<script lang="ts">
  import { goto, invalidateAll } from "$app/navigation";
  import { page } from "$app/state";
  import { SvelteURLSearchParams } from "svelte/reactivity";
  import { toast } from "svelte-sonner";
  import { _ } from "svelte-i18n";
  import { adminRetryJob, adminRemoveJob, adminPauseQueue, adminResumeQueue } from "$lib/services";
  import { Button } from "$lib/components/ui/button";
  import { Badge } from "$lib/components/ui/badge";
  import { FilterPills } from "$lib/components/ui/filter-pills";
  import type { Job } from "$lib/services";
  import Meta from "$lib/components/meta/meta.svelte";
  import Pagination from "$lib/components/pagination/pagination.svelte";

  const { data } = $props();

  let togglingQueue = $state<string | null>(null);

  const STATUS_FILTERS = [
    { value: null, label: $_("admin.queues.status_all") },
    { value: "waiting", label: $_("admin.queues.status_waiting") },
    { value: "active", label: $_("admin.queues.status_active") },
    { value: "completed", label: $_("admin.queues.status_completed") },
    { value: "failed", label: $_("admin.queues.status_failed") },
    { value: "delayed", label: $_("admin.queues.status_delayed") },
  ];

  function navigate(overrides: Record<string, string | null>) {
    const params = new SvelteURLSearchParams(page.url.searchParams.toString());
    for (const [k, v] of Object.entries(overrides)) {
      if (v === null) params.delete(k);
      else params.set(k, v);
    }
    goto(`?${params.toString()}`);
  }

  function selectQueue(name: string) {
    navigate({ queue: name, status: null, offset: null });
  }

  function selectStatus(status: string | null) {
    navigate({ status, offset: null });
  }

  async function retryJob(job: Job) {
    try {
      await adminRetryJob(job.queue, job.id);
      toast.success($_("admin.queues.retry_success"));
      await invalidateAll();
    } catch {
      toast.error($_("admin.queues.retry_error"));
    }
  }

  async function removeJob(job: Job) {
    try {
      await adminRemoveJob(job.queue, job.id);
      toast.success($_("admin.queues.remove_success"));
      await invalidateAll();
    } catch {
      toast.error($_("admin.queues.remove_error"));
    }
  }

  async function toggleQueue(queueName: string, isPaused: boolean) {
    togglingQueue = queueName;
    try {
      if (isPaused) {
        await adminResumeQueue(queueName);
        toast.success($_("admin.queues.resume_success"));
      } else {
        await adminPauseQueue(queueName);
        toast.success($_("admin.queues.pause_success"));
      }
      await invalidateAll();
    } catch {
      toast.error(isPaused ? $_("admin.queues.resume_error") : $_("admin.queues.pause_error"));
    } finally {
      togglingQueue = null;
    }
  }

  function statusColor(status: string): string {
    switch (status) {
      case "active":
        return "text-blue-500 border-blue-500/30 bg-blue-500/10";
      case "completed":
        return "text-green-500 border-green-500/30 bg-green-500/10";
      case "failed":
        return "text-destructive border-destructive/30 bg-destructive/10";
      case "delayed":
        return "text-yellow-500 border-yellow-500/30 bg-yellow-500/10";
      default:
        return "text-muted-foreground border-border/40 bg-muted/20";
    }
  }

  function formatDate(iso: string | null): string {
    if (!iso) return "—";
    return new Date(iso).toLocaleString();
  }
</script>

<Meta title={$_("admin.queues.title")} description={null} />

<div class="py-3 sm:py-6 lg:pl-6">
  <div class="flex items-center justify-between mb-6">
    <h1 class="text-2xl font-bold">{$_("admin.queues.title")}</h1>
    {#if data.queue && data.total > 0}
      <span class="text-sm text-muted-foreground">
        {$_("admin.users.total", { values: { total: data.total } })}
      </span>
    {/if}
  </div>

  <!-- Queue cards -->
  <div class="flex flex-wrap gap-3 mb-6">
    {#each data.queues as queue (queue.name)}
      {@const isSelected = data.queue === queue.name}
      <div
        role="button"
        tabindex="0"
        class={`flex-1 min-w-48 rounded-lg border p-4 text-left transition-colors cursor-pointer ${
          isSelected
            ? "border-primary/50 bg-primary/5"
            : "border-border/40 bg-card hover:border-border/70"
        }`}
        onclick={() => selectQueue(queue.name)}
        onkeydown={(e) => e.key === "Enter" && selectQueue(queue.name)}
        aria-pressed={isSelected}
      >
        <div class="flex items-center justify-between mb-3">
          <span class="font-semibold capitalize">{queue.name}</span>
          <div class="flex items-center gap-1.5">
            {#if queue.isPaused}
              <Badge variant="outline" class="text-yellow-600 border-yellow-500/40 bg-yellow-500/10"
                >{$_("admin.queues.paused_badge")}</Badge
              >
            {/if}
            <Button
              size="sm"
              variant="ghost"
              class="h-6 px-2 text-xs"
              disabled={togglingQueue === queue.name}
              onclick={(e) => {
                e.stopPropagation();
                toggleQueue(queue.name, queue.isPaused);
              }}
            >
              {queue.isPaused ? $_("admin.queues.resume") : $_("admin.queues.pause")}
            </Button>
          </div>
        </div>
        <div class="flex flex-wrap gap-2 text-xs">
          {#if queue.counts.waiting > 0}
            <span class="text-muted-foreground">{queue.counts.waiting} waiting</span>
          {/if}
          {#if queue.counts.active > 0}
            <span class="text-blue-500">{queue.counts.active} active</span>
          {/if}
          {#if queue.counts.completed > 0}
            <span class="text-green-500">{queue.counts.completed} completed</span>
          {/if}
          {#if queue.counts.failed > 0}
            <span class="text-destructive font-medium">{queue.counts.failed} failed</span>
          {/if}
          {#if queue.counts.delayed > 0}
            <span class="text-yellow-500">{queue.counts.delayed} delayed</span>
          {/if}
          {#if Object.values(queue.counts).every((v) => v === 0)}
            <span class="text-muted-foreground">empty</span>
          {/if}
        </div>
      </div>
    {/each}
  </div>

  {#if data.queue}
    <!-- Status filter tabs -->
    <div class="mb-4">
      <FilterPills
        scrollable
        value={data.status ?? "all"}
        options={STATUS_FILTERS.map((f) => ({ value: f.value ?? "all", label: f.label }))}
        onchange={(v) => selectStatus(v === "all" ? null : v)}
      />
    </div>

    <!-- Jobs table -->
    <div class="sm:rounded-lg border-y sm:border border-border/40 overflow-x-auto">
      <table class="w-full text-sm">
        <thead class="bg-muted/30">
          <tr>
            <th class="px-4 py-3 text-left font-medium text-muted-foreground"
              >{$_("admin.queues.col_id")}</th
            >
            <th class="px-4 py-3 text-left font-medium text-muted-foreground"
              >{$_("admin.queues.col_name")}</th
            >
            <th class="px-4 py-3 text-left font-medium text-muted-foreground"
              >{$_("admin.queues.col_status")}</th
            >
            <th class="px-4 py-3 text-left font-medium text-muted-foreground hidden md:table-cell">
              {$_("admin.queues.col_attempts")}
            </th>
            <th class="px-4 py-3 text-left font-medium text-muted-foreground hidden lg:table-cell">
              {$_("admin.queues.col_created")}
            </th>
            <th class="px-4 py-3 text-right font-medium text-muted-foreground"
              >{$_("admin.queues.col_actions")}</th
            >
          </tr>
        </thead>
        <tbody class="divide-y divide-border/30">
          {#each data.jobs as job (job.id)}
            <tr class="hover:bg-muted/10 transition-colors">
              <td class="px-4 py-3 font-mono text-xs text-muted-foreground">{job.id}</td>
              <td class="px-4 py-3">
                <div>
                  <p class="font-medium">{job.name}</p>
                  {#if job.failedReason}
                    <p class="text-xs text-destructive mt-0.5 max-w-xs truncate">
                      {$_("admin.queues.failed_reason", { values: { reason: job.failedReason } })}
                    </p>
                  {/if}
                </div>
              </td>
              <td class="px-4 py-3">
                <Badge variant="outline" class={statusColor(job.status)}>{job.status}</Badge>
              </td>
              <td class="px-4 py-3 text-muted-foreground hidden md:table-cell"
                >{job.attemptsMade}</td
              >
              <td class="px-4 py-3 text-muted-foreground hidden lg:table-cell text-xs"
                >{formatDate(job.createdAt)}</td
              >
              <td class="px-4 py-3 text-right">
                <div class="flex items-center justify-end gap-1">
                  {#if job.status === "failed"}
                    <Button
                      size="sm"
                      variant="ghost"
                      aria-label={$_("admin.queues.retry")}
                      onclick={() => retryJob(job)}
                    >
                      <span class="icon-[ri--restart-line] h-4 w-4"></span>
                    </Button>
                  {/if}
                  <Button
                    size="sm"
                    variant="ghost"
                    aria-label={$_("admin.queues.remove")}
                    class="text-destructive hover:text-destructive hover:bg-destructive/10"
                    onclick={() => removeJob(job)}
                  >
                    <span class="icon-[ri--delete-bin-line] h-4 w-4"></span>
                  </Button>
                </div>
              </td>
            </tr>
          {/each}
          {#if data.jobs.length === 0}
            <tr>
              <td colspan="6" class="px-4 py-8 text-center text-muted-foreground"
                >{$_("admin.queues.no_jobs")}</td
              >
            </tr>
          {/if}
        </tbody>
      </table>
    </div>

    {#if data.total > data.limit}
      <div class="flex items-center justify-between mt-4 flex-wrap gap-3">
        <span class="text-sm text-muted-foreground">
          {$_("admin.users.showing", {
            values: {
              start: data.offset + 1,
              end: Math.min(data.offset + data.limit, data.total),
              total: data.total,
            },
          })}
        </span>
        <Pagination
          currentPage={Math.floor(data.offset / data.limit) + 1}
          totalPages={Math.ceil(data.total / data.limit)}
          onPageChange={(p) => navigate({ offset: String((p - 1) * data.limit) })}
        />
      </div>
    {/if}
  {/if}
</div>
