import { createFileRoute } from "@tanstack/react-router";
import { queryOptions, useSuspenseQuery, useQueryClient } from "@tanstack/react-query";
import { useRef, useState } from "react";
import { useServerFn } from "@tanstack/react-start";
import { listProofs, createProof, updateProof, deleteProof } from "@/lib/admin.functions";
import { toast } from "sonner";
import { Trash2, Upload, ArrowUp, ArrowDown, Save } from "lucide-react";

const q = queryOptions({ queryKey: ["admin-proofs"], queryFn: () => listProofs() });

export const Route = createFileRoute("/_authenticated/admin/proofs")({
  loader: ({ context }) => context.queryClient.ensureQueryData(q),
  component: AdminProofs,
});

function fileToBase64(file: File): Promise<string> {
  return new Promise((resolve, reject) => {
    const r = new FileReader();
    r.onload = () => {
      const s = String(r.result);
      resolve(s.split(",")[1] ?? "");
    };
    r.onerror = reject;
    r.readAsDataURL(file);
  });
}

function AdminProofs() {
  const { data } = useSuspenseQuery(q);
  const qc = useQueryClient();
  const createFn = useServerFn(createProof);
  const updateFn = useServerFn(updateProof);
  const deleteFn = useServerFn(deleteProof);
  const fileRef = useRef<HTMLInputElement>(null);
  const [caption, setCaption] = useState("");
  const [uploading, setUploading] = useState(false);

  const refresh = () => { qc.invalidateQueries({ queryKey: ["admin-proofs"] }); qc.invalidateQueries({ queryKey: ["landing"] }); };

  const upload = async (file: File) => {
    if (file.size > 5 * 1024 * 1024) { toast.error("Max 5 MB per image"); return; }
    setUploading(true);
    try {
      const fileBase64 = await fileToBase64(file);
      await createFn({ data: { fileName: file.name, fileBase64, contentType: file.type || "image/jpeg", caption: caption || null } });
      toast.success("Uploaded");
      setCaption("");
      if (fileRef.current) fileRef.current.value = "";
      refresh();
    } catch (e: any) { toast.error(e.message); }
    finally { setUploading(false); }
  };

  const onPickFile = (e: React.ChangeEvent<HTMLInputElement>) => {
    const f = e.target.files?.[0]; if (f) upload(f);
  };

  const move = async (idx: number, dir: -1 | 1) => {
    const a = data.proofs[idx]; const b = data.proofs[idx + dir];
    if (!a || !b) return;
    await Promise.all([
      updateFn({ data: { id: a.id, position: b.position } }),
      updateFn({ data: { id: b.id, position: a.position } }),
    ]);
    refresh();
  };

  const toggle = async (id: string, is_published: boolean) => {
    await updateFn({ data: { id, is_published: !is_published } });
    refresh();
  };

  const saveCaption = async (id: string, value: string) => {
    await updateFn({ data: { id, caption: value || null } });
    toast.success("Saved");
    refresh();
  };

  const remove = async (id: string) => {
    if (!confirm("Delete this screenshot?")) return;
    await deleteFn({ data: { id } });
    toast.success("Deleted");
    refresh();
  };

  return (
    <div>
      <div className="mb-6">
        <h1 className="font-display text-3xl font-bold">Student Proofs</h1>
        <p className="mt-1 text-sm text-muted-foreground">Upload inbox screenshots to build trust on the landing page.</p>
      </div>

      <div className="mb-8 rounded-2xl border border-border bg-card p-5">
        <h2 className="font-semibold">Upload new screenshot</h2>
        <div className="mt-3 grid gap-3 sm:grid-cols-[1fr_auto]">
          <input value={caption} onChange={(e) => setCaption(e.target.value)} placeholder="Optional caption" className="rounded-lg border border-border bg-input px-3 py-2.5 text-sm" />
          <input ref={fileRef} type="file" accept="image/*" onChange={onPickFile} className="hidden" />
          <button disabled={uploading} onClick={() => fileRef.current?.click()} className="inline-flex items-center justify-center gap-2 rounded-lg bg-gradient-primary px-5 py-2.5 text-sm font-semibold text-primary-foreground shadow-glow disabled:opacity-60">
            <Upload className="h-4 w-4" /> {uploading ? "Uploading…" : "Upload image"}
          </button>
        </div>
        <p className="mt-2 text-xs text-muted-foreground">Recommended: portrait screenshots. Max 5 MB.</p>
      </div>

      <div className="grid gap-4 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
        {data.proofs.map((p, i) => (
          <div key={p.id} className="rounded-2xl border border-border bg-card p-3">
            {p.signed_url ? (
              <img src={p.signed_url} alt="" loading="lazy" className="aspect-[9/16] w-full rounded-xl object-cover" />
            ) : (
              <div className="grid aspect-[9/16] place-items-center rounded-xl bg-muted text-xs text-muted-foreground">No preview</div>
            )}
            <CaptionRow defaultValue={p.caption ?? ""} onSave={(v) => saveCaption(p.id, v)} />
            <div className="mt-2 flex items-center justify-between gap-1">
              <div className="flex gap-1">
                <button onClick={() => move(i, -1)} disabled={i === 0} className="rounded-md border border-border p-1.5 disabled:opacity-40"><ArrowUp className="h-3.5 w-3.5" /></button>
                <button onClick={() => move(i, 1)} disabled={i === data.proofs.length - 1} className="rounded-md border border-border p-1.5 disabled:opacity-40"><ArrowDown className="h-3.5 w-3.5" /></button>
              </div>
              <label className="inline-flex items-center gap-1.5 text-xs">
                <input type="checkbox" checked={p.is_published} onChange={() => toggle(p.id, p.is_published)} /> Live
              </label>
              <button onClick={() => remove(p.id)} className="rounded-md bg-destructive/15 p-1.5 text-destructive"><Trash2 className="h-3.5 w-3.5" /></button>
            </div>
          </div>
        ))}
        {data.proofs.length === 0 && (
          <div className="col-span-full rounded-2xl border border-dashed border-border p-10 text-center text-sm text-muted-foreground">
            No screenshots yet. Upload your first proof above.
          </div>
        )}
      </div>
    </div>
  );
}

function CaptionRow({ defaultValue, onSave }: { defaultValue: string; onSave: (v: string) => void }) {
  const [v, setV] = useState(defaultValue);
  return (
    <div className="mt-2 flex gap-1">
      <input value={v} onChange={(e) => setV(e.target.value)} placeholder="Caption" className="flex-1 rounded-md border border-border bg-input px-2 py-1.5 text-xs" />
      <button onClick={() => onSave(v)} className="rounded-md bg-success px-2 py-1.5 text-success-foreground"><Save className="h-3.5 w-3.5" /></button>
    </div>
  );
}
