<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 { adminUpdateUser, adminDeleteUser } from "$lib/services";
  import { getAssetUrl } from "$lib/api";
  import { Button } from "$lib/components/ui/button";
  import { Input } from "$lib/components/ui/input";
  import { Select, SelectContent, SelectItem, SelectTrigger } from "$lib/components/ui/select";
  import * as Dialog from "$lib/components/ui/dialog";
  import type { User } from "$lib/types";

  const { data } = $props();

  let searchValue = $state(data.search ?? "");
  let searchTimeout: ReturnType<typeof setTimeout>;
  let deleteTarget: User | null = $state(null);
  let deleteOpen = $state(false);
  let deleting = $state(false);
  let updatingId = $state<string | null>(null);

  const currentUserId = page.data.authStatus?.user?.id;

  const roles = ["", "viewer", "model", "admin"] as const;

  function debounceSearch(value: string) {
    clearTimeout(searchTimeout);
    searchTimeout = setTimeout(() => {
      const params = new SvelteURLSearchParams(page.url.searchParams.toString());
      if (value) params.set("search", value);
      else params.delete("search");
      params.delete("offset");
      goto(`?${params.toString()}`, { keepFocus: true });
    }, 300);
  }

  function setRole(role: string) {
    const params = new SvelteURLSearchParams(page.url.searchParams.toString());
    if (role) params.set("role", role);
    else params.delete("role");
    params.delete("offset");
    goto(`?${params.toString()}`);
  }

  async function changeUserRole(user: User, newRole: string) {
    updatingId = user.id;
    try {
      await adminUpdateUser({ userId: user.id, role: newRole });
      toast.success(`Role updated to ${newRole}`);
      await invalidateAll();
    } catch {
      toast.error("Failed to update role");
    } finally {
      updatingId = null;
    }
  }

  function confirmDelete(user: User) {
    deleteTarget = user;
    deleteOpen = true;
  }

  async function handleDelete() {
    if (!deleteTarget) return;
    deleting = true;
    try {
      await adminDeleteUser(deleteTarget.id);
      toast.success("User deleted");
      deleteOpen = false;
      deleteTarget = null;
      await invalidateAll();
    } catch {
      toast.error("Failed to delete user");
    } finally {
      deleting = false;
    }
  }

  function formatDate(d: string | Date) {
    return new Date(d).toLocaleDateString();
  }
</script>

<div class="p-6">
  <div class="flex items-center justify-between mb-6">
    <h1 class="text-2xl font-bold">Users</h1>
    <span class="text-sm text-muted-foreground">{data.total} total</span>
  </div>

  <!-- Filters -->
  <div class="flex flex-wrap gap-3 mb-4">
    <Input
      placeholder="Search email or name…"
      class="max-w-xs"
      value={searchValue}
      oninput={(e) => {
        searchValue = (e.target as HTMLInputElement).value;
        debounceSearch(searchValue);
      }}
    />

    <div class="flex gap-1">
      {#each roles as role (role)}
        <Button
          size="sm"
          variant={data.role === role || (!data.role && role === "") ? "default" : "outline"}
          onclick={() => setRole(role)}
        >
          {role || "All"}
        </Button>
      {/each}
    </div>
  </div>

  <!-- Table -->
  <div class="rounded-lg border border-border/40 overflow-hidden">
    <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">User</th>
          <th class="px-4 py-3 text-left font-medium text-muted-foreground">Email</th>
          <th class="px-4 py-3 text-left font-medium text-muted-foreground">Role</th>
          <th class="px-4 py-3 text-left font-medium text-muted-foreground">Joined</th>
          <th class="px-4 py-3 text-right font-medium text-muted-foreground">Actions</th>
        </tr>
      </thead>
      <tbody class="divide-y divide-border/30">
        {#each data.items as user (user.id)}
          <tr class="hover:bg-muted/10 transition-colors">
            <td class="px-4 py-3">
              <div class="flex items-center gap-3">
                {#if user.avatar}
                  <img
                    src={getAssetUrl(user.avatar, "mini")}
                    alt=""
                    class="h-8 w-8 rounded-full object-cover"
                  />
                {:else}
                  <div
                    class="h-8 w-8 rounded-full bg-primary/20 flex items-center justify-center text-xs font-semibold text-primary"
                  >
                    {(user.artist_name || user.email)[0].toUpperCase()}
                  </div>
                {/if}
                <span class="font-medium">{user.artist_name || user.first_name || "—"}</span>
              </div>
            </td>
            <td class="px-4 py-3 text-muted-foreground">{user.email}</td>
            <td class="px-4 py-3">
              <Select
                type="single"
                value={user.role}
                disabled={user.id === currentUserId || updatingId === user.id}
                onValueChange={(v) => v && changeUserRole(user, v)}
              >
                <SelectTrigger class="w-24 h-7 text-xs">
                  {user.role}
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="viewer">Viewer</SelectItem>
                  <SelectItem value="model">Model</SelectItem>
                  <SelectItem value="admin">Admin</SelectItem>
                </SelectContent>
              </Select>
            </td>
            <td class="px-4 py-3 text-muted-foreground">{formatDate(user.date_created)}</td>
            <td class="px-4 py-3 text-right">
              <div class="flex items-center justify-end gap-1">
                <Button size="sm" variant="ghost" href="/admin/users/{user.id}">
                  <span class="icon-[ri--edit-line] h-4 w-4"></span>
                </Button>
                <Button
                  size="sm"
                  variant="ghost"
                  class="text-destructive hover:text-destructive hover:bg-destructive/10"
                  disabled={user.id === currentUserId}
                  onclick={() => confirmDelete(user)}
                >
                  <span class="icon-[ri--delete-bin-line] h-4 w-4"></span>
                </Button>
              </div>
            </td>
          </tr>
        {/each}

        {#if data.items.length === 0}
          <tr>
            <td colspan="5" class="px-4 py-8 text-center text-muted-foreground">No users found</td>
          </tr>
        {/if}
      </tbody>
    </table>
  </div>

  <!-- Pagination -->
  {#if data.total > data.limit}
    <div class="flex items-center justify-between mt-4">
      <span class="text-sm text-muted-foreground">
        Showing {data.offset + 1}–{Math.min(data.offset + data.limit, data.total)} of {data.total}
      </span>
      <div class="flex gap-2">
        <Button
          size="sm"
          variant="outline"
          disabled={data.offset === 0}
          onclick={() => {
            const params = new SvelteURLSearchParams(page.url.searchParams.toString());
            params.set("offset", String(Math.max(0, data.offset - data.limit)));
            goto(`?${params.toString()}`);
          }}
        >
          Previous
        </Button>
        <Button
          size="sm"
          variant="outline"
          disabled={data.offset + data.limit >= data.total}
          onclick={() => {
            const params = new SvelteURLSearchParams(page.url.searchParams.toString());
            params.set("offset", String(data.offset + data.limit));
            goto(`?${params.toString()}`);
          }}
        >
          Next
        </Button>
      </div>
    </div>
  {/if}
</div>

<!-- Delete confirmation dialog -->
<Dialog.Root bind:open={deleteOpen}>
  <Dialog.Content>
    <Dialog.Header>
      <Dialog.Title>Delete user</Dialog.Title>
      <Dialog.Description>
        Are you sure you want to permanently delete <strong
          >{deleteTarget?.artist_name || deleteTarget?.email}</strong
        >? This cannot be undone.
      </Dialog.Description>
    </Dialog.Header>
    <Dialog.Footer>
      <Button variant="outline" onclick={() => (deleteOpen = false)}>Cancel</Button>
      <Button variant="destructive" disabled={deleting} onclick={handleDelete}>
        {deleting ? "Deleting…" : "Delete"}
      </Button>
    </Dialog.Footer>
  </Dialog.Content>
</Dialog.Root>
