import { useEffect, useState } from "react";
import { useQuery } from "@tanstack/react-query";
import { useTranslation } from "react-i18next";
import { Library, Loader2 } from "lucide-react";

import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Checkbox } from "@/components/ui/checkbox";
import { Skeleton } from "@/components/ui/skeleton";

import { resourcesService } from "@/services/resources.service";
import type { Resource } from "@/types";

/**
 * Generic, reusable picker over `/api/resources`.
 *
 * Two callers wire this up today:
 *
 * 1. **AdminCoursePlanDetail** — for an *existing* plan, so it forwards
 *    the picked resources to `coursePlanService.attachResources` in the
 *    `onConfirm` handler and invalidates the sources query.
 *
 * 2. **CoursePlanWizard** — the plan does not exist yet at pick time,
 *    so the wizard simply pushes the picks into its draft state and
 *    attaches them in one batch after the plan is created.
 *
 * The dialog itself is purposefully agnostic: it only reports the
 * selected `Resource` rows; the parent decides what to do.
 */
export function LibraryPickerDialog({
  open,
  onOpenChange,
  alreadyLinkedIds,
  onConfirm,
  isPending,
}: {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  /** Resources whose ids are in this set render disabled + checked. */
  alreadyLinkedIds?: Set<number>;
  /** Called when the admin clicks "Attach selected". */
  onConfirm: (resources: Resource[]) => void | Promise<void>;
  /** Optional spinner state from the parent's mutation. */
  isPending?: boolean;
}) {
  const { t } = useTranslation();
  const [search, setSearch] = useState("");
  const [typeFilter, setTypeFilter] = useState<string>("all");
  const [selected, setSelected] = useState<Set<number>>(new Set());

  // Reset every time the dialog re-opens so a previous session's
  // selection doesn't bleed into the next attach.
  useEffect(() => {
    if (open) {
      setSelected(new Set());
      setSearch("");
      setTypeFilter("all");
    }
  }, [open]);

  const { data, isLoading } = useQuery({
    queryKey: ["library-resources", { search, type: typeFilter }],
    queryFn: () =>
      resourcesService.list({
        search: search || undefined,
        resource_type: typeFilter === "all" ? undefined : typeFilter,
        review_status: "approved",
      }),
    enabled: open,
  });
  const resources: Resource[] = data?.items ?? [];

  const toggle = (id: number) => {
    setSelected((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      return next;
    });
  };

  const handleConfirm = async () => {
    const picked = resources.filter((r) => selected.has(r.id));
    if (!picked.length) return;
    await onConfirm(picked);
  };

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-[640px] max-h-[85vh] overflow-hidden flex flex-col">
        <DialogHeader>
          <DialogTitle className="flex items-center gap-2">
            <Library className="h-5 w-5 text-primary" />
            {t("coursePlan.sources.libraryTitle")}
          </DialogTitle>
          <DialogDescription>
            {t("coursePlan.sources.libraryDescription")}
          </DialogDescription>
        </DialogHeader>

        <div className="flex gap-2 pt-2">
          <Input
            placeholder={t("coursePlan.sources.librarySearchPlaceholder")}
            value={search}
            onChange={(e) => setSearch(e.target.value)}
            className="flex-1"
          />
          <Select value={typeFilter} onValueChange={setTypeFilter}>
            <SelectTrigger className="w-[140px]">
              <SelectValue />
            </SelectTrigger>
            <SelectContent>
              <SelectItem value="all">
                {t("coursePlan.sources.libraryTypeAll")}
              </SelectItem>
              <SelectItem value="pdf">PDF</SelectItem>
              <SelectItem value="document">DOCX</SelectItem>
              <SelectItem value="link">URL</SelectItem>
              <SelectItem value="article">Article</SelectItem>
            </SelectContent>
          </Select>
        </div>

        <div className="flex-1 overflow-y-auto -mx-2 px-2 space-y-1">
          {isLoading && <Skeleton className="h-32 w-full" />}
          {!isLoading && resources.length === 0 && (
            <p className="text-center text-sm text-muted-foreground py-8">
              {t("coursePlan.sources.libraryEmpty")}
            </p>
          )}
          {!isLoading &&
            resources.map((r) => {
              const isLinked = alreadyLinkedIds?.has(r.id) ?? false;
              const isSelected = selected.has(r.id);
              return (
                <label
                  key={r.id}
                  className={`flex items-start gap-3 rounded-md border p-2 text-sm transition-colors ${
                    isLinked
                      ? "opacity-60 cursor-not-allowed bg-muted/40"
                      : "cursor-pointer hover:bg-accent/50"
                  }`}
                >
                  <Checkbox
                    checked={isLinked || isSelected}
                    disabled={isLinked}
                    onCheckedChange={() => !isLinked && toggle(r.id)}
                    className="mt-0.5"
                  />
                  <div className="flex-1 min-w-0 space-y-0.5">
                    <div className="flex items-center gap-2 flex-wrap">
                      <span className="font-medium truncate">{r.name}</span>
                      <Badge
                        variant="outline"
                        className="text-[10px] capitalize"
                      >
                        {r.resource_type || r.type || "resource"}
                      </Badge>
                      {isLinked && (
                        <Badge variant="secondary" className="text-[10px]">
                          {t("coursePlan.sources.libraryAlreadyLinked")}
                        </Badge>
                      )}
                    </div>
                    {(r.subject_name || (r.topic_names ?? []).length > 0) && (
                      <p className="text-xs text-muted-foreground truncate">
                        {[r.subject_name, ...(r.topic_names?.slice(0, 2) ?? [])]
                          .filter(Boolean)
                          .join(" › ")}
                      </p>
                    )}
                  </div>
                </label>
              );
            })}
        </div>

        <DialogFooter className="border-t pt-3">
          <span className="mr-auto text-xs text-muted-foreground self-center">
            {t("coursePlan.sources.librarySelectedCount", {
              count: selected.size,
            })}
          </span>
          <Button variant="outline" onClick={() => onOpenChange(false)}>
            {t("common.cancel", "Cancel")}
          </Button>
          <Button
            onClick={handleConfirm}
            disabled={!selected.size || isPending}
          >
            {isPending && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
            {t("coursePlan.sources.libraryAttach")}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
