import { useState, useEffect } from 'react';
import { useSearchParams } from 'react-router';
import { toast } from 'sonner';
import { Users, Search, CircleCheck, CircleSlash, Clock, Loader2, Star, X, Download } from 'lucide-react';
import { useSoulseekFavorites } from './useSoulseekFavorites';
import { useSoulseekUser } from './useSoulseekUser';
import { useSoulseekBrowseSnapshots } from './useSoulseekBrowse';
import { SharesBrowser, BrowseStateChip } from './SharesBrowser';
import { USER_PARAM } from './shared';

// Users panel — look up a peer: their presence (online/away/offline) and profile info (description,
// upload slots, queue), both cheap live calls (GET /users/{u}/status + /info). Their shared folders come
// from Officer's own cache instead, via <SharesBrowser> — see that file for why it isn't browsed live.
//
// This is also where the workspace's peer actions land: the username dropdown in search results and
// downloads links here with `?user=<name>`, which is the whole mechanism — a peer profile is now
// linkable and survives a reload.
// Favourites — Officer's own data, since slskd has no such concept — get their own section at the top,
// which also serves as this panel's landing content before any lookup.

const presenceStyle = (p?: string): { label: string; dot: string; icon: typeof CircleCheck } => {
  switch ((p ?? '').toLowerCase()) {
    case 'online':
      return { label: 'Online', dot: 'text-green-500', icon: CircleCheck };
    case 'away':
      return { label: 'Away', dot: 'text-amber-500', icon: Clock };
    default:
      return { label: 'Offline', dot: 'text-zinc-500', icon: CircleSlash };
  }
};

export const SoulseekUsers = () => {
  const [params, setParams] = useSearchParams();
  const selected = params.get(USER_PARAM)?.trim() ?? '';
  const [query, setQuery] = useState(selected);
  const { favorites, isFavorite, toggle } = useSoulseekFavorites();
  const { snapshotOf, fetchShares } = useSoulseekBrowseSnapshots();

  // Selecting a peer is now just naming one — the query owns the fetching, and its cache owns the answer.
  const user = useSoulseekUser(selected);
  const peer = user.data ?? null;

  // Navigating, not setting state: the peer is `?user=`. Shares are still NOT fetched automatically —
  // that's a multi-minute server-side job, so it stays an explicit click in the shares card.
  const select = (name: string) => {
    const username = name.trim();
    if (!username) return;
    setParams((prev) => {
      const next = new URLSearchParams(prev);
      next.set(USER_PARAM, username);
      return next;
    });
  };

  // Arriving by link (or Back) should show the name in the box that produced it.
  useEffect(() => {
    if (selected) setQuery(selected);
  }, [selected]);

  useEffect(() => {
    if (user.error) toast.error(user.error.message);
  }, [user.error]);

  const pres = presenceStyle(peer?.status?.presence);
  const PresIcon = pres.icon;
  // Only a peer we have nothing cached for is worth showing a pending state for.
  const pending = !!selected && user.isPending;

  return (
    <div className="flex h-full flex-col overflow-hidden">
      <div className="flex shrink-0 items-center gap-2 border-b p-3">
        <Users className="h-4 w-4 shrink-0 text-muted-foreground" />
        <form
          onSubmit={(ev) => {
            ev.preventDefault();
            select(query);
          }}
          className="flex flex-1 items-center gap-2"
        >
          <input
            value={query}
            onChange={(ev) => setQuery(ev.target.value)}
            placeholder="Look up a username…"
            className="h-9 min-w-0 flex-1 rounded-lg border bg-background px-3 text-sm outline-none focus:border-primary/50 focus:ring-2 focus:ring-primary/20"
          />
          <button
            type="submit"
            disabled={!query.trim() || user.isFetching}
            className="flex h-9 items-center gap-1.5 rounded-lg bg-primary px-3 text-sm text-primary-foreground transition hover:bg-primary/90 disabled:opacity-40"
          >
            {user.isFetching ? <Loader2 className="h-4 w-4 animate-spin" /> : <Search className="h-4 w-4" />}
            Look up
          </button>
        </form>
      </div>

      <div className="min-h-0 flex-1 overflow-y-auto p-4">
        <div className="mx-auto flex max-w-2xl flex-col gap-4">
          {/* Favorites — Officer's own data (slskd has no such concept). Always present, so the section
              doubles as the panel's landing content before any lookup. */}
          <div className="rounded-xl border border-white/10 bg-zinc-950">
            <div className="flex items-center gap-2 border-b border-white/10 px-4 py-2.5">
              <Star className="h-4 w-4 fill-amber-400 text-amber-400" />
              <span className="text-sm font-medium text-zinc-100">Favorites</span>
              {favorites.length > 0 && <span className="text-xs text-zinc-500">· {favorites.length}</span>}
            </div>
            {favorites.length === 0 ? (
              <p className="px-4 py-3 text-sm text-zinc-500">
                No favorites yet — add one from a peer's profile below, or from the username menu in search results and
                downloads.
              </p>
            ) : (
              <div className="max-h-64 divide-y divide-white/5 overflow-y-auto">
                {favorites.map((u) => {
                  const current = selected === u;
                  return (
                    <div
                      key={u}
                      className={`flex items-center gap-2 px-4 py-2 text-sm transition-colors ${
                        current ? 'bg-primary/5' : 'hover:bg-white/[0.02]'
                      }`}
                    >
                      <button
                        type="button"
                        onClick={() => select(u)}
                        title={`Look up ${u}`}
                        className={`min-w-0 flex-1 truncate text-left transition ${
                          current ? 'font-medium text-primary' : 'text-zinc-200 hover:text-zinc-100'
                        }`}
                      >
                        {u}
                      </button>
                      <BrowseStateChip snapshot={snapshotOf(u)} />
                      {!snapshotOf(u) && (
                        <button
                          type="button"
                          onClick={() => fetchShares(u)}
                          title={`Fetch ${u}'s shares in the background`}
                          className="flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-zinc-500 transition hover:bg-white/10 hover:text-zinc-200"
                        >
                          <Download className="h-3.5 w-3.5" />
                        </button>
                      )}
                      <button
                        type="button"
                        onClick={() => toggle(u)}
                        title={`Remove ${u} from favorites`}
                        className="flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-zinc-500 transition hover:bg-white/10 hover:text-zinc-200"
                      >
                        <X className="h-3.5 w-3.5" />
                      </button>
                    </div>
                  );
                })}
              </div>
            )}
          </div>

          {!selected ? (
            <div className="flex flex-col items-center justify-center gap-2 py-10 text-center text-muted-foreground">
              <Users className="h-8 w-8" />
              <p className="text-sm">Enter a Soulseek username to see their profile and shares.</p>
            </div>
          ) : (
            <>
              {/* Profile. Keyed off the selected name, not the loaded peer, so a lookup already in cache
                  paints instantly and a fresh one fills in around a card that's already on screen. */}
              <div className="rounded-xl border border-white/10 bg-zinc-950 p-4">
                <div className="flex items-center gap-3">
                  <div className="flex h-11 w-11 shrink-0 items-center justify-center rounded-full bg-white/5 text-lg font-semibold text-zinc-300">
                    {selected.charAt(0).toUpperCase()}
                  </div>
                  <div className="min-w-0 flex-1">
                    <div className="truncate text-sm font-semibold text-zinc-100">{selected}</div>
                    {pending ? (
                      <div className="flex items-center gap-1.5 text-xs text-zinc-500">
                        <Loader2 className="h-3.5 w-3.5 animate-spin" />
                        Checking…
                      </div>
                    ) : (
                      <div className={`flex items-center gap-1.5 text-xs ${pres.dot}`}>
                        <PresIcon className="h-3.5 w-3.5" />
                        {pres.label}
                        {peer?.status?.isPrivileged && <span className="text-amber-400">· privileged</span>}
                      </div>
                    )}
                  </div>
                  <button
                    type="button"
                    onClick={() => toggle(selected)}
                    title={isFavorite(selected) ? 'Remove from favorites' : 'Add to favorites'}
                    className="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg text-zinc-500 transition hover:bg-white/5 hover:text-zinc-200"
                  >
                    <Star className={`h-4 w-4 ${isFavorite(selected) ? 'fill-amber-400 text-amber-400' : ''}`} />
                  </button>
                </div>

                {peer?.info && (
                  <>
                    <div className="mt-4 grid grid-cols-3 gap-2">
                      <Stat label="Upload slots" value={peer.info.uploadSlots ?? 0} />
                      <Stat label="Queue" value={peer.info.queueLength ?? 0} />
                      <Stat
                        label="Free slot"
                        value={peer.info.hasFreeUploadSlot ? 'Yes' : 'No'}
                        accent={peer.info.hasFreeUploadSlot ? 'text-green-400' : 'text-zinc-400'}
                      />
                    </div>
                    {peer.info.description && (
                      <p className="mt-3 whitespace-pre-wrap border-t border-white/5 pt-3 text-sm text-zinc-300">
                        {peer.info.description}
                      </p>
                    )}
                  </>
                )}
              </div>

              <SharesBrowser username={selected} />
            </>
          )}
        </div>
      </div>
    </div>
  );
};

type StatProps = { label: string; value: string | number; accent?: string };

const Stat = ({ label, value, accent = 'text-zinc-100' }: StatProps) => (
  <div className="flex flex-col gap-1 rounded-lg border border-white/5 bg-white/[0.02] px-3 py-2">
    <span className="text-xs text-zinc-500">{label}</span>
    <span className={`text-lg font-semibold tabular-nums ${accent}`}>{value}</span>
  </div>
);
