import { useRef, useState } from "react"
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
import { Link } from "wouter"
import { Eye, EyeOff, Trash2, Upload } from "lucide-react"
import type { QuizFormat } from "@nerdware/shared"
import { Button } from "@workspace/ui/components/button"
import {
  Tooltip,
  TooltipContent,
  TooltipTrigger,
} from "@workspace/ui/components/tooltip"
import {
  adminApi,
  assetUrl,
  clearAdminToken,
  getAdminToken,
  setAdminToken,
  type AdminQuestion,
  type NewQuestionInput,
} from "@/lib/admin-api"

const inputClass =
  "border-input bg-background h-10 w-full rounded-md border px-3 py-2 text-sm focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none"

export function AdminPage() {
  const [token, setToken] = useState(getAdminToken())

  if (!token) {
    return <Login onAuth={setToken} />
  }
  return (
    <AdminPanel
      onLogout={() => {
        clearAdminToken()
        setToken("")
      }}
    />
  )
}

function Login({ onAuth }: { onAuth: (token: string) => void }) {
  const [value, setValue] = useState("")
  return (
    <div className="flex min-h-svh items-center justify-center p-6">
      <div className="flex w-full max-w-xs flex-col gap-4">
        <h1 className="font-heading text-center text-2xl font-bold">
          Back-office quiz
        </h1>
        <input
          type="password"
          className={inputClass}
          placeholder="Jeton admin"
          value={value}
          onChange={(e) => setValue(e.target.value)}
          onKeyDown={(e) => {
            if (e.key === "Enter" && value.trim()) {
              setAdminToken(value.trim())
              onAuth(value.trim())
            }
          }}
        />
        <Button
          disabled={!value.trim()}
          onClick={() => {
            setAdminToken(value.trim())
            onAuth(value.trim())
          }}
        >
          Entrer
        </Button>
        <Link href="/">
          <Button variant="secondary" className="w-full">
            Retour
          </Button>
        </Link>
      </div>
    </div>
  )
}

function AdminPanel({ onLogout }: { onLogout: () => void }) {
  const qc = useQueryClient()
  const questions = useQuery({
    queryKey: ["admin-questions"],
    queryFn: adminApi.listQuestions,
    retry: false,
  })

  const remove = useMutation({
    mutationFn: adminApi.deleteQuestion,
    onSuccess: () => qc.invalidateQueries({ queryKey: ["admin-questions"] }),
  })

  const toggle = useMutation({
    mutationFn: ({ id, active }: { id: string; active: boolean }) =>
      adminApi.setActive(id, active),
    onSuccess: () => qc.invalidateQueries({ queryKey: ["admin-questions"] }),
  })

  const unauthorized =
    questions.isError && /401|autoris/i.test(String(questions.error))

  return (
    <div className="mx-auto flex min-h-svh w-full max-w-5xl flex-col gap-6 p-6">
      <header className="flex items-center justify-between">
        <h1 className="font-heading text-2xl font-bold">Back-office quiz</h1>
        <Button size="sm" variant="secondary" onClick={onLogout}>
          Déconnexion
        </Button>
      </header>

      {unauthorized ? (
        <p className="text-destructive text-sm">
          Jeton invalide ou back-office indisponible.{" "}
          <button className="underline" onClick={onLogout}>
            Réessayer
          </button>
        </p>
      ) : (
        <div className="grid gap-6 md:grid-cols-2 md:items-start">
          <QuestionForm
            onCreated={() =>
              qc.invalidateQueries({ queryKey: ["admin-questions"] })
            }
          />

          <section className="flex flex-col gap-2">
            <h2 className="text-muted-foreground text-sm font-medium">
              Questions ({questions.data?.length ?? 0})
            </h2>
            {questions.isLoading && (
              <p className="text-muted-foreground text-sm">Chargement…</p>
            )}
            <ul className="flex flex-col gap-2">
              {questions.data?.map((q) => (
                <QuestionRow
                  key={q.id}
                  q={q}
                  onDelete={() => remove.mutate(q.id)}
                  onToggle={() => toggle.mutate({ id: q.id, active: !q.active })}
                  deleting={remove.isPending}
                />
              ))}
            </ul>
          </section>
        </div>
      )}
    </div>
  )
}

function QuestionRow({
  q,
  onDelete,
  onToggle,
  deleting,
}: {
  q: AdminQuestion
  onDelete: () => void
  onToggle: () => void
  deleting: boolean
}) {
  return (
    <li
      className={`bg-muted/40 flex items-start justify-between gap-3 rounded-lg p-3 ${
        q.active ? "" : "opacity-50"
      }`}
    >
      {q.format === "image_reveal" && q.imageUrl && (
        <img
          src={assetUrl(q.imageUrl)}
          alt=""
          className="h-12 w-12 shrink-0 rounded object-cover"
        />
      )}
      <div className="min-w-0 flex-1">
        <p className="text-sm font-medium">{q.prompt}</p>
        <p className="text-muted-foreground text-xs">
          {q.format} · {q.category ?? "—"} · diff. {q.difficulty} ·{" "}
          {q.lang.toUpperCase()} · {q.source}
          {!q.active && " · désactivée"}
        </p>
        {q.format === "free" ||
        q.format === "image_reveal" ||
        q.format === "rebus" ? (
          <p className="text-muted-foreground text-xs">
            ✔ {q.acceptedAnswers?.join(", ")}
          </p>
        ) : (
          <p className="text-muted-foreground text-xs">
            {q.choices
              ?.map((c, i) => (i === q.correctIndex ? `✔ ${c}` : c))
              .join(" · ")}
          </p>
        )}
      </div>
      <Tooltip>
        <TooltipTrigger asChild>
          <Button size="icon-sm" variant="secondary" onClick={onToggle}>
            {q.active ? <Eye /> : <EyeOff />}
          </Button>
        </TooltipTrigger>
        <TooltipContent>{q.active ? "Désactiver" : "Activer"}</TooltipContent>
      </Tooltip>
      <Button
        size="icon-sm"
        variant="secondary"
        disabled={deleting}
        onClick={onDelete}
      >
        <Trash2 />
      </Button>
    </li>
  )
}

const EMPTY_CHOICES = ["", "", "", ""]

function QuestionForm({ onCreated }: { onCreated: () => void }) {
  const [format, setFormat] = useState<QuizFormat>("mcq")
  const [prompt, setPrompt] = useState("")
  const [category, setCategory] = useState("")
  const [difficulty, setDifficulty] = useState(1)
  const [lang, setLang] = useState("fr")
  const [choices, setChoices] = useState<string[]>(EMPTY_CHOICES)
  const [correctIndex, setCorrectIndex] = useState(0)
  const [answers, setAnswers] = useState("")
  const [imageUrl, setImageUrl] = useState<string | null>(null)
  const [uploading, setUploading] = useState(false)
  const [uploadError, setUploadError] = useState<string | null>(null)
  const fileInputRef = useRef<HTMLInputElement>(null)

  const create = useMutation({
    mutationFn: (input: NewQuestionInput) => adminApi.createQuestion(input),
    onSuccess: () => {
      setPrompt("")
      setChoices(EMPTY_CHOICES)
      setCorrectIndex(0)
      setAnswers("")
      setImageUrl(null)
      onCreated()
    },
  })

  async function onPickImage(file: File | undefined) {
    if (!file) {
      return
    }
    setUploading(true)
    setUploadError(null)
    try {
      const { url } = await adminApi.uploadImage(file)
      setImageUrl(url)
    } catch (err) {
      setUploadError((err as { message?: string }).message ?? "Échec de l'upload")
    } finally {
      setUploading(false)
    }
  }

  function submit() {
    const input: NewQuestionInput = { format, prompt, category, difficulty, lang }
    if (format === "free" || format === "rebus") {
      input.acceptedAnswers = answers
        .split("\n")
        .map((a) => a.trim())
        .filter(Boolean)
    } else if (format === "image_reveal") {
      input.acceptedAnswers = answers
        .split("\n")
        .map((a) => a.trim())
        .filter(Boolean)
      input.imageUrl = imageUrl ?? undefined
    } else if (format === "truefalse") {
      input.choices = ["Vrai", "Faux"]
      input.correctIndex = correctIndex
    } else {
      input.choices = choices.map((c) => c.trim()).filter(Boolean)
      input.correctIndex = correctIndex
    }
    create.mutate(input)
  }

  return (
    <section className="flex flex-col gap-3 rounded-xl border p-4">
      <h2 className="text-sm font-medium">Nouvelle question</h2>

      <div className="flex gap-2">
        <select
          className={inputClass}
          value={format}
          onChange={(e) => {
            setFormat(e.target.value as QuizFormat)
            setCorrectIndex(0)
          }}
        >
          <option value="mcq">QCM</option>
          <option value="truefalse">Vrai / Faux</option>
          <option value="free">Réponse libre</option>
          <option value="image_reveal">Image à deviner</option>
          <option value="rebus">Rébus</option>
        </select>
        <select
          className={inputClass}
          value={difficulty}
          onChange={(e) => setDifficulty(Number(e.target.value))}
        >
          <option value={1}>Facile</option>
          <option value={2}>Moyen</option>
          <option value={3}>Difficile</option>
        </select>
        <select
          className={inputClass}
          value={lang}
          onChange={(e) => setLang(e.target.value)}
        >
          <option value="fr">FR</option>
          <option value="en">EN</option>
        </select>
      </div>

      <input
        className={inputClass}
        placeholder="Catégorie (ex: Jeux vidéo)"
        value={category}
        onChange={(e) => setCategory(e.target.value)}
      />
      <input
        className={inputClass}
        placeholder={
          format === "image_reveal"
            ? "Intitulé (optionnel — déf. « Qui est-ce ? »)"
            : "Intitulé de la question"
        }
        value={prompt}
        onChange={(e) => setPrompt(e.target.value)}
      />

      {format === "mcq" && (
        <div className="flex flex-col gap-2">
          {choices.map((choice, i) => (
            <label key={i} className="flex items-center gap-2">
              <input
                type="radio"
                name="correct"
                checked={correctIndex === i}
                onChange={() => setCorrectIndex(i)}
              />
              <input
                className={inputClass}
                placeholder={`Choix ${i + 1}`}
                value={choice}
                onChange={(e) =>
                  setChoices((c) =>
                    c.map((x, j) => (j === i ? e.target.value : x))
                  )
                }
              />
            </label>
          ))}
          <p className="text-muted-foreground text-xs">
            Coche la bonne réponse. Les choix vides sont ignorés (min. 2).
          </p>
        </div>
      )}

      {format === "truefalse" && (
        <div className="flex gap-4">
          {["Vrai", "Faux"].map((label, i) => (
            <label key={label} className="flex items-center gap-2 text-sm">
              <input
                type="radio"
                name="correct"
                checked={correctIndex === i}
                onChange={() => setCorrectIndex(i)}
              />
              {label}
            </label>
          ))}
        </div>
      )}

      {format === "image_reveal" && (
        <div className="flex flex-col gap-2">
          <input
            ref={fileInputRef}
            type="file"
            accept="image/*"
            className="hidden"
            onChange={(e) => onPickImage(e.target.files?.[0])}
          />
          <Button
            type="button"
            variant="secondary"
            disabled={uploading}
            onClick={() => fileInputRef.current?.click()}
          >
            <Upload />
            {uploading
              ? "Upload…"
              : imageUrl
                ? "Changer l'image"
                : "Choisir une image"}
          </Button>
          {uploadError && (
            <p className="text-destructive text-xs">{uploadError}</p>
          )}
          {imageUrl && (
            <img
              src={assetUrl(imageUrl)}
              alt=""
              className="max-h-40 w-fit rounded-md object-contain"
            />
          )}
        </div>
      )}

      {(format === "free" || format === "image_reveal" || format === "rebus") && (
        <textarea
          className={`${inputClass} h-24 py-2`}
          placeholder="Réponses acceptées (une par ligne)"
          value={answers}
          onChange={(e) => setAnswers(e.target.value)}
        />
      )}

      {create.isError && (
        <p className="text-destructive text-sm">{String(create.error)}</p>
      )}

      <Button
        disabled={
          create.isPending ||
          uploading ||
          (!prompt.trim() && format !== "image_reveal") ||
          !category.trim() ||
          (format === "image_reveal" && !imageUrl)
        }
        onClick={submit}
      >
        {create.isPending ? "Ajout…" : "Ajouter la question"}
      </Button>
    </section>
  )
}
