import { useState } from "react";
import { useParams, Link } from "react-router-dom";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { getBand } from "../api/bands";
import { api } from "../api/client";

interface SongSummary {
  id: string;
  title: string;
  status: string;
  tags: string[];
  global_key: string | null;
  global_bpm: number | null;
  version_count: number;
}

interface BandMember {
  id: string;
  display_name: string;
  email: string;
  role: string;
  joined_at: string;
}

interface BandInvite {
  id: string;
  token: string;
  role: string;
  expires_at: string;
}

interface SessionSummary {
  id: string;
  date: string;
  label: string | null;
  recording_count: number;
}

function formatDate(iso: string): string {
  const d = new Date(iso);
  return d.toLocaleDateString(undefined, { year: "numeric", month: "short", day: "numeric" });
}

function weekday(iso: string): string {
  return new Date(iso).toLocaleDateString(undefined, { weekday: "short" });
}

export function BandPage() {
  const { bandId } = useParams<{ bandId: string }>();
  const qc = useQueryClient();
  const [tab, setTab] = useState<"dates" | "search">("dates");
  const [showCreate, setShowCreate] = useState(false);
  const [title, setTitle] = useState("");
  const [error, setError] = useState<string | null>(null);
  const [scanning, setScanning] = useState(false);
  const [scanProgress, setScanProgress] = useState<string | null>(null);
  const [scanMsg, setScanMsg] = useState<string | null>(null);
  const [inviteLink, setInviteLink] = useState<string | null>(null);
  const [editingFolder, setEditingFolder] = useState(false);
  const [folderInput, setFolderInput] = useState("");

  // Search state
  const [searchQ, setSearchQ] = useState("");
  const [searchKey, setSearchKey] = useState("");
  const [searchBpmMin, setSearchBpmMin] = useState("");
  const [searchBpmMax, setSearchBpmMax] = useState("");
  const [searchTagInput, setSearchTagInput] = useState("");
  const [searchTags, setSearchTags] = useState<string[]>([]);
  const [searchDirty, setSearchDirty] = useState(false);

  const { data: band, isLoading } = useQuery({
    queryKey: ["band", bandId],
    queryFn: () => getBand(bandId!),
    enabled: !!bandId,
  });

  const { data: sessions } = useQuery({
    queryKey: ["sessions", bandId],
    queryFn: () => api.get<SessionSummary[]>(`/bands/${bandId}/sessions`),
    enabled: !!bandId && tab === "dates",
  });

  const { data: unattributedSongs } = useQuery({
    queryKey: ["songs-unattributed", bandId],
    queryFn: () => api.get<SongSummary[]>(`/bands/${bandId}/songs/search?unattributed=true`),
    enabled: !!bandId && tab === "dates",
  });

  const { data: members } = useQuery({
    queryKey: ["members", bandId],
    queryFn: () => api.get<BandMember[]>(`/bands/${bandId}/members`),
    enabled: !!bandId,
  });

  // Search results — only fetch when user has triggered a search
  const searchParams = new URLSearchParams();
  if (searchQ) searchParams.set("q", searchQ);
  if (searchKey) searchParams.set("key", searchKey);
  if (searchBpmMin) searchParams.set("bpm_min", searchBpmMin);
  if (searchBpmMax) searchParams.set("bpm_max", searchBpmMax);
  searchTags.forEach((t) => searchParams.append("tags", t));

  const { data: searchResults, isFetching: searchFetching } = useQuery({
    queryKey: ["songs-search", bandId, searchParams.toString()],
    queryFn: () => api.get<SongSummary[]>(`/bands/${bandId}/songs/search?${searchParams}`),
    enabled: !!bandId && tab === "search" && searchDirty,
  });

  const createMutation = useMutation({
    mutationFn: () => api.post(`/bands/${bandId}/songs`, { title }),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["sessions", bandId] });
      setShowCreate(false);
      setTitle("");
      setError(null);
    },
    onError: (err) => setError(err instanceof Error ? err.message : "Failed to create song"),
  });

  async function startScan() {
    if (scanning || !bandId) return;
    setScanning(true);
    setScanMsg(null);
    setScanProgress("Starting scan…");

    const token = localStorage.getItem("rh_token");
    const url = `/api/v1/bands/${bandId}/nc-scan/stream${token ? `?token=${encodeURIComponent(token)}` : ""}`;

    try {
      const resp = await fetch(url);
      if (!resp.ok || !resp.body) {
        const text = await resp.text().catch(() => resp.statusText);
        throw new Error(text || `HTTP ${resp.status}`);
      }

      const reader = resp.body.getReader();
      const decoder = new TextDecoder();
      let buf = "";

      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        buf += decoder.decode(value, { stream: true });
        const lines = buf.split("\n");
        buf = lines.pop() ?? "";

        for (const line of lines) {
          if (!line.trim()) continue;
          let event: Record<string, unknown>;
          try { event = JSON.parse(line); } catch { continue; }

          if (event.type === "progress") {
            setScanProgress(event.message as string);
          } else if (event.type === "song" || event.type === "session") {
            qc.invalidateQueries({ queryKey: ["sessions", bandId] });
            qc.invalidateQueries({ queryKey: ["songs-unattributed", bandId] });
          } else if (event.type === "done") {
            const s = event.stats as { found: number; imported: number; skipped: number };
            if (s.imported > 0) {
              setScanMsg(`Imported ${s.imported} new song${s.imported !== 1 ? "s" : ""} (${s.skipped} already registered).`);
            } else if (s.found === 0) {
              setScanMsg("No audio files found.");
            } else {
              setScanMsg(`All ${s.found} file${s.found !== 1 ? "s" : ""} already registered.`);
            }
            setTimeout(() => setScanMsg(null), 6000);
          } else if (event.type === "error") {
            setScanMsg(`Scan error: ${event.message}`);
          }
        }
      }
    } catch (err) {
      setScanMsg(err instanceof Error ? err.message : "Scan failed");
    } finally {
      setScanning(false);
      setScanProgress(null);
    }
  }

  const inviteMutation = useMutation({
    mutationFn: () => api.post<BandInvite>(`/bands/${bandId}/invites`, {}),
    onSuccess: (invite) => {
      const url = `${window.location.origin}/invite/${invite.token}`;
      setInviteLink(url);
      navigator.clipboard.writeText(url).catch(() => {});
    },
  });

  const removeMemberMutation = useMutation({
    mutationFn: (memberId: string) => api.delete(`/bands/${bandId}/members/${memberId}`),
    onSuccess: () => qc.invalidateQueries({ queryKey: ["members", bandId] }),
  });

  const updateFolderMutation = useMutation({
    mutationFn: (nc_folder_path: string) =>
      api.patch(`/bands/${bandId}`, { nc_folder_path }),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["band", bandId] });
      setEditingFolder(false);
    },
  });

  const amAdmin = members?.some((m) => m.role === "admin") ?? false;

  function addTag() {
    const t = searchTagInput.trim();
    if (t && !searchTags.includes(t)) setSearchTags((prev) => [...prev, t]);
    setSearchTagInput("");
  }

  function removeTag(t: string) {
    setSearchTags((prev) => prev.filter((x) => x !== t));
  }

  if (isLoading) return <div style={{ color: "var(--text-muted)", padding: 32 }}>Loading...</div>;
  if (!band) return <div style={{ color: "var(--danger)", padding: 32 }}>Band not found</div>;

  return (
    <div style={{ background: "var(--bg)", minHeight: "100vh", color: "var(--text)", padding: 32 }}>
      <div style={{ maxWidth: 720, margin: "0 auto" }}>
        <Link to="/" style={{ color: "var(--text-muted)", fontSize: 12, textDecoration: "none", display: "inline-block", marginBottom: 20 }}>
          ← All Bands
        </Link>

        {/* Band header */}
        <div style={{ marginBottom: 24 }}>
          <h1 style={{ color: "var(--accent)", fontFamily: "monospace", margin: "0 0 4px" }}>{band.name}</h1>
          {band.genre_tags.length > 0 && (
            <div style={{ display: "flex", gap: 4, marginTop: 8 }}>
              {band.genre_tags.map((t: string) => (
                <span key={t} style={{ background: "var(--teal-bg)", color: "var(--teal)", fontSize: 10, padding: "2px 6px", borderRadius: 3, fontFamily: "monospace" }}>{t}</span>
              ))}
            </div>
          )}
        </div>

        {/* Nextcloud folder */}
        <div style={{ marginBottom: 24, background: "var(--bg-subtle)", border: "1px solid var(--border)", borderRadius: 8, padding: "12px 16px" }}>
          <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8 }}>
            <div>
              <span style={{ color: "var(--text-muted)", fontSize: 11 }}>NEXTCLOUD SCAN FOLDER</span>
              <div style={{ fontFamily: "monospace", color: "var(--teal)", fontSize: 13, marginTop: 4 }}>
                {band.nc_folder_path ?? `bands/${band.slug}/`}
              </div>
            </div>
            {amAdmin && !editingFolder && (
              <button
                onClick={() => { setFolderInput(band.nc_folder_path ?? ""); setEditingFolder(true); }}
                style={{ background: "none", border: "1px solid var(--border)", borderRadius: 6, color: "var(--text-muted)", cursor: "pointer", padding: "4px 10px", fontSize: 11 }}
              >
                Edit
              </button>
            )}
          </div>
          {editingFolder && (
            <div style={{ marginTop: 10 }}>
              <input
                value={folderInput}
                onChange={(e) => setFolderInput(e.target.value)}
                placeholder={`bands/${band.slug}/`}
                style={{ width: "100%", padding: "7px 10px", background: "var(--bg-inset)", border: "1px solid var(--border)", borderRadius: 6, color: "var(--text)", fontSize: 13, fontFamily: "monospace", boxSizing: "border-box" }}
              />
              <div style={{ display: "flex", gap: 8, marginTop: 8 }}>
                <button
                  onClick={() => updateFolderMutation.mutate(folderInput)}
                  disabled={updateFolderMutation.isPending}
                  style={{ background: "var(--teal)", border: "none", borderRadius: 6, color: "var(--bg)", cursor: "pointer", padding: "6px 14px", fontSize: 12, fontWeight: 600 }}
                >
                  Save
                </button>
                <button
                  onClick={() => setEditingFolder(false)}
                  style={{ background: "none", border: "1px solid var(--border)", borderRadius: 6, color: "var(--text-muted)", cursor: "pointer", padding: "6px 14px", fontSize: 12 }}
                >
                  Cancel
                </button>
              </div>
            </div>
          )}
        </div>

        {/* Members */}
        <div style={{ marginBottom: 32 }}>
          <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 12 }}>
            <h2 style={{ color: "var(--text)", margin: 0, fontSize: 16 }}>Members</h2>
            <button
              onClick={() => inviteMutation.mutate()}
              disabled={inviteMutation.isPending}
              style={{ background: "none", border: "1px solid var(--border)", borderRadius: 6, color: "var(--accent)", cursor: "pointer", padding: "6px 14px", fontSize: 12 }}
            >
              + Invite
            </button>
          </div>

          {inviteLink && (
            <div style={{ background: "var(--accent-bg)", border: "1px solid var(--accent)", borderRadius: 6, padding: "10px 14px", marginBottom: 12 }}>
              <p style={{ color: "var(--text-muted)", fontSize: 11, margin: "0 0 6px" }}>Invite link (copied to clipboard, valid 72h):</p>
              <code style={{ color: "var(--accent)", fontSize: 12, wordBreak: "break-all" }}>{inviteLink}</code>
              <button
                onClick={() => setInviteLink(null)}
                style={{ display: "block", marginTop: 8, background: "none", border: "none", color: "var(--text-muted)", cursor: "pointer", fontSize: 11, padding: 0 }}
              >
                Dismiss
              </button>
            </div>
          )}

          <div style={{ display: "grid", gap: 6 }}>
            {members?.map((m) => (
              <div
                key={m.id}
                style={{ background: "var(--bg-subtle)", border: "1px solid var(--border)", borderRadius: 6, padding: "10px 14px", display: "flex", justifyContent: "space-between", alignItems: "center" }}
              >
                <div>
                  <span style={{ fontWeight: 500 }}>{m.display_name}</span>
                  <span style={{ color: "var(--text-muted)", fontSize: 11, marginLeft: 10 }}>{m.email}</span>
                </div>
                <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
                  <span style={{
                    fontSize: 10, fontFamily: "monospace", padding: "2px 6px", borderRadius: 3,
                    background: m.role === "admin" ? "var(--accent-bg)" : "var(--bg-inset)",
                    color: m.role === "admin" ? "var(--accent)" : "var(--text-muted)",
                    border: `1px solid ${m.role === "admin" ? "var(--accent)" : "var(--border)"}`,
                  }}>
                    {m.role}
                  </span>
                  {amAdmin && m.role !== "admin" && (
                    <button
                      onClick={() => removeMemberMutation.mutate(m.id)}
                      style={{ background: "none", border: "none", color: "var(--danger)", cursor: "pointer", fontSize: 11, padding: 0 }}
                    >
                      Remove
                    </button>
                  )}
                </div>
              </div>
            ))}
          </div>
        </div>

        {/* Recordings header */}
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 16 }}>
          <h2 style={{ color: "var(--text)", margin: 0, fontSize: 16 }}>Recordings</h2>
          <div style={{ display: "flex", gap: 8 }}>
            <button
              onClick={startScan}
              disabled={scanning}
              style={{ background: "none", border: "1px solid var(--border)", borderRadius: 6, color: "var(--teal)", cursor: "pointer", padding: "6px 14px", fontSize: 12 }}
            >
              {scanning ? "Scanning…" : "⟳ Scan Nextcloud"}
            </button>
            <button
              onClick={() => { setShowCreate(!showCreate); setError(null); }}
              style={{ background: "var(--accent)", border: "none", borderRadius: 6, color: "var(--accent-fg)", cursor: "pointer", padding: "6px 14px", fontSize: 12, fontWeight: 600 }}
            >
              + New Song
            </button>
          </div>
        </div>

        {scanning && scanProgress && (
          <div style={{ background: "var(--bg-subtle)", border: "1px solid var(--border)", borderRadius: 6, color: "var(--text-muted)", fontSize: 12, padding: "8px 14px", marginBottom: 8, fontFamily: "monospace" }}>
            {scanProgress}
          </div>
        )}
        {scanMsg && (
          <div style={{ background: "var(--teal-bg)", border: "1px solid var(--teal)", borderRadius: 6, color: "var(--teal)", fontSize: 12, padding: "8px 14px", marginBottom: 12 }}>
            {scanMsg}
          </div>
        )}

        {showCreate && (
          <div style={{ background: "var(--bg-subtle)", border: "1px solid var(--border)", borderRadius: 8, padding: 20, marginBottom: 16 }}>
            {error && <p style={{ color: "var(--danger)", fontSize: 13, marginBottom: 12 }}>{error}</p>}
            <label style={{ display: "block", color: "var(--text-muted)", fontSize: 11, marginBottom: 6 }}>SONG TITLE</label>
            <input
              value={title}
              onChange={(e) => setTitle(e.target.value)}
              onKeyDown={(e) => e.key === "Enter" && title && createMutation.mutate()}
              style={{ width: "100%", padding: "8px 12px", background: "var(--bg-inset)", border: "1px solid var(--border)", borderRadius: 6, color: "var(--text)", marginBottom: 12, fontSize: 14, boxSizing: "border-box" }}
              autoFocus
            />
            <div style={{ display: "flex", gap: 8 }}>
              <button
                onClick={() => createMutation.mutate()}
                disabled={!title}
                style={{ background: "var(--accent)", border: "none", borderRadius: 6, color: "var(--accent-fg)", cursor: "pointer", padding: "8px 18px", fontWeight: 600, fontSize: 13 }}
              >
                Create
              </button>
              <button
                onClick={() => { setShowCreate(false); setError(null); }}
                style={{ background: "none", border: "1px solid var(--border)", borderRadius: 6, color: "var(--text-muted)", cursor: "pointer", padding: "8px 18px", fontSize: 13 }}
              >
                Cancel
              </button>
            </div>
          </div>
        )}

        {/* Tabs */}
        <div style={{ display: "flex", gap: 0, marginBottom: 16, borderBottom: "1px solid var(--border)" }}>
          {(["dates", "search"] as const).map((t) => (
            <button
              key={t}
              onClick={() => setTab(t)}
              style={{
                background: "none",
                border: "none",
                borderBottom: `2px solid ${tab === t ? "var(--accent)" : "transparent"}`,
                color: tab === t ? "var(--accent)" : "var(--text-muted)",
                cursor: "pointer",
                padding: "8px 16px",
                fontSize: 13,
                fontWeight: tab === t ? 600 : 400,
                marginBottom: -1,
              }}
            >
              {t === "dates" ? "By Date" : "Search"}
            </button>
          ))}
        </div>

        {/* By Date tab */}
        {tab === "dates" && (
          <div style={{ display: "grid", gap: 6 }}>
            {sessions?.map((s) => (
              <Link
                key={s.id}
                to={`/bands/${bandId}/sessions/${s.id}`}
                style={{
                  background: "var(--bg-inset)",
                  border: "1px solid var(--border)",
                  borderRadius: 8,
                  padding: "14px 18px",
                  textDecoration: "none",
                  color: "var(--text)",
                  display: "flex",
                  justifyContent: "space-between",
                  alignItems: "center",
                  gap: 12,
                }}
              >
                <div>
                  <span style={{ fontFamily: "monospace", color: "var(--text-muted)", fontSize: 10, marginRight: 8 }}>{weekday(s.date)}</span>
                  <span style={{ fontWeight: 500 }}>{formatDate(s.date)}</span>
                  {s.label && (
                    <span style={{ color: "var(--teal)", fontSize: 12, marginLeft: 10 }}>{s.label}</span>
                  )}
                </div>
                <span style={{ color: "var(--text-muted)", fontSize: 12, whiteSpace: "nowrap" }}>
                  {s.recording_count} recording{s.recording_count !== 1 ? "s" : ""}
                </span>
              </Link>
            ))}
            {sessions?.length === 0 && !unattributedSongs?.length && (
              <p style={{ color: "var(--text-muted)", fontSize: 13 }}>
                No sessions yet. Scan Nextcloud to import from <code style={{ color: "var(--teal)" }}>{band.nc_folder_path ?? `bands/${band.slug}/`}</code>.
              </p>
            )}

            {/* Songs not linked to any dated session */}
            {!!unattributedSongs?.length && (
              <div style={{ marginTop: sessions?.length ? 24 : 0 }}>
                <div style={{ color: "var(--text-muted)", fontSize: 11, fontFamily: "monospace", letterSpacing: 1, marginBottom: 8 }}>
                  UNATTRIBUTED RECORDINGS
                </div>
                <div style={{ display: "grid", gap: 6 }}>
                  {unattributedSongs.map((song) => (
                    <Link
                      key={song.id}
                      to={`/bands/${bandId}/songs/${song.id}`}
                      style={{
                        background: "var(--bg-inset)",
                        border: "1px solid var(--border)",
                        borderRadius: 8,
                        padding: "14px 18px",
                        textDecoration: "none",
                        color: "var(--text)",
                        display: "flex",
                        justifyContent: "space-between",
                        alignItems: "center",
                        gap: 12,
                      }}
                    >
                      <div style={{ minWidth: 0 }}>
                        <div style={{ fontWeight: 500, marginBottom: 4 }}>{song.title}</div>
                        <div style={{ display: "flex", gap: 4, flexWrap: "wrap" }}>
                          {song.tags.map((t) => (
                            <span key={t} style={{ background: "var(--teal-bg)", color: "var(--teal)", fontSize: 9, padding: "1px 6px", borderRadius: 3, fontFamily: "monospace" }}>{t}</span>
                          ))}
                        </div>
                      </div>
                      <span style={{ color: "var(--text-muted)", fontSize: 12, whiteSpace: "nowrap" }}>
                        <span style={{ background: "var(--bg-subtle)", borderRadius: 4, padding: "2px 6px", marginRight: 8, fontFamily: "monospace", fontSize: 10 }}>{song.status}</span>
                        {song.version_count} version{song.version_count !== 1 ? "s" : ""}
                      </span>
                    </Link>
                  ))}
                </div>
              </div>
            )}
          </div>
        )}

        {/* Search tab */}
        {tab === "search" && (
          <div>
            {/* Filters */}
            <div style={{ background: "var(--bg-subtle)", border: "1px solid var(--border)", borderRadius: 8, padding: 16, marginBottom: 16 }}>
              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10, marginBottom: 10 }}>
                <div>
                  <label style={{ display: "block", color: "var(--text-muted)", fontSize: 10, marginBottom: 4 }}>TITLE</label>
                  <input
                    value={searchQ}
                    onChange={(e) => setSearchQ(e.target.value)}
                    onKeyDown={(e) => { if (e.key === "Enter") { setSearchDirty(true); qc.invalidateQueries({ queryKey: ["songs-search", bandId] }); } }}
                    placeholder="Search by name…"
                    style={{ width: "100%", padding: "7px 10px", background: "var(--bg-inset)", border: "1px solid var(--border)", borderRadius: 6, color: "var(--text)", fontSize: 13, boxSizing: "border-box" }}
                  />
                </div>
                <div>
                  <label style={{ display: "block", color: "var(--text-muted)", fontSize: 10, marginBottom: 4 }}>KEY</label>
                  <input
                    value={searchKey}
                    onChange={(e) => setSearchKey(e.target.value)}
                    placeholder="e.g. Am, C, F#"
                    style={{ width: "100%", padding: "7px 10px", background: "var(--bg-inset)", border: "1px solid var(--border)", borderRadius: 6, color: "var(--text)", fontSize: 13, boxSizing: "border-box" }}
                  />
                </div>
                <div>
                  <label style={{ display: "block", color: "var(--text-muted)", fontSize: 10, marginBottom: 4 }}>BPM MIN</label>
                  <input
                    value={searchBpmMin}
                    onChange={(e) => setSearchBpmMin(e.target.value)}
                    type="number"
                    min={0}
                    placeholder="e.g. 80"
                    style={{ width: "100%", padding: "7px 10px", background: "var(--bg-inset)", border: "1px solid var(--border)", borderRadius: 6, color: "var(--text)", fontSize: 13, boxSizing: "border-box" }}
                  />
                </div>
                <div>
                  <label style={{ display: "block", color: "var(--text-muted)", fontSize: 10, marginBottom: 4 }}>BPM MAX</label>
                  <input
                    value={searchBpmMax}
                    onChange={(e) => setSearchBpmMax(e.target.value)}
                    type="number"
                    min={0}
                    placeholder="e.g. 140"
                    style={{ width: "100%", padding: "7px 10px", background: "var(--bg-inset)", border: "1px solid var(--border)", borderRadius: 6, color: "var(--text)", fontSize: 13, boxSizing: "border-box" }}
                  />
                </div>
              </div>

              {/* Tag filter */}
              <div>
                <label style={{ display: "block", color: "var(--text-muted)", fontSize: 10, marginBottom: 4 }}>TAGS (must have all)</label>
                <div style={{ display: "flex", gap: 6, flexWrap: "wrap", marginBottom: 6 }}>
                  {searchTags.map((t) => (
                    <span
                      key={t}
                      style={{ background: "var(--teal-bg)", color: "var(--teal)", fontSize: 11, padding: "2px 8px", borderRadius: 12, fontFamily: "monospace", display: "flex", alignItems: "center", gap: 4 }}
                    >
                      {t}
                      <button
                        onClick={() => removeTag(t)}
                        style={{ background: "none", border: "none", color: "var(--teal)", cursor: "pointer", fontSize: 12, padding: 0, lineHeight: 1 }}
                      >×</button>
                    </span>
                  ))}
                </div>
                <div style={{ display: "flex", gap: 6 }}>
                  <input
                    value={searchTagInput}
                    onChange={(e) => setSearchTagInput(e.target.value)}
                    onKeyDown={(e) => e.key === "Enter" && addTag()}
                    placeholder="Add tag…"
                    style={{ flex: 1, padding: "6px 10px", background: "var(--bg-inset)", border: "1px solid var(--border)", borderRadius: 6, color: "var(--text)", fontSize: 12 }}
                  />
                  <button
                    onClick={addTag}
                    style={{ background: "none", border: "1px solid var(--border)", borderRadius: 6, color: "var(--teal)", cursor: "pointer", padding: "6px 10px", fontSize: 12 }}
                  >
                    +
                  </button>
                </div>
              </div>

              <button
                onClick={() => { setSearchDirty(true); qc.invalidateQueries({ queryKey: ["songs-search", bandId] }); }}
                style={{ marginTop: 12, background: "var(--accent)", border: "none", borderRadius: 6, color: "var(--accent-fg)", cursor: "pointer", padding: "7px 18px", fontSize: 13, fontWeight: 600 }}
              >
                Search
              </button>
            </div>

            {/* Results */}
            {searchFetching && <p style={{ color: "var(--text-muted)", fontSize: 13 }}>Searching…</p>}
            {!searchFetching && searchDirty && (
              <div style={{ display: "grid", gap: 8 }}>
                {searchResults?.map((song) => (
                  <Link
                    key={song.id}
                    to={`/bands/${bandId}/songs/${song.id}`}
                    style={{
                      background: "var(--bg-inset)",
                      border: "1px solid var(--border)",
                      borderRadius: 8,
                      padding: "14px 18px",
                      textDecoration: "none",
                      color: "var(--text)",
                      display: "flex",
                      justifyContent: "space-between",
                      alignItems: "center",
                      gap: 12,
                    }}
                  >
                    <div style={{ minWidth: 0 }}>
                      <div style={{ fontWeight: 500, marginBottom: 4 }}>{song.title}</div>
                      <div style={{ display: "flex", gap: 4, flexWrap: "wrap" }}>
                        {song.tags.map((t) => (
                          <span key={t} style={{ background: "var(--teal-bg)", color: "var(--teal)", fontSize: 9, padding: "1px 6px", borderRadius: 3, fontFamily: "monospace" }}>{t}</span>
                        ))}
                        {song.global_key && (
                          <span style={{ background: "var(--bg-subtle)", color: "var(--text-muted)", fontSize: 9, padding: "1px 6px", borderRadius: 3, fontFamily: "monospace" }}>{song.global_key}</span>
                        )}
                        {song.global_bpm && (
                          <span style={{ background: "var(--bg-subtle)", color: "var(--text-muted)", fontSize: 9, padding: "1px 6px", borderRadius: 3, fontFamily: "monospace" }}>{song.global_bpm.toFixed(0)} BPM</span>
                        )}
                      </div>
                    </div>
                    <div style={{ color: "var(--text-muted)", fontSize: 12, whiteSpace: "nowrap" }}>
                      <span style={{ background: "var(--bg-subtle)", borderRadius: 4, padding: "2px 6px", marginRight: 8, fontFamily: "monospace", fontSize: 10 }}>{song.status}</span>
                      {song.version_count} version{song.version_count !== 1 ? "s" : ""}
                    </div>
                  </Link>
                ))}
                {searchResults?.length === 0 && (
                  <p style={{ color: "var(--text-muted)", fontSize: 13 }}>No songs match your filters.</p>
                )}
              </div>
            )}
            {!searchDirty && (
              <p style={{ color: "var(--text-muted)", fontSize: 13 }}>Enter filters above and hit Search.</p>
            )}
          </div>
        )}
      </div>
    </div>
  );
}
