import { useMemo, useState, useRef } from "react";
import { useQuery, useMutation } from "@tanstack/react-query";
import { apiRequest, queryClient } from "@/lib/queryClient";
import type { Recording } from "@shared/schema";
import { WaveformIcon } from "@/components/Waveform";
import { formatDuration, groupByDay, formatDate } from "@/lib/format";
import { Search, Star, Trash2, Share2, X } from "lucide-react";
import { useLocation } from "wouter";
import { useApp } from "@/lib/app-context";
import { ShareSheet } from "@/components/ShareSheet";

type FilterKey = "all" | "starred" | "week";

export default function LibraryPage() {
  const { data: recordings = [], isLoading } = useQuery<Recording[]>({ queryKey: ["/api/recordings"] });
  const [query, setQuery] = useState("");
  const [filter, setFilter] = useState<FilterKey>("all");
  const [, navigate] = useLocation();
  const { showSnackbar } = useApp();
  const [shareTarget, setShareTarget] = useState<Recording | null>(null);

  const deleteMutation = useMutation({
    mutationFn: async (id: number) => apiRequest("DELETE", `/api/recordings/${id}`),
    onSuccess: () => queryClient.invalidateQueries({ queryKey: ["/api/recordings"] }),
  });

  const filtered = useMemo(() => {
    let list = recordings;
    if (query.trim()) {
      const q = query.toLowerCase();
      list = list.filter((r) => r.title.toLowerCase().includes(q));
    }
    if (filter === "starred") list = list.filter((r) => r.starred === 1);
    if (filter === "week") {
      const weekAgo = Date.now() - 7 * 24 * 60 * 60 * 1000;
      list = list.filter((r) => r.createdAt >= weekAgo);
    }
    return list;
  }, [recordings, query, filter]);

  // Group by day section
  const groups = useMemo(() => {
    const buckets: Record<string, Recording[]> = { Heute: [], Gestern: [], "Diese Woche": [], "Älter": [] };
    for (const r of filtered) {
      const key = groupByDay(r.createdAt);
      buckets[key].push(r);
    }
    return buckets;
  }, [filtered]);

  const handleDelete = async (rec: Recording) => {
    await deleteMutation.mutateAsync(rec.id);
    showSnackbar({ message: `„${rec.title}“ gelöscht` });
  };

  return (
    <div className="flex flex-col h-full">
      <header className="px-5 pt-3 pb-3">
        <h1 className="text-lg font-semibold tracking-tight">Bibliothek</h1>
        <p className="text-xs text-muted-foreground mt-0.5">{recordings.length} Aufnahmen</p>
      </header>

      <div className="px-4 space-y-3 pb-3">
        {/* Search */}
        <div className="relative">
          <Search className="w-4 h-4 absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground pointer-events-none" />
          <input
            type="search"
            value={query}
            onChange={(e) => setQuery(e.target.value)}
            placeholder="Aufnahmen durchsuchen"
            className="w-full h-11 pl-9 pr-9 rounded-xl bg-secondary text-secondary-foreground placeholder:text-muted-foreground text-sm outline-none focus:ring-2 focus:ring-primary/40"
            data-testid="input-search"
          />
          {query && (
            <button
              onClick={() => setQuery("")}
              className="absolute right-2 top-1/2 -translate-y-1/2 w-7 h-7 flex items-center justify-center rounded-full text-muted-foreground"
              aria-label="Suche leeren"
            >
              <X className="w-4 h-4" />
            </button>
          )}
        </div>

        {/* Filter chips */}
        <div className="flex gap-2 overflow-x-auto no-scrollbar -mx-1 px-1">
          {([
            { k: "all" as FilterKey, l: "Alle" },
            { k: "starred" as FilterKey, l: "Markiert" },
            { k: "week" as FilterKey, l: "Diese Woche" },
          ]).map((c) => (
            <button
              key={c.k}
              onClick={() => setFilter(c.k)}
              className={`shrink-0 h-8 px-3 rounded-full text-xs font-medium transition ${
                filter === c.k
                  ? "bg-foreground text-background"
                  : "bg-secondary text-foreground/80 hover-elevate"
              }`}
              data-testid={`chip-filter-${c.k}`}
            >
              {c.l}
            </button>
          ))}
        </div>
      </div>

      {/* List */}
      <div className="flex-1 overflow-y-auto px-4 pb-4 no-scrollbar" data-testid="library-list">
        {isLoading && <p className="text-center text-sm text-muted-foreground py-10">Lade…</p>}
        {!isLoading && filtered.length === 0 && (
          <div className="text-center py-14 text-muted-foreground">
            <p className="text-sm">Keine Aufnahmen gefunden</p>
          </div>
        )}
        {(["Heute", "Gestern", "Diese Woche", "Älter"] as const).map((section) => {
          const items = groups[section];
          if (!items || items.length === 0) return null;
          return (
            <section key={section} className="mb-5">
              <h2 className="text-[11px] uppercase tracking-wider text-muted-foreground font-medium px-1 mb-2">
                {section}
              </h2>
              <ul className="space-y-1.5">
                {items.map((rec) => (
                  <RecordingRow
                    key={rec.id}
                    rec={rec}
                    onTap={() => navigate(`/aufnahme/${rec.id}`)}
                    onDelete={() => handleDelete(rec)}
                    onShare={() => setShareTarget(rec)}
                  />
                ))}
              </ul>
            </section>
          );
        })}
      </div>

      {shareTarget && <ShareSheet recording={shareTarget} onClose={() => setShareTarget(null)} />}
    </div>
  );
}

function RecordingRow({
  rec,
  onTap,
  onDelete,
  onShare,
}: {
  rec: Recording;
  onTap: () => void;
  onDelete: () => void;
  onShare: () => void;
}) {
  const [offset, setOffset] = useState(0);
  const [revealed, setRevealed] = useState<"none" | "delete" | "share">("none");
  const startX = useRef<number | null>(null);
  const startOffset = useRef(0);
  const moved = useRef(false);

  const SWIPE_THRESHOLD = 70;
  const MAX = 100;

  const waveformArr = useMemo<number[]>(() => {
    try {
      return JSON.parse(rec.waveform);
    } catch {
      return [];
    }
  }, [rec.waveform]);

  const onPointerDown = (e: React.PointerEvent) => {
    startX.current = e.clientX;
    startOffset.current = offset;
    moved.current = false;
    (e.target as HTMLElement).setPointerCapture(e.pointerId);
  };

  const onPointerMove = (e: React.PointerEvent) => {
    if (startX.current === null) return;
    const delta = e.clientX - startX.current;
    if (Math.abs(delta) > 6) moved.current = true;
    let next = startOffset.current + delta;
    next = Math.max(-MAX, Math.min(MAX, next));
    setOffset(next);
  };

  const onPointerUp = () => {
    if (startX.current === null) return;
    startX.current = null;
    if (offset <= -SWIPE_THRESHOLD) {
      setOffset(-MAX);
      setRevealed("delete");
    } else if (offset >= SWIPE_THRESHOLD) {
      setOffset(MAX);
      setRevealed("share");
    } else {
      setOffset(0);
      setRevealed("none");
    }
  };

  const handleTap = () => {
    if (moved.current) return;
    if (revealed !== "none") {
      setOffset(0);
      setRevealed("none");
      return;
    }
    onTap();
  };

  return (
    <li className="relative rounded-xl overflow-hidden bg-card border border-card-border" data-testid={`row-recording-${rec.id}`}>
      {/* Action backgrounds */}
      <div className="absolute inset-0 flex">
        <div className="flex-1 bg-[hsl(220,9%,17%)] flex items-center justify-start pl-5">
          <button onClick={onShare} className="flex items-center gap-2 text-blue-400 font-medium text-sm" data-testid={`button-share-${rec.id}`}>
            <Share2 className="w-4 h-4" />
            Teilen
          </button>
        </div>
        <div className="flex-1 bg-destructive flex items-center justify-end pr-5">
          <button onClick={onDelete} className="flex items-center gap-2 text-destructive-foreground font-medium text-sm" data-testid={`button-delete-${rec.id}`}>
            <Trash2 className="w-4 h-4" />
            Löschen
          </button>
        </div>
      </div>

      {/* Foreground card */}
      <div
        className="relative bg-card touch-pan-y"
        style={{
          transform: `translateX(${offset}px)`,
          transition: startX.current === null ? "transform 220ms cubic-bezier(0.32,0.72,0,1)" : "none",
          // When fully revealed, ignore taps so the underlying action button receives clicks.
          pointerEvents: revealed !== "none" ? "none" : undefined,
        }}
        onPointerDown={onPointerDown}
        onPointerMove={onPointerMove}
        onPointerUp={onPointerUp}
        onPointerCancel={onPointerUp}
        onClick={handleTap}
      >
        <div className="flex items-center gap-3 px-4 py-3">
          <div className="w-14 h-10 flex items-center justify-center text-muted-foreground shrink-0">
            <WaveformIcon bars={waveformArr.length ? waveformArr : [0.3, 0.6, 0.9, 0.5, 0.8, 0.4, 0.7]} />
          </div>
          <div className="flex-1 min-w-0">
            <div className="flex items-center gap-1.5">
              <p className="text-sm font-medium truncate" data-testid={`text-title-${rec.id}`}>{rec.title}</p>
              {rec.starred === 1 && <Star className="w-3 h-3 text-amber-400 fill-amber-400 shrink-0" />}
            </div>
            <p className="text-xs text-muted-foreground mt-0.5 tabular-nums">
              {formatDate(rec.createdAt)} · {formatDuration(rec.durationSec)}
            </p>
          </div>
        </div>
      </div>
    </li>
  );
}
