import { useEffect, useState } from "react";
import { listSamples, sampleDownloadUrl } from "@/lib/api";
import type { SampleAudio } from "@/types/inference";
import { useInferenceStore } from "@/store/inferenceStore";
import { cn } from "@/lib/utils";
import { CheckCircle2, Music2 } from "lucide-react";

export default function SampleLibrary() {
  const [samples, setSamples] = useState<SampleAudio[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const audio = useInferenceStore((s) => s.audio);
  const setAudio = useInferenceStore((s) => s.setAudio);

  useEffect(() => {
    let alive = true;
    listSamples()
      .then((r) => {
        if (alive) setSamples(r.samples);
      })
      .catch((e) => {
        if (alive)
          setError(
            e instanceof Error ? e.message : "Could not load sample list."
          );
      })
      .finally(() => alive && setLoading(false));
    return () => {
      alive = false;
    };
  }, []);

  if (loading) {
    return (
      <div className="font-mono text-xs text-ink-dim">loading samples…</div>
    );
  }
  if (error) {
    return <div className="font-mono text-xs text-danger">{error}</div>;
  }

  const reals = samples.filter((s) => s.label === "real");
  const fakes = samples.filter((s) => s.label === "fake");

  return (
    <div>
      <div className="mb-3 flex items-center justify-between">
        <div className="label">sample library</div>
        <span className="font-mono text-[10px] text-ink-mute">
          {samples.length} clips
        </span>
      </div>

      <SampleGroup title="real" tint="cyber" items={reals} audio={audio} setAudio={setAudio} />
      <div className="my-3 border-t border-line/60" />
      <SampleGroup title="fake" tint="danger" items={fakes} audio={audio} setAudio={setAudio} />

      <div className="mt-3 font-mono text-[10px] text-ink-mute">
        Tip: drop your own real-world WAVs into{" "}
        <code className="font-mono">data/sample_audios/</code> to add them here.
      </div>
    </div>
  );
}

function SampleGroup({
  title,
  tint,
  items,
  audio,
  setAudio,
}: {
  title: string;
  tint: "cyber" | "danger";
  items: SampleAudio[];
  audio: ReturnType<typeof useInferenceStore.getState>["audio"];
  setAudio: ReturnType<typeof useInferenceStore.getState>["setAudio"];
}) {
  return (
    <div>
      <div className="mb-1.5 flex items-center gap-1.5">
        <span
          className={cn(
            "h-1.5 w-1.5 rounded-full",
            tint === "danger" ? "bg-danger" : "bg-cyber"
          )}
        />
        <span className="font-mono text-[10px] uppercase tracking-wider text-ink-dim">
          {title} · {items.length}
        </span>
      </div>
      <div className="grid gap-1.5">
        {items.map((s) => {
          const isSelected =
            audio?.kind === "sample" && audio.sampleId === s.sample_id;
          return (
            <button
              key={s.sample_id}
              onClick={() =>
                setAudio({
                  kind: "sample",
                  sampleId: s.sample_id,
                  url: sampleDownloadUrl(s.sample_id),
                })
              }
              className={cn(
                "group flex items-start justify-between gap-2 rounded-md border bg-surface-alt/50 px-2.5 py-2 text-left transition-all duration-150",
                "hover:bg-surface-alt hover:translate-x-0.5",
                isSelected
                  ? tint === "danger"
                    ? "border-danger/60 bg-danger/10"
                    : "border-cyber/60 bg-cyber/10"
                  : "border-line"
              )}
            >
              <div className="flex min-w-0 items-start gap-2">
                <Music2
                  className={cn(
                    "mt-0.5 h-3.5 w-3.5 shrink-0 transition-transform group-hover:scale-110",
                    tint === "danger" ? "text-danger" : "text-cyber"
                  )}
                />
                <div className="min-w-0">
                  <div className="truncate font-mono text-[11px] text-ink">
                    {s.filename.replace(/\.wav$/, "")}
                  </div>
                  <div className="mt-0.5 truncate text-[10px] text-ink-dim">
                    {s.description}
                  </div>
                </div>
              </div>
              {isSelected && (
                <CheckCircle2
                  className={cn(
                    "h-3.5 w-3.5 shrink-0",
                    tint === "danger" ? "text-danger" : "text-cyber"
                  )}
                />
              )}
            </button>
          );
        })}
      </div>
    </div>
  );
}
