import { useState } from "react";
import { Card, CardContent, CardHeader } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Badge } from "@/components/ui/badge";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, DialogFooter } from "@/components/ui/dialog";
import { Label } from "@/components/ui/label";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import {
  Upload, Search, FileText, Video, Link2, Download, Trash2,
  CheckCircle2, Clock, XCircle, Loader2, BookOpen, Music, Image,
  Tag, Plus, Pencil, X, CalendarDays,
} from "lucide-react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { resourcesService } from "@/services/resources.service";
import { coursewareService } from "@/services/courseware.service";
import { taxonomyService } from "@/services/taxonomy.service";
import { describeApiError } from "@/lib/api-client";
import { useToast } from "@/hooks/use-toast";
import { TaxonomyCascade } from "@/components/TaxonomyCascade";
import type { Resource, ResourceTag } from "@/types";

const statusBadge: Record<string, { variant: "default" | "secondary" | "destructive"; icon: React.ReactNode }> = {
  approved: { variant: "default", icon: <CheckCircle2 className="h-3 w-3 mr-1" /> },
  pending: { variant: "secondary", icon: <Clock className="h-3 w-3 mr-1" /> },
  rejected: { variant: "destructive", icon: <XCircle className="h-3 w-3 mr-1" /> },
};

const typeIcons: Record<string, React.ReactNode> = {
  pdf: <FileText className="h-4 w-4 text-red-500" />,
  video: <Video className="h-4 w-4 text-blue-500" />,
  link: <Link2 className="h-4 w-4 text-green-500" />,
  document: <FileText className="h-4 w-4 text-orange-500" />,
  interactive: <FileText className="h-4 w-4 text-purple-500" />,
  article: <FileText className="h-4 w-4 text-indigo-500" />,
  audio: <Music className="h-4 w-4 text-yellow-500" />,
  image: <Image className="h-4 w-4 text-pink-500" />,
};

const TAG_COLORS = [
  "#3b82f6", "#ef4444", "#22c55e", "#f59e0b", "#8b5cf6",
  "#ec4899", "#06b6d4", "#f97316", "#6366f1", "#14b8a6",
];

function pickColor() {
  return TAG_COLORS[Math.floor(Math.random() * TAG_COLORS.length)];
}

// ── Reusable Tag Picker with inline create ──────────────────────────
function TagPicker({
  allTags, selectedIds, onToggle, onTagCreated,
}: {
  allTags: ResourceTag[];
  selectedIds: number[];
  onToggle: (id: number) => void;
  onTagCreated: (tag: ResourceTag) => void;
}) {
  const [newName, setNewName] = useState("");
  const [creating, setCreating] = useState(false);

  const handleCreate = async () => {
    const name = newName.trim();
    if (!name) return;
    setCreating(true);
    try {
      const tag = await resourcesService.createTag({ name, color: pickColor() });
      onTagCreated(tag);
      onToggle(tag.id);
      setNewName("");
    } catch { /* ignore */ }
    setCreating(false);
  };

  return (
    <div className="space-y-2">
      <Label>Tags</Label>
      <div className="flex flex-wrap gap-2">
        {allTags.map((t) => (
          <Badge
            key={t.id}
            variant={selectedIds.includes(t.id) ? "default" : "outline"}
            className="cursor-pointer select-none transition-colors"
            style={selectedIds.includes(t.id) ? { backgroundColor: t.color, borderColor: t.color, color: "#fff" } : { borderColor: t.color, color: t.color }}
            onClick={() => onToggle(t.id)}
          >
            {t.name}
          </Badge>
        ))}
      </div>
      <div className="flex gap-2 items-center">
        <Input
          placeholder="New tag…"
          value={newName}
          onChange={(e) => setNewName(e.target.value)}
          onKeyDown={(e) => { if (e.key === "Enter") { e.preventDefault(); handleCreate(); } }}
          className="h-8 text-sm flex-1"
        />
        <Button type="button" size="sm" variant="outline" disabled={!newName.trim() || creating} onClick={handleCreate}>
          {creating ? <Loader2 className="h-3 w-3 animate-spin" /> : <><Plus className="h-3 w-3 mr-1" />Add</>}
        </Button>
      </div>
    </div>
  );
}

// ── Edit Resource Dialog ────────────────────────────────────────────
function EditResourceDialog({
  resource, open, onOpenChange, allTags, onTagCreated,
}: {
  resource: Resource;
  open: boolean;
  onOpenChange: (open: boolean) => void;
  allTags: ResourceTag[];
  onTagCreated: (tag: ResourceTag) => void;
}) {
  const { toast } = useToast();
  const qc = useQueryClient();
  const [name, setName] = useState(resource.name);
  const [type, setType] = useState(resource.type || resource.resource_type || "document");
  const [status, setStatus] = useState(resource.review_status || "approved");
  const [tagIds, setTagIds] = useState<number[]>(resource.tag_ids ?? resource.tags?.map((t) => t.id) ?? []);

  const [editSubjectId, setEditSubjectId] = useState<string>(resource.subject_id ? String(resource.subject_id) : "none");
  const [editDomainId, setEditDomainId] = useState<string>(resource.domain_id ? String(resource.domain_id) : "none");
  const [editTopicIds, setEditTopicIds] = useState<number[]>(resource.topic_ids ?? []);
  const [editObjectiveIds, setEditObjectiveIds] = useState<number[]>(resource.learning_objective_ids ?? []);

  const updateMutation = useMutation({
    mutationFn: (data: Record<string, unknown>) => resourcesService.update(resource.id, data as Partial<Resource>),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["resources"] });
      toast({ title: "Resource updated" });
      onOpenChange(false);
    },
    onError: () => toast({ title: "Error", description: "Failed to update", variant: "destructive" }),
  });

  const handleSave = () => {
    updateMutation.mutate({
      name,
      type,
      subject_id: editSubjectId !== "none" ? Number(editSubjectId) : null,
      domain_id: editDomainId !== "none" ? Number(editDomainId) : null,
      topic_ids: editTopicIds,
      learning_objective_ids: editObjectiveIds,
      review_status: status,
      tag_ids: tagIds,
    });
  };

  const toggleTag = (id: number) => setTagIds((prev) => prev.includes(id) ? prev.filter((t) => t !== id) : [...prev, id]);

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-[540px] max-h-[90vh] overflow-y-auto">
        <DialogHeader><DialogTitle>Edit Resource</DialogTitle></DialogHeader>
        <div className="space-y-4 pt-2">
          <div className="space-y-2"><Label>Name</Label><Input value={name} onChange={(e) => setName(e.target.value)} /></div>
          <div className="grid grid-cols-2 gap-4">
            <div className="space-y-2">
              <Label>Type</Label>
              <Select value={type} onValueChange={setType}>
                <SelectTrigger><SelectValue /></SelectTrigger>
                <SelectContent>
                  <SelectItem value="pdf">PDF</SelectItem>
                  <SelectItem value="video">Video</SelectItem>
                  <SelectItem value="link">Link</SelectItem>
                  <SelectItem value="document">Document</SelectItem>
                  <SelectItem value="interactive">Interactive</SelectItem>
                  <SelectItem value="audio">Audio</SelectItem>
                  <SelectItem value="image">Image</SelectItem>
                  <SelectItem value="article">Article</SelectItem>
                </SelectContent>
              </Select>
            </div>
            <div className="space-y-2">
              <Label>Status</Label>
              <Select value={status} onValueChange={(v) => setStatus(v as "pending" | "approved" | "rejected")}>
                <SelectTrigger><SelectValue /></SelectTrigger>
                <SelectContent>
                  <SelectItem value="pending">Pending</SelectItem>
                  <SelectItem value="approved">Approved</SelectItem>
                  <SelectItem value="rejected">Rejected</SelectItem>
                </SelectContent>
              </Select>
            </div>
          </div>
          <TaxonomyCascade
            subjectId={editSubjectId} onSubjectChange={setEditSubjectId}
            domainId={editDomainId} onDomainChange={setEditDomainId}
            topicIds={editTopicIds} onTopicIdsChange={setEditTopicIds}
            objectiveIds={editObjectiveIds} onObjectiveIdsChange={setEditObjectiveIds}
          />
          <TagPicker allTags={allTags} selectedIds={tagIds} onToggle={toggleTag} onTagCreated={onTagCreated} />
        </div>
        <DialogFooter>
          <Button variant="outline" onClick={() => onOpenChange(false)}>Cancel</Button>
          <Button onClick={handleSave} disabled={updateMutation.isPending || !name.trim()}>
            {updateMutation.isPending && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
            Save Changes
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

// ── Main Component ──────────────────────────────────────────────────
export default function ResourceManager() {
  const { toast } = useToast();
  const qc = useQueryClient();

  const [search, setSearch] = useState("");
  const [typeFilter, setTypeFilter] = useState<string>("all");
  const [statusFilter, setStatusFilter] = useState<string>("all");
  const [subjectFilter, setSubjectFilter] = useState<string>("all");
  const [tagFilter, setTagFilter] = useState<string>("all");
  const [dateFrom, setDateFrom] = useState("");
  const [dateTo, setDateTo] = useState("");
  const [activeTab, setActiveTab] = useState<string>("all");

  const [showUpload, setShowUpload] = useState(false);
  const [uploadType, setUploadType] = useState<string>("pdf");
  const [uploadSubjectId, setUploadSubjectId] = useState<string>("none");
  const [uploadDomainId, setUploadDomainId] = useState<string>("none");
  const [uploadTopicIds, setUploadTopicIds] = useState<number[]>([]);
  const [uploadObjectiveIds, setUploadObjectiveIds] = useState<number[]>([]);
  const [uploadTagIds, setUploadTagIds] = useState<number[]>([]);

  const [showTagManager, setShowTagManager] = useState(false);
  const [newTagName, setNewTagName] = useState("");
  const [newTagColor, setNewTagColor] = useState(TAG_COLORS[0]);
  const [editingTag, setEditingTag] = useState<ResourceTag | null>(null);

  const [editingResource, setEditingResource] = useState<Resource | null>(null);

  const { data: subjects } = useQuery({
    queryKey: ["taxonomy", "subjects"],
    queryFn: () => taxonomyService.listSubjects(),
  });

  const { data: tags } = useQuery({
    queryKey: ["resource-tags"],
    queryFn: () => resourcesService.listTags(),
  });

  const { data: resourcesData, isLoading: loadingResources } = useQuery({
    queryKey: ["resources", "list", { search, resource_type: typeFilter === "all" ? undefined : typeFilter, review_status: statusFilter === "all" ? undefined : statusFilter, subject_id: subjectFilter === "all" ? undefined : subjectFilter, tag_id: tagFilter === "all" ? undefined : tagFilter, date_from: dateFrom || undefined, date_to: dateTo || undefined }],
    queryFn: () => resourcesService.list({
      search: search || undefined,
      resource_type: typeFilter === "all" ? undefined : typeFilter,
      review_status: statusFilter === "all" ? undefined : statusFilter,
      subject_id: subjectFilter === "all" ? undefined : Number(subjectFilter),
      tag_id: tagFilter === "all" ? undefined : Number(tagFilter),
      date_from: dateFrom || undefined,
      date_to: dateTo || undefined,
    }),
  });
  const resources = resourcesData?.items ?? [];

  const { data: materialsData, isLoading: loadingMaterials } = useQuery({
    queryKey: ["materials", "search", { search, type: typeFilter }],
    queryFn: () => coursewareService.searchMaterials({ search: search || undefined, type: typeFilter === "all" ? undefined : typeFilter }),
  });
  const courseMaterials = materialsData?.items ?? [];

  const deleteMutation = useMutation({
    mutationFn: (id: number) => resourcesService.delete(id),
    onSuccess: () => { qc.invalidateQueries({ queryKey: ["resources"] }); toast({ title: "Resource deleted" }); },
    onError: () => toast({ title: "Error", description: "Failed to delete", variant: "destructive" }),
  });

  const uploadMutation = useMutation({
    mutationFn: (formData: FormData) => resourcesService.upload(formData),
    onSuccess: () => { qc.invalidateQueries({ queryKey: ["resources"] }); toast({ title: "Resource uploaded" }); setShowUpload(false); setUploadTagIds([]); setUploadSubjectId("none"); setUploadDomainId("none"); setUploadTopicIds([]); setUploadObjectiveIds([]); },
    onError: (err) => {
      // describeApiError surfaces status code + actionable next step so QA /
      // ops can tell 413 (payload limit) from 504 (timeout) from 401 (session
      // expired) without opening DevTools. Default "Upload failed" was
      // reported as non-actionable during the Apr-2026 deployment.
      toast({
        title: "Upload failed",
        description: describeApiError(err, "Upload failed", "file"),
        variant: "destructive",
      });
    },
  });

  const createTagMutation = useMutation({
    mutationFn: (data: { name: string; color: string }) => resourcesService.createTag(data),
    onSuccess: () => { qc.invalidateQueries({ queryKey: ["resource-tags"] }); setNewTagName(""); toast({ title: "Tag created" }); },
    onError: () => toast({ title: "Error", description: "Failed to create tag", variant: "destructive" }),
  });

  const updateTagMutation = useMutation({
    mutationFn: ({ id, ...data }: { id: number; name: string; color: string }) => resourcesService.updateTag(id, data),
    onSuccess: () => { qc.invalidateQueries({ queryKey: ["resource-tags"] }); qc.invalidateQueries({ queryKey: ["resources"] }); setEditingTag(null); toast({ title: "Tag updated" }); },
    onError: () => toast({ title: "Error", description: "Failed to update tag", variant: "destructive" }),
  });

  const deleteTagMutation = useMutation({
    mutationFn: (id: number) => resourcesService.deleteTag(id),
    onSuccess: () => { qc.invalidateQueries({ queryKey: ["resource-tags"] }); qc.invalidateQueries({ queryKey: ["resources"] }); toast({ title: "Tag deleted" }); },
    onError: () => toast({ title: "Error", description: "Failed to delete tag", variant: "destructive" }),
  });

  const handleUpload = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    const formData = new FormData(e.currentTarget);
    if (uploadTagIds.length > 0) formData.set("tag_ids", uploadTagIds.join(","));
    if (uploadDomainId !== "none") formData.set("domain_id", uploadDomainId);
    if (uploadTopicIds.length > 0) formData.set("topic_ids", uploadTopicIds.join(","));
    if (uploadObjectiveIds.length > 0) formData.set("learning_objective_ids", uploadObjectiveIds.join(","));
    uploadMutation.mutate(formData);
  };

  const toggleUploadTag = (id: number) => setUploadTagIds((prev) => prev.includes(id) ? prev.filter((t) => t !== id) : [...prev, id]);

  const handleInlineTagCreated = () => qc.invalidateQueries({ queryKey: ["resource-tags"] });

  const clearFilters = () => {
    setSearch(""); setTypeFilter("all"); setStatusFilter("all");
    setSubjectFilter("all"); setTagFilter("all"); setDateFrom(""); setDateTo("");
  };
  const hasActiveFilters = search || typeFilter !== "all" || statusFilter !== "all" || subjectFilter !== "all" || tagFilter !== "all" || dateFrom || dateTo;
  const isLoading = loadingResources || loadingMaterials;

  return (
    <div className="space-y-6">
      {/* Header */}
      <div className="flex items-center justify-between">
        <div>
          <h1 className="text-2xl font-bold">Resource Manager</h1>
          <p className="text-muted-foreground">All learning content — uploaded resources and course materials — available for AI generation.</p>
        </div>
        <div className="flex gap-2">
          <Button variant="outline" onClick={() => setShowTagManager(true)}><Tag className="mr-2 h-4 w-4" /> Manage Tags</Button>
          <Dialog open={showUpload} onOpenChange={(o) => { setShowUpload(o); if (!o) { setUploadTagIds([]); setUploadSubjectId("none"); setUploadDomainId("none"); setUploadTopicIds([]); setUploadObjectiveIds([]); } }}>
            <DialogTrigger asChild><Button><Upload className="mr-2 h-4 w-4" /> Upload Resource</Button></DialogTrigger>
            <DialogContent className="sm:max-w-[500px]">
              <DialogHeader><DialogTitle>Upload New Resource</DialogTitle></DialogHeader>
              <form onSubmit={handleUpload} className="space-y-4 pt-4">
                <input type="hidden" name="resource_type" value={uploadType} />
                {uploadSubjectId !== "none" && <input type="hidden" name="subject_id" value={uploadSubjectId} />}
                <div className="space-y-2"><Label>Name</Label><Input name="name" placeholder="Resource title" required /></div>
                <div className="space-y-2">
                  <Label>Type</Label>
                  <Select value={uploadType} onValueChange={setUploadType}>
                    <SelectTrigger><SelectValue /></SelectTrigger>
                    <SelectContent>
                      <SelectItem value="pdf">PDF</SelectItem>
                      <SelectItem value="video">Video</SelectItem>
                      <SelectItem value="link">Link</SelectItem>
                      <SelectItem value="document">Document</SelectItem>
                      <SelectItem value="interactive">Interactive</SelectItem>
                    </SelectContent>
                  </Select>
                </div>
                <TaxonomyCascade
                  subjectId={uploadSubjectId} onSubjectChange={setUploadSubjectId}
                  domainId={uploadDomainId} onDomainChange={setUploadDomainId}
                  topicIds={uploadTopicIds} onTopicIdsChange={setUploadTopicIds}
                  objectiveIds={uploadObjectiveIds} onObjectiveIdsChange={setUploadObjectiveIds}
                />
                <TagPicker
                  allTags={tags ?? []}
                  selectedIds={uploadTagIds}
                  onToggle={toggleUploadTag}
                  onTagCreated={(tag) => { handleInlineTagCreated(); toggleUploadTag(tag.id); }}
                />
                <div className="space-y-2"><Label>File</Label><Input name="file" type="file" /></div>
                <Button type="submit" className="w-full" disabled={uploadMutation.isPending}>
                  {uploadMutation.isPending && <Loader2 className="mr-2 h-4 w-4 animate-spin" />} Upload
                </Button>
              </form>
            </DialogContent>
          </Dialog>
        </div>
      </div>

      {/* Stats */}
      <div className="grid grid-cols-3 gap-4">
        <Card className="cursor-pointer hover:shadow-md transition-shadow" onClick={() => setActiveTab("all")}>
          <CardContent className="pt-6 text-center"><p className="text-2xl font-bold">{resources.length + courseMaterials.length}</p><p className="text-sm text-muted-foreground">Total Content Items</p></CardContent>
        </Card>
        <Card className="cursor-pointer hover:shadow-md transition-shadow" onClick={() => setActiveTab("resources")}>
          <CardContent className="pt-6 text-center"><p className="text-2xl font-bold">{resources.length}</p><p className="text-sm text-muted-foreground">Library Resources</p></CardContent>
        </Card>
        <Card className="cursor-pointer hover:shadow-md transition-shadow" onClick={() => setActiveTab("materials")}>
          <CardContent className="pt-6 text-center"><p className="text-2xl font-bold">{courseMaterials.length}</p><p className="text-sm text-muted-foreground">Course Materials</p></CardContent>
        </Card>
      </div>

      {/* Filters + Table */}
      <Card>
        <CardHeader className="space-y-3">
          <div className="flex items-center gap-3 flex-wrap">
            <div className="relative flex-1 min-w-[200px]">
              <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
              <Input placeholder="Search all content..." value={search} onChange={e => setSearch(e.target.value)} className="pl-9" />
            </div>
            <Select value={subjectFilter} onValueChange={setSubjectFilter}>
              <SelectTrigger className="w-[150px]"><SelectValue placeholder="Subject" /></SelectTrigger>
              <SelectContent>
                <SelectItem value="all">All Subjects</SelectItem>
                {(subjects ?? []).map((s) => (<SelectItem key={s.id} value={String(s.id)}>{s.name}</SelectItem>))}
              </SelectContent>
            </Select>
            <Select value={tagFilter} onValueChange={setTagFilter}>
              <SelectTrigger className="w-[140px]"><SelectValue placeholder="Tag" /></SelectTrigger>
              <SelectContent>
                <SelectItem value="all">All Tags</SelectItem>
                {(tags ?? []).map((t) => (
                  <SelectItem key={t.id} value={String(t.id)}>
                    <span className="flex items-center gap-2"><span className="h-2 w-2 rounded-full inline-block" style={{ backgroundColor: t.color }} />{t.name}</span>
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
            <Select value={typeFilter} onValueChange={setTypeFilter}>
              <SelectTrigger className="w-[130px]"><SelectValue placeholder="Type" /></SelectTrigger>
              <SelectContent>
                <SelectItem value="all">All Types</SelectItem>
                <SelectItem value="pdf">PDF</SelectItem><SelectItem value="video">Video</SelectItem><SelectItem value="link">Link</SelectItem>
                <SelectItem value="article">Article</SelectItem><SelectItem value="document">Document</SelectItem><SelectItem value="audio">Audio</SelectItem>
              </SelectContent>
            </Select>
            {activeTab !== "materials" && (
              <Select value={statusFilter} onValueChange={setStatusFilter}>
                <SelectTrigger className="w-[130px]"><SelectValue placeholder="Status" /></SelectTrigger>
                <SelectContent>
                  <SelectItem value="all">All Status</SelectItem>
                  <SelectItem value="pending">Pending</SelectItem><SelectItem value="approved">Approved</SelectItem><SelectItem value="rejected">Rejected</SelectItem>
                </SelectContent>
              </Select>
            )}
          </div>
          <div className="flex items-center gap-3">
            <div className="flex items-center gap-2 text-sm text-muted-foreground">
              <CalendarDays className="h-4 w-4" /><span>From</span>
              <Input type="date" value={dateFrom} onChange={e => setDateFrom(e.target.value)} className="w-[150px] h-8 text-xs" />
              <span>To</span>
              <Input type="date" value={dateTo} onChange={e => setDateTo(e.target.value)} className="w-[150px] h-8 text-xs" />
            </div>
            {hasActiveFilters && (<Button variant="ghost" size="sm" onClick={clearFilters} className="text-muted-foreground"><X className="h-3 w-3 mr-1" /> Clear filters</Button>)}
          </div>
        </CardHeader>
        <CardContent>
          {isLoading ? (
            <div className="flex justify-center py-12"><Loader2 className="h-8 w-8 animate-spin text-muted-foreground" /></div>
          ) : (
            <Tabs value={activeTab} onValueChange={setActiveTab}>
              <TabsList className="mb-4">
                <TabsTrigger value="all">All ({resources.length + courseMaterials.length})</TabsTrigger>
                <TabsTrigger value="resources">Library Resources ({resources.length})</TabsTrigger>
                <TabsTrigger value="materials">Course Materials ({courseMaterials.length})</TabsTrigger>
              </TabsList>
              <TabsContent value="all">
                <ContentTable resources={resources} materials={courseMaterials} showSource onDeleteResource={(id) => { if (window.confirm("Delete this resource?")) deleteMutation.mutate(id); }} onEditResource={setEditingResource} deletePending={deleteMutation.isPending} toast={toast} />
              </TabsContent>
              <TabsContent value="resources">
                <ContentTable resources={resources} materials={[]} onDeleteResource={(id) => { if (window.confirm("Delete this resource?")) deleteMutation.mutate(id); }} onEditResource={setEditingResource} deletePending={deleteMutation.isPending} toast={toast} />
              </TabsContent>
              <TabsContent value="materials">
                <ContentTable resources={[]} materials={courseMaterials} showCourseInfo onDeleteResource={() => {}} onEditResource={() => {}} deletePending={false} toast={toast} />
              </TabsContent>
            </Tabs>
          )}
        </CardContent>
      </Card>

      {/* Tag Manager Dialog */}
      <Dialog open={showTagManager} onOpenChange={(o) => { setShowTagManager(o); if (!o) setEditingTag(null); }}>
        <DialogContent className="sm:max-w-[500px]">
          <DialogHeader><DialogTitle className="flex items-center gap-2"><Tag className="h-5 w-5" /> Manage Resource Tags</DialogTitle></DialogHeader>
          <div className="space-y-4 pt-2">
            <div className="flex gap-2">
              <Input placeholder="New tag name…" value={newTagName} onChange={(e) => setNewTagName(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter" && newTagName.trim()) createTagMutation.mutate({ name: newTagName.trim(), color: newTagColor }); }} className="flex-1" />
              <div className="flex gap-1">
                {TAG_COLORS.slice(0, 5).map((c) => (
                  <button key={c} className="h-8 w-8 rounded-full border-2 transition-transform" style={{ backgroundColor: c, borderColor: newTagColor === c ? "#000" : "transparent", transform: newTagColor === c ? "scale(1.2)" : "scale(1)" }} onClick={() => setNewTagColor(c)} />
                ))}
              </div>
              <Button size="sm" disabled={!newTagName.trim() || createTagMutation.isPending} onClick={() => createTagMutation.mutate({ name: newTagName.trim(), color: newTagColor })}>
                {createTagMutation.isPending ? <Loader2 className="h-4 w-4 animate-spin" /> : <Plus className="h-4 w-4" />}
              </Button>
            </div>
            <div className="space-y-2 max-h-[300px] overflow-y-auto">
              {(tags ?? []).length === 0 && <p className="text-sm text-muted-foreground text-center py-4">No tags yet. Create one above.</p>}
              {(tags ?? []).map((t) => (
                <div key={t.id} className="flex items-center justify-between p-2 rounded-lg border hover:bg-accent/50">
                  {editingTag?.id === t.id ? (
                    <div className="flex items-center gap-2 flex-1">
                      <Input value={editingTag.name} onChange={(e) => setEditingTag({ ...editingTag, name: e.target.value })} className="h-8 text-sm flex-1" />
                      <div className="flex gap-1">
                        {TAG_COLORS.slice(0, 5).map((c) => (
                          <button key={c} className="h-6 w-6 rounded-full border-2" style={{ backgroundColor: c, borderColor: editingTag.color === c ? "#000" : "transparent" }} onClick={() => setEditingTag({ ...editingTag, color: c })} />
                        ))}
                      </div>
                      <Button size="sm" variant="ghost" onClick={() => updateTagMutation.mutate({ id: editingTag.id, name: editingTag.name, color: editingTag.color })} disabled={updateTagMutation.isPending}><CheckCircle2 className="h-4 w-4 text-green-600" /></Button>
                      <Button size="sm" variant="ghost" onClick={() => setEditingTag(null)}><X className="h-4 w-4" /></Button>
                    </div>
                  ) : (
                    <>
                      <div className="flex items-center gap-2">
                        <span className="h-3 w-3 rounded-full" style={{ backgroundColor: t.color }} />
                        <span className="text-sm font-medium">{t.name}</span>
                        <Badge variant="outline" className="text-xs">{t.resource_count ?? 0}</Badge>
                      </div>
                      <div className="flex gap-1">
                        <Button size="sm" variant="ghost" onClick={() => setEditingTag(t)}><Pencil className="h-3 w-3" /></Button>
                        <Button size="sm" variant="ghost" onClick={() => { if (window.confirm(`Delete tag "${t.name}"?`)) deleteTagMutation.mutate(t.id); }} disabled={deleteTagMutation.isPending}><Trash2 className="h-3 w-3 text-destructive" /></Button>
                      </div>
                    </>
                  )}
                </div>
              ))}
            </div>
          </div>
          <DialogFooter><Button variant="outline" onClick={() => setShowTagManager(false)}>Done</Button></DialogFooter>
        </DialogContent>
      </Dialog>

      {/* Edit Resource Dialog */}
      {editingResource && (
        <EditResourceDialog
          resource={editingResource}
          open={!!editingResource}
          onOpenChange={(o) => { if (!o) setEditingResource(null); }}
          allTags={tags ?? []}
          onTagCreated={handleInlineTagCreated}
        />
      )}
    </div>
  );
}

// ── Content Table ───────────────────────────────────────────────────
interface CourseMaterialItem {
  id: number; name: string; type: string; course_name: string;
  chapter_name: string; source: string; file_url: string | null;
  url: string | null; description: string | null;
}

function ContentTable({
  resources, materials, showSource, showCourseInfo, onDeleteResource, onEditResource, deletePending, toast,
}: {
  resources: Resource[]; materials: CourseMaterialItem[];
  showSource?: boolean; showCourseInfo?: boolean;
  onDeleteResource: (id: number) => void;
  onEditResource: (r: Resource) => void;
  deletePending: boolean;
  toast: ReturnType<typeof useToast>["toast"];
}) {
  type UnifiedRow = {
    key: string; name: string; type: string; source: "resource" | "material";
    context: string; tags?: { id: number; name: string; color: string }[];
    status?: string; createdAt?: string; resourceId?: number; raw?: Resource;
  };

  const rows: UnifiedRow[] = [
    ...resources.map((r): UnifiedRow => ({
      key: `r-${r.id}`, name: r.name, type: r.resource_type, source: "resource",
      context: [r.subject_name, ...(r.topic_names?.slice(0, 2) ?? [])].filter(Boolean).join(" › ") || "",
      tags: r.tags ?? [], status: r.review_status, createdAt: r.created_at, resourceId: r.id, raw: r,
    })),
    ...materials.map((m): UnifiedRow => ({
      key: `m-${m.id}`, name: m.name, type: m.type, source: "material",
      context: showCourseInfo || showSource ? `${m.course_name} › ${m.chapter_name}` : m.chapter_name || "",
    })),
  ];

  const formatDate = (iso?: string) => {
    if (!iso) return "";
    try { return new Date(iso).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" }); } catch { return ""; }
  };

  return (
    <Table>
      <TableHeader>
        <TableRow>
          <TableHead>Name</TableHead>
          <TableHead>Type</TableHead>
          {showSource && <TableHead>Source</TableHead>}
          <TableHead>Subject / Tags</TableHead>
          <TableHead>Status</TableHead>
          <TableHead>Uploaded</TableHead>
          <TableHead className="text-right">Actions</TableHead>
        </TableRow>
      </TableHeader>
      <TableBody>
        {rows.map((row) => {
          const sb = row.status ? (statusBadge[row.status] ?? statusBadge.pending) : null;
          return (
            <TableRow key={row.key}>
              <TableCell><div className="flex items-center gap-2">{typeIcons[row.type] ?? <FileText className="h-4 w-4" />}<span className="font-medium">{row.name}</span></div></TableCell>
              <TableCell><Badge variant="outline" className="capitalize">{row.type}</Badge></TableCell>
              {showSource && (
                <TableCell>
                  <Badge variant={row.source === "resource" ? "secondary" : "default"} className="text-xs">
                    {row.source === "resource" ? "Library" : <><BookOpen className="h-3 w-3 mr-1 inline" />Course</>}
                  </Badge>
                </TableCell>
              )}
              <TableCell>
                <div className="flex flex-col gap-1">
                  {row.context && <span className="text-xs text-muted-foreground">{row.context}</span>}
                  {row.tags && row.tags.length > 0 && (
                    <div className="flex flex-wrap gap-1">
                      {row.tags.map((t) => (<span key={t.id} className="inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium text-white" style={{ backgroundColor: t.color }}>{t.name}</span>))}
                    </div>
                  )}
                  {!row.context && (!row.tags || row.tags.length === 0) && <span className="text-muted-foreground">—</span>}
                </div>
              </TableCell>
              <TableCell>{sb ? (<Badge variant={sb.variant} className="flex items-center w-fit">{sb.icon}{row.status}</Badge>) : (<Badge variant="default" className="flex items-center w-fit"><CheckCircle2 className="h-3 w-3 mr-1" />indexed</Badge>)}</TableCell>
              <TableCell className="text-xs text-muted-foreground whitespace-nowrap">{formatDate(row.createdAt)}</TableCell>
              <TableCell className="text-right">
                <div className="flex items-center justify-end gap-1">
                  {row.source === "resource" && row.resourceId && (
                    <>
                      <Button variant="ghost" size="icon" title="Edit" onClick={() => row.raw && onEditResource(row.raw)}><Pencil className="h-4 w-4" /></Button>
                      <Button variant="ghost" size="icon" title="Download" onClick={async () => {
                        try { const blob = await resourcesService.download(row.resourceId!); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = row.name || "resource"; a.click(); URL.revokeObjectURL(url); } catch { toast({ title: "Download failed", variant: "destructive" }); }
                      }}><Download className="h-4 w-4" /></Button>
                      <Button variant="ghost" size="icon" title="Delete" onClick={() => onDeleteResource(row.resourceId!)} disabled={deletePending}><Trash2 className="h-4 w-4 text-destructive" /></Button>
                    </>
                  )}
                </div>
              </TableCell>
            </TableRow>
          );
        })}
        {rows.length === 0 && (<TableRow><TableCell colSpan={showSource ? 8 : 7} className="text-center py-8 text-muted-foreground">No content found.</TableCell></TableRow>)}
      </TableBody>
    </Table>
  );
}
