"use client";

import type { ReactElement, SyntheticEvent } from "react";
import { useState, useEffect, useCallback, useRef } from "react";
import { useRouter } from "next/navigation";
import {
  Plus,
  Trash2,
  List,
  LayoutGrid,
  Search,
  ArrowUpDown,
  ChevronUp,
  ChevronDown,
} from "lucide-react";
import type { KnowledgeEntryWithTags } from "@mosaic/shared";
import { EntryStatus, Visibility } from "@mosaic/shared";

import { MosaicSpinner } from "@/components/ui/MosaicSpinner";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
  DialogFooter,
} from "@/components/ui/dialog";
import { fetchEntries, createEntry, deleteEntry } from "@/lib/api/knowledge";
import type { EntriesResponse, CreateEntryData, EntryFilters } from "@/lib/api/knowledge";

/* ---------------------------------------------------------------------------
   Helpers
   --------------------------------------------------------------------------- */

type SortField = "title" | "updatedAt" | "createdAt";
type SortOrder = "asc" | "desc";
type ViewMode = "list" | "grid";

interface StatusStyle {
  label: string;
  bg: string;
  color: string;
}

function getStatusStyle(status: EntryStatus): StatusStyle {
  switch (status) {
    case EntryStatus.PUBLISHED:
      return { label: "Published", bg: "rgba(20,184,166,0.15)", color: "var(--ms-teal-400)" };
    case EntryStatus.DRAFT:
      return { label: "Draft", bg: "rgba(245,158,11,0.15)", color: "var(--ms-amber-400)" };
    case EntryStatus.ARCHIVED:
      return { label: "Archived", bg: "rgba(143,157,183,0.15)", color: "var(--muted)" };
    default:
      return { label: String(status), bg: "rgba(143,157,183,0.15)", color: "var(--muted)" };
  }
}

interface VisibilityStyle {
  label: string;
  bg: string;
  color: string;
}

function getVisibilityStyle(visibility: Visibility): VisibilityStyle {
  switch (visibility) {
    case Visibility.PUBLIC:
      return { label: "Public", bg: "rgba(47,128,255,0.15)", color: "var(--ms-blue-400)" };
    case Visibility.WORKSPACE:
      return { label: "Workspace", bg: "rgba(139,92,246,0.15)", color: "var(--ms-purple-400)" };
    case Visibility.PRIVATE:
      return { label: "Private", bg: "rgba(143,157,183,0.15)", color: "var(--muted)" };
    default:
      return { label: String(visibility), bg: "rgba(143,157,183,0.15)", color: "var(--muted)" };
  }
}

function formatTimestamp(date: Date | string): string {
  try {
    const d = typeof date === "string" ? new Date(date) : date;
    return d.toLocaleDateString("en-US", {
      month: "short",
      day: "numeric",
      year: "numeric",
    });
  } catch {
    return String(date);
  }
}

/* ---------------------------------------------------------------------------
   Status / Visibility Badges
   --------------------------------------------------------------------------- */

function StatusBadge({ status }: { status: EntryStatus }): ReactElement {
  const s = getStatusStyle(status);
  return (
    <span
      style={{
        display: "inline-block",
        padding: "2px 10px",
        borderRadius: "var(--r)",
        background: s.bg,
        color: s.color,
        fontSize: "0.75rem",
        fontWeight: 500,
        whiteSpace: "nowrap",
      }}
    >
      {s.label}
    </span>
  );
}

function VisibilityBadge({ visibility }: { visibility: Visibility }): ReactElement {
  const v = getVisibilityStyle(visibility);
  return (
    <span
      style={{
        display: "inline-block",
        padding: "2px 10px",
        borderRadius: "var(--r)",
        background: v.bg,
        color: v.color,
        fontSize: "0.75rem",
        fontWeight: 500,
        whiteSpace: "nowrap",
      }}
    >
      {v.label}
    </span>
  );
}

/* ---------------------------------------------------------------------------
   Tag Pill
   --------------------------------------------------------------------------- */

function TagPill({ name }: { name: string }): ReactElement {
  return (
    <span
      style={{
        display: "inline-block",
        padding: "1px 8px",
        borderRadius: "var(--r)",
        background: "var(--surface-2)",
        color: "var(--muted)",
        fontSize: "0.7rem",
        fontWeight: 500,
        whiteSpace: "nowrap",
      }}
    >
      {name}
    </span>
  );
}

/* ---------------------------------------------------------------------------
   Sort Header (for list view)
   --------------------------------------------------------------------------- */

interface SortHeaderProps {
  label: string;
  field: SortField;
  currentSort: SortField;
  currentOrder: SortOrder;
  onSort: (field: SortField) => void;
  style?: React.CSSProperties;
}

function SortHeader({
  label,
  field,
  currentSort,
  currentOrder,
  onSort,
  style,
}: SortHeaderProps): ReactElement {
  const isActive = currentSort === field;
  return (
    <button
      type="button"
      onClick={() => {
        onSort(field);
      }}
      style={{
        display: "inline-flex",
        alignItems: "center",
        gap: 4,
        background: "transparent",
        border: "none",
        cursor: "pointer",
        padding: 0,
        color: isActive ? "var(--text)" : "var(--muted)",
        fontSize: "0.75rem",
        fontWeight: 600,
        textTransform: "uppercase",
        letterSpacing: "0.05em",
        ...style,
      }}
    >
      {label}
      {isActive ? (
        currentOrder === "asc" ? (
          <ChevronUp size={14} />
        ) : (
          <ChevronDown size={14} />
        )
      ) : (
        <ArrowUpDown size={12} style={{ opacity: 0.5 }} />
      )}
    </button>
  );
}

/* ---------------------------------------------------------------------------
   Grid Card
   --------------------------------------------------------------------------- */

interface GridCardProps {
  entry: KnowledgeEntryWithTags;
  onDelete: (slug: string) => void;
  onClick: (slug: string) => void;
}

function GridCard({ entry, onDelete, onClick }: GridCardProps): ReactElement {
  const [hovered, setHovered] = useState(false);

  return (
    <div
      role="button"
      tabIndex={0}
      onClick={() => {
        onClick(entry.slug);
      }}
      onKeyDown={(e) => {
        if (e.key === "Enter" || e.key === " ") {
          e.preventDefault();
          onClick(entry.slug);
        }
      }}
      onMouseEnter={() => {
        setHovered(true);
      }}
      onMouseLeave={() => {
        setHovered(false);
      }}
      style={{
        background: "var(--surface)",
        border: `1px solid ${hovered ? "var(--primary)" : "var(--border)"}`,
        borderRadius: "var(--r-lg)",
        padding: 20,
        cursor: "pointer",
        transition: "border-color 0.2s var(--ease)",
        display: "flex",
        flexDirection: "column",
        gap: 12,
        position: "relative",
      }}
    >
      {/* Header: title + delete */}
      <div style={{ display: "flex", alignItems: "flex-start", justifyContent: "space-between" }}>
        <div style={{ flex: 1, minWidth: 0 }}>
          <h3
            style={{
              fontWeight: 600,
              color: "var(--text)",
              fontSize: "1rem",
              margin: 0,
              overflow: "hidden",
              textOverflow: "ellipsis",
              whiteSpace: "nowrap",
            }}
          >
            {entry.title}
          </h3>
        </div>
        <button
          aria-label={`Delete ${entry.title}`}
          onClick={(e) => {
            e.stopPropagation();
            onDelete(entry.slug);
          }}
          onKeyDown={(e) => {
            e.stopPropagation();
          }}
          style={{
            background: "transparent",
            border: "none",
            cursor: "pointer",
            padding: 4,
            borderRadius: "var(--r-sm)",
            color: "var(--muted)",
            transition: "color 0.15s, background 0.15s",
            display: "flex",
            alignItems: "center",
            justifyContent: "center",
            flexShrink: 0,
            marginLeft: 8,
          }}
          onMouseEnter={(e) => {
            e.currentTarget.style.color = "var(--danger)";
            e.currentTarget.style.background = "rgba(229,72,77,0.1)";
          }}
          onMouseLeave={(e) => {
            e.currentTarget.style.color = "var(--muted)";
            e.currentTarget.style.background = "transparent";
          }}
        >
          <Trash2 size={16} />
        </button>
      </div>

      {/* Status badge */}
      <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
        <StatusBadge status={entry.status} />
        <VisibilityBadge visibility={entry.visibility} />
      </div>

      {/* Tags (first 2) */}
      {entry.tags.length > 0 && (
        <div style={{ display: "flex", flexWrap: "wrap", gap: 4 }}>
          {entry.tags.slice(0, 2).map((tag) => (
            <TagPill key={tag.id} name={tag.name} />
          ))}
          {entry.tags.length > 2 && (
            <span style={{ fontSize: "0.7rem", color: "var(--muted)" }}>
              +{String(entry.tags.length - 2)}
            </span>
          )}
        </div>
      )}

      {/* Description */}
      {entry.summary ? (
        <p
          style={{
            color: "var(--muted)",
            fontSize: "0.85rem",
            margin: 0,
            overflow: "hidden",
            textOverflow: "ellipsis",
            display: "-webkit-box",
            WebkitLineClamp: 2,
            WebkitBoxOrient: "vertical",
            lineHeight: 1.5,
          }}
        >
          {entry.summary}
        </p>
      ) : null}

      {/* Footer: updated date */}
      <div style={{ marginTop: "auto" }}>
        <span
          style={{
            fontSize: "0.75rem",
            color: "var(--muted)",
            fontFamily: "var(--mono)",
          }}
        >
          {formatTimestamp(entry.updatedAt)}
        </span>
      </div>
    </div>
  );
}

/* ---------------------------------------------------------------------------
   Submit Button (extracted to avoid inline ternary line-length issues)
   --------------------------------------------------------------------------- */

interface SubmitButtonProps {
  isSubmitting: boolean;
  canSubmit: boolean;
}

function SubmitButton({ isSubmitting, canSubmit }: SubmitButtonProps): ReactElement {
  const enabled = canSubmit && !isSubmitting;
  return (
    <button
      type="submit"
      disabled={!enabled}
      style={{
        padding: "8px 16px",
        background: "var(--primary)",
        border: "none",
        borderRadius: "var(--r)",
        color: "#fff",
        fontSize: "0.85rem",
        fontWeight: 500,
        cursor: enabled ? "pointer" : "not-allowed",
        opacity: enabled ? 1 : 0.6,
      }}
    >
      {isSubmitting ? "Creating..." : "Create Entry"}
    </button>
  );
}

/* ---------------------------------------------------------------------------
   Create Entry Dialog
   --------------------------------------------------------------------------- */

interface CreateDialogProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  onSubmit: (data: CreateEntryData) => Promise<void>;
  isSubmitting: boolean;
}

function CreateEntryDialog({
  open,
  onOpenChange,
  onSubmit,
  isSubmitting,
}: CreateDialogProps): ReactElement {
  const [title, setTitle] = useState("");
  const [content, setContent] = useState("");
  const [summary, setSummary] = useState("");
  const [status, setStatus] = useState<EntryStatus>(EntryStatus.DRAFT);
  const [visibility, setVisibility] = useState<Visibility>(Visibility.PRIVATE);
  const [formError, setFormError] = useState<string | null>(null);

  function resetForm(): void {
    setTitle("");
    setContent("");
    setSummary("");
    setStatus(EntryStatus.DRAFT);
    setVisibility(Visibility.PRIVATE);
    setFormError(null);
  }

  async function handleSubmit(e: SyntheticEvent): Promise<void> {
    e.preventDefault();
    setFormError(null);

    const trimmedTitle = title.trim();
    if (!trimmedTitle) {
      setFormError("Title is required.");
      return;
    }

    const trimmedContent = content.trim();
    if (!trimmedContent) {
      setFormError("Content is required.");
      return;
    }

    try {
      const payload: CreateEntryData = {
        title: trimmedTitle,
        content: trimmedContent,
        status,
        visibility,
      };
      const trimmedSummary = summary.trim();
      if (trimmedSummary) {
        payload.summary = trimmedSummary;
      }
      await onSubmit(payload);
      resetForm();
    } catch (err: unknown) {
      setFormError(err instanceof Error ? err.message : "Failed to create entry.");
    }
  }

  return (
    <Dialog
      open={open}
      onOpenChange={(isOpen) => {
        if (!isOpen) resetForm();
        onOpenChange(isOpen);
      }}
    >
      <DialogContent>
        <div
          style={{
            background: "var(--surface)",
            borderRadius: "var(--r-lg)",
            border: "1px solid var(--border)",
            padding: 24,
            position: "relative",
          }}
        >
          <DialogHeader>
            <DialogTitle>
              <span style={{ color: "var(--text)" }}>New Entry</span>
            </DialogTitle>
            <DialogDescription>
              <span style={{ color: "var(--muted)" }}>Create a new knowledge entry.</span>
            </DialogDescription>
          </DialogHeader>

          <form
            onSubmit={(e) => {
              void handleSubmit(e);
            }}
            style={{ marginTop: 16 }}
          >
            {/* Title */}
            <div style={{ marginBottom: 16 }}>
              <label
                htmlFor="entry-title"
                style={{
                  display: "block",
                  marginBottom: 6,
                  fontSize: "0.85rem",
                  fontWeight: 500,
                  color: "var(--text-2)",
                }}
              >
                Title <span style={{ color: "var(--danger)" }}>*</span>
              </label>
              <input
                id="entry-title"
                type="text"
                value={title}
                onChange={(e) => {
                  setTitle(e.target.value);
                }}
                placeholder="e.g. API Authentication Guide"
                maxLength={255}
                autoFocus
                style={{
                  width: "100%",
                  padding: "8px 12px",
                  background: "var(--bg)",
                  border: "1px solid var(--border)",
                  borderRadius: "var(--r)",
                  color: "var(--text)",
                  fontSize: "0.9rem",
                  outline: "none",
                  boxSizing: "border-box",
                }}
              />
            </div>

            {/* Content */}
            <div style={{ marginBottom: 16 }}>
              <label
                htmlFor="entry-content"
                style={{
                  display: "block",
                  marginBottom: 6,
                  fontSize: "0.85rem",
                  fontWeight: 500,
                  color: "var(--text-2)",
                }}
              >
                Content <span style={{ color: "var(--danger)" }}>*</span>
              </label>
              <textarea
                id="entry-content"
                value={content}
                onChange={(e) => {
                  setContent(e.target.value);
                }}
                placeholder="Write your knowledge entry content..."
                rows={4}
                style={{
                  width: "100%",
                  padding: "8px 12px",
                  background: "var(--bg)",
                  border: "1px solid var(--border)",
                  borderRadius: "var(--r)",
                  color: "var(--text)",
                  fontSize: "0.9rem",
                  outline: "none",
                  resize: "vertical",
                  fontFamily: "inherit",
                  boxSizing: "border-box",
                }}
              />
            </div>

            {/* Summary */}
            <div style={{ marginBottom: 16 }}>
              <label
                htmlFor="entry-summary"
                style={{
                  display: "block",
                  marginBottom: 6,
                  fontSize: "0.85rem",
                  fontWeight: 500,
                  color: "var(--text-2)",
                }}
              >
                Summary
              </label>
              <input
                id="entry-summary"
                type="text"
                value={summary}
                onChange={(e) => {
                  setSummary(e.target.value);
                }}
                placeholder="Brief summary (optional)"
                maxLength={500}
                style={{
                  width: "100%",
                  padding: "8px 12px",
                  background: "var(--bg)",
                  border: "1px solid var(--border)",
                  borderRadius: "var(--r)",
                  color: "var(--text)",
                  fontSize: "0.9rem",
                  outline: "none",
                  boxSizing: "border-box",
                }}
              />
            </div>

            {/* Status + Visibility row */}
            <div style={{ display: "flex", gap: 16, marginBottom: 16 }}>
              <div style={{ flex: 1 }}>
                <label
                  htmlFor="entry-status"
                  style={{
                    display: "block",
                    marginBottom: 6,
                    fontSize: "0.85rem",
                    fontWeight: 500,
                    color: "var(--text-2)",
                  }}
                >
                  Status
                </label>
                <select
                  id="entry-status"
                  value={status}
                  onChange={(e) => {
                    setStatus(e.target.value as EntryStatus);
                  }}
                  style={{
                    width: "100%",
                    padding: "8px 12px",
                    background: "var(--bg)",
                    border: "1px solid var(--border)",
                    borderRadius: "var(--r)",
                    color: "var(--text)",
                    fontSize: "0.9rem",
                    outline: "none",
                    boxSizing: "border-box",
                  }}
                >
                  <option value={EntryStatus.DRAFT}>Draft</option>
                  <option value={EntryStatus.PUBLISHED}>Published</option>
                  <option value={EntryStatus.ARCHIVED}>Archived</option>
                </select>
              </div>
              <div style={{ flex: 1 }}>
                <label
                  htmlFor="entry-visibility"
                  style={{
                    display: "block",
                    marginBottom: 6,
                    fontSize: "0.85rem",
                    fontWeight: 500,
                    color: "var(--text-2)",
                  }}
                >
                  Visibility
                </label>
                <select
                  id="entry-visibility"
                  value={visibility}
                  onChange={(e) => {
                    setVisibility(e.target.value as Visibility);
                  }}
                  style={{
                    width: "100%",
                    padding: "8px 12px",
                    background: "var(--bg)",
                    border: "1px solid var(--border)",
                    borderRadius: "var(--r)",
                    color: "var(--text)",
                    fontSize: "0.9rem",
                    outline: "none",
                    boxSizing: "border-box",
                  }}
                >
                  <option value={Visibility.PRIVATE}>Private</option>
                  <option value={Visibility.WORKSPACE}>Workspace</option>
                  <option value={Visibility.PUBLIC}>Public</option>
                </select>
              </div>
            </div>

            {/* Form error */}
            {formError !== null && (
              <p style={{ color: "var(--danger)", fontSize: "0.85rem", margin: "0 0 12px" }}>
                {formError}
              </p>
            )}

            <DialogFooter>
              <button
                type="button"
                onClick={() => {
                  onOpenChange(false);
                }}
                disabled={isSubmitting}
                style={{
                  padding: "8px 16px",
                  background: "transparent",
                  border: "1px solid var(--border)",
                  borderRadius: "var(--r)",
                  color: "var(--text-2)",
                  fontSize: "0.85rem",
                  cursor: "pointer",
                }}
              >
                Cancel
              </button>
              <SubmitButton
                isSubmitting={isSubmitting}
                canSubmit={!!title.trim() && !!content.trim()}
              />
            </DialogFooter>
          </form>
        </div>
      </DialogContent>
    </Dialog>
  );
}

/* ---------------------------------------------------------------------------
   Delete Confirmation Dialog
   --------------------------------------------------------------------------- */

interface DeleteDialogProps {
  open: boolean;
  entryTitle: string;
  onConfirm: () => void;
  onCancel: () => void;
  isDeleting: boolean;
}

function DeleteConfirmDialog({
  open,
  entryTitle,
  onConfirm,
  onCancel,
  isDeleting,
}: DeleteDialogProps): ReactElement {
  return (
    <Dialog
      open={open}
      onOpenChange={(isOpen) => {
        if (!isOpen) onCancel();
      }}
    >
      <DialogContent>
        <div
          style={{
            background: "var(--surface)",
            borderRadius: "var(--r-lg)",
            border: "1px solid var(--border)",
            padding: 24,
          }}
        >
          <DialogHeader>
            <DialogTitle>
              <span style={{ color: "var(--text)" }}>Delete Entry</span>
            </DialogTitle>
            <DialogDescription>
              <span style={{ color: "var(--muted)" }}>
                {"This will permanently delete "}
                <strong style={{ color: "var(--text)" }}>{entryTitle}</strong>
                {". This action cannot be undone."}
              </span>
            </DialogDescription>
          </DialogHeader>

          <DialogFooter>
            <button
              type="button"
              onClick={onCancel}
              disabled={isDeleting}
              style={{
                padding: "8px 16px",
                background: "transparent",
                border: "1px solid var(--border)",
                borderRadius: "var(--r)",
                color: "var(--text-2)",
                fontSize: "0.85rem",
                cursor: "pointer",
              }}
            >
              Cancel
            </button>
            <button
              type="button"
              onClick={onConfirm}
              disabled={isDeleting}
              style={{
                padding: "8px 16px",
                background: "var(--danger)",
                border: "none",
                borderRadius: "var(--r)",
                color: "#fff",
                fontSize: "0.85rem",
                fontWeight: 500,
                cursor: isDeleting ? "not-allowed" : "pointer",
                opacity: isDeleting ? 0.6 : 1,
              }}
            >
              {isDeleting ? "Deleting..." : "Delete"}
            </button>
          </DialogFooter>
        </div>
      </DialogContent>
    </Dialog>
  );
}

/* ---------------------------------------------------------------------------
   File Manager Page
   --------------------------------------------------------------------------- */

export default function FileManagerPage(): ReactElement {
  const router = useRouter();

  // Data state
  const [entries, setEntries] = useState<KnowledgeEntryWithTags[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  // View state
  const [viewMode, setViewMode] = useState<ViewMode>("list");
  const [searchQuery, setSearchQuery] = useState("");
  const [sortBy, setSortBy] = useState<SortField>("updatedAt");
  const [sortOrder, setSortOrder] = useState<SortOrder>("desc");

  // Debounced search
  const searchTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const [debouncedSearch, setDebouncedSearch] = useState("");

  // Create dialog state
  const [createOpen, setCreateOpen] = useState(false);
  const [isCreating, setIsCreating] = useState(false);

  // Delete dialog state
  const [deleteTarget, setDeleteTarget] = useState<KnowledgeEntryWithTags | null>(null);
  const [isDeleting, setIsDeleting] = useState(false);

  // Debounce search input
  useEffect(() => {
    if (searchTimerRef.current !== null) {
      clearTimeout(searchTimerRef.current);
    }
    searchTimerRef.current = setTimeout(() => {
      setDebouncedSearch(searchQuery);
    }, 300);

    return (): void => {
      if (searchTimerRef.current !== null) {
        clearTimeout(searchTimerRef.current);
      }
    };
  }, [searchQuery]);

  // Load entries
  const loadEntries = useCallback(async (): Promise<void> => {
    setIsLoading(true);
    setError(null);

    try {
      const filters: EntryFilters = {
        sortBy,
        sortOrder,
        limit: 100,
      };

      if (debouncedSearch.trim()) {
        filters.search = debouncedSearch.trim();
      }

      const response: EntriesResponse = await fetchEntries(filters);
      setEntries(response.data);
    } catch (err: unknown) {
      setError(err instanceof Error ? err.message : "Failed to load entries");
    } finally {
      setIsLoading(false);
    }
  }, [sortBy, sortOrder, debouncedSearch]);

  useEffect(() => {
    void loadEntries();
  }, [loadEntries]);

  // Sort toggle handler
  function handleSortToggle(field: SortField): void {
    if (sortBy === field) {
      setSortOrder((prev) => (prev === "asc" ? "desc" : "asc"));
    } else {
      setSortBy(field);
      setSortOrder(field === "title" ? "asc" : "desc");
    }
  }

  // Navigation
  function handleEntryClick(slug: string): void {
    router.push(`/knowledge/${slug}`);
  }

  // Create
  async function handleCreate(data: CreateEntryData): Promise<void> {
    setIsCreating(true);
    try {
      await createEntry(data);
      setCreateOpen(false);
      void loadEntries();
    } finally {
      setIsCreating(false);
    }
  }

  // Delete
  function handleDeleteRequest(slug: string): void {
    const target = entries.find((e) => e.slug === slug);
    if (target) {
      setDeleteTarget(target);
    }
  }

  async function handleDeleteConfirm(): Promise<void> {
    if (!deleteTarget) return;
    setIsDeleting(true);
    try {
      await deleteEntry(deleteTarget.slug);
      setDeleteTarget(null);
      void loadEntries();
    } catch (err: unknown) {
      console.error("[FileManager] Failed to delete entry:", err);
      setError(err instanceof Error ? err.message : "Failed to delete entry.");
      setDeleteTarget(null);
    } finally {
      setIsDeleting(false);
    }
  }

  // Retry
  function handleRetry(): void {
    void loadEntries();
  }

  /* ---- Render ---- */

  return (
    <main className="container mx-auto px-4 py-8" style={{ maxWidth: 1100 }}>
      {/* Header */}
      <div
        style={{
          display: "flex",
          alignItems: "flex-start",
          justifyContent: "space-between",
          marginBottom: 24,
          flexWrap: "wrap",
          gap: 16,
        }}
      >
        <div>
          <h1
            style={{
              fontSize: "1.875rem",
              fontWeight: 700,
              color: "var(--text)",
              margin: 0,
            }}
          >
            File Manager
          </h1>
          <p
            style={{
              fontSize: "0.9rem",
              color: "var(--muted)",
              marginTop: 4,
            }}
          >
            Browse and manage knowledge entries
          </p>
        </div>

        <button
          onClick={() => {
            setCreateOpen(true);
          }}
          style={{
            display: "inline-flex",
            alignItems: "center",
            gap: 8,
            padding: "8px 16px",
            background: "var(--primary)",
            border: "none",
            borderRadius: "var(--r)",
            color: "#fff",
            fontSize: "0.85rem",
            fontWeight: 500,
            cursor: "pointer",
          }}
        >
          <Plus size={16} />
          New Entry
        </button>
      </div>

      {/* Toolbar: Search + View toggle */}
      <div
        style={{
          display: "flex",
          alignItems: "center",
          gap: 12,
          marginBottom: 20,
          flexWrap: "wrap",
        }}
      >
        {/* Search */}
        <div
          style={{
            flex: 1,
            minWidth: 200,
            position: "relative",
          }}
        >
          <Search
            size={16}
            style={{
              position: "absolute",
              left: 12,
              top: "50%",
              transform: "translateY(-50%)",
              color: "var(--muted)",
              pointerEvents: "none",
            }}
          />
          <input
            type="text"
            value={searchQuery}
            onChange={(e) => {
              setSearchQuery(e.target.value);
            }}
            placeholder="Search entries..."
            style={{
              width: "100%",
              padding: "8px 12px 8px 36px",
              background: "var(--surface)",
              border: "1px solid var(--border)",
              borderRadius: "var(--r)",
              color: "var(--text)",
              fontSize: "0.9rem",
              outline: "none",
              boxSizing: "border-box",
            }}
          />
        </div>

        {/* View toggle */}
        <div
          style={{
            display: "flex",
            borderRadius: "var(--r)",
            border: "1px solid var(--border)",
            overflow: "hidden",
          }}
        >
          <button
            type="button"
            aria-label="List view"
            onClick={() => {
              setViewMode("list");
            }}
            style={{
              display: "flex",
              alignItems: "center",
              justifyContent: "center",
              padding: "6px 10px",
              background: viewMode === "list" ? "var(--surface-2)" : "var(--surface)",
              border: "none",
              cursor: "pointer",
              color: viewMode === "list" ? "var(--text)" : "var(--muted)",
              transition: "background 0.15s, color 0.15s",
            }}
          >
            <List size={18} />
          </button>
          <button
            type="button"
            aria-label="Grid view"
            onClick={() => {
              setViewMode("grid");
            }}
            style={{
              display: "flex",
              alignItems: "center",
              justifyContent: "center",
              padding: "6px 10px",
              background: viewMode === "grid" ? "var(--surface-2)" : "var(--surface)",
              border: "none",
              borderLeft: "1px solid var(--border)",
              cursor: "pointer",
              color: viewMode === "grid" ? "var(--text)" : "var(--muted)",
              transition: "background 0.15s, color 0.15s",
            }}
          >
            <LayoutGrid size={18} />
          </button>
        </div>
      </div>

      {/* Loading state */}
      {isLoading && entries.length === 0 ? (
        <div className="flex justify-center py-16">
          <MosaicSpinner label="Loading entries..." />
        </div>
      ) : error !== null ? (
        /* Error state */
        <div
          style={{
            background: "var(--surface)",
            border: "1px solid var(--border)",
            borderRadius: "var(--r-lg)",
            padding: 32,
            textAlign: "center",
          }}
        >
          <p style={{ color: "var(--danger)", margin: "0 0 16px" }}>{error}</p>
          <button
            type="button"
            onClick={handleRetry}
            style={{
              padding: "8px 16px",
              background: "var(--danger)",
              border: "none",
              borderRadius: "var(--r)",
              color: "#fff",
              fontSize: "0.85rem",
              fontWeight: 500,
              cursor: "pointer",
            }}
          >
            Try again
          </button>
        </div>
      ) : entries.length === 0 ? (
        /* Empty state */
        <div
          style={{
            background: "var(--surface)",
            border: "1px solid var(--border)",
            borderRadius: "var(--r-lg)",
            padding: 48,
            textAlign: "center",
          }}
        >
          <p style={{ color: "var(--muted)", margin: "0 0 16px", fontSize: "0.9rem" }}>
            {debouncedSearch
              ? "No entries match your search."
              : "No files found. Create your first entry to get started."}
          </p>
          {!debouncedSearch && (
            <button
              type="button"
              onClick={() => {
                setCreateOpen(true);
              }}
              style={{
                display: "inline-flex",
                alignItems: "center",
                gap: 8,
                padding: "8px 16px",
                background: "var(--primary)",
                border: "none",
                borderRadius: "var(--r)",
                color: "#fff",
                fontSize: "0.85rem",
                fontWeight: 500,
                cursor: "pointer",
              }}
            >
              <Plus size={16} />
              Create Entry
            </button>
          )}
        </div>
      ) : viewMode === "list" ? (
        /* List View */
        <div
          style={{
            background: "var(--surface)",
            border: "1px solid var(--border)",
            borderRadius: "var(--r-lg)",
            overflow: "hidden",
          }}
        >
          {/* Table header */}
          <div
            style={{
              display: "grid",
              gridTemplateColumns: "1fr 110px 110px 160px 110px 40px",
              gap: 0,
              padding: "10px 16px",
              background: "var(--bg-mid)",
              borderBottom: "1px solid var(--border)",
              alignItems: "center",
            }}
          >
            <SortHeader
              label="Name"
              field="title"
              currentSort={sortBy}
              currentOrder={sortOrder}
              onSort={handleSortToggle}
            />
            <span
              style={{
                fontSize: "0.75rem",
                fontWeight: 600,
                textTransform: "uppercase",
                letterSpacing: "0.05em",
                color: "var(--muted)",
              }}
            >
              Status
            </span>
            <span
              style={{
                fontSize: "0.75rem",
                fontWeight: 600,
                textTransform: "uppercase",
                letterSpacing: "0.05em",
                color: "var(--muted)",
              }}
            >
              Visibility
            </span>
            <span
              style={{
                fontSize: "0.75rem",
                fontWeight: 600,
                textTransform: "uppercase",
                letterSpacing: "0.05em",
                color: "var(--muted)",
              }}
            >
              Tags
            </span>
            <SortHeader
              label="Updated"
              field="updatedAt"
              currentSort={sortBy}
              currentOrder={sortOrder}
              onSort={handleSortToggle}
            />
            {/* Actions column header - empty */}
            <span />
          </div>

          {/* Table rows */}
          {entries.map((entry) => (
            <ListRow
              key={entry.id}
              entry={entry}
              onDelete={handleDeleteRequest}
              onClick={handleEntryClick}
            />
          ))}
        </div>
      ) : (
        /* Grid View */
        <div
          style={{
            display: "grid",
            gridTemplateColumns: "repeat(auto-fill, minmax(300px, 1fr))",
            gap: 16,
          }}
        >
          {entries.map((entry) => (
            <GridCard
              key={entry.id}
              entry={entry}
              onDelete={handleDeleteRequest}
              onClick={handleEntryClick}
            />
          ))}
        </div>
      )}

      {/* Create Dialog */}
      <CreateEntryDialog
        open={createOpen}
        onOpenChange={setCreateOpen}
        onSubmit={handleCreate}
        isSubmitting={isCreating}
      />

      {/* Delete Confirmation Dialog */}
      <DeleteConfirmDialog
        open={deleteTarget !== null}
        entryTitle={deleteTarget?.title ?? ""}
        onConfirm={() => {
          void handleDeleteConfirm();
        }}
        onCancel={() => {
          setDeleteTarget(null);
        }}
        isDeleting={isDeleting}
      />
    </main>
  );
}

/* ---------------------------------------------------------------------------
   List Row (extracted for hover state)
   --------------------------------------------------------------------------- */

interface ListRowProps {
  entry: KnowledgeEntryWithTags;
  onDelete: (slug: string) => void;
  onClick: (slug: string) => void;
}

function ListRow({ entry, onDelete, onClick }: ListRowProps): ReactElement {
  const [hovered, setHovered] = useState(false);

  return (
    <div
      role="button"
      tabIndex={0}
      onClick={() => {
        onClick(entry.slug);
      }}
      onKeyDown={(e) => {
        if (e.key === "Enter" || e.key === " ") {
          e.preventDefault();
          onClick(entry.slug);
        }
      }}
      onMouseEnter={() => {
        setHovered(true);
      }}
      onMouseLeave={() => {
        setHovered(false);
      }}
      style={{
        display: "grid",
        gridTemplateColumns: "1fr 110px 110px 160px 110px 40px",
        gap: 0,
        padding: "12px 16px",
        borderBottom: "1px solid var(--border)",
        cursor: "pointer",
        background: hovered ? "var(--surface-2)" : "var(--surface)",
        transition: "background 0.15s",
        alignItems: "center",
      }}
    >
      {/* Name */}
      <span
        style={{
          fontWeight: 500,
          color: "var(--text)",
          fontSize: "0.9rem",
          overflow: "hidden",
          textOverflow: "ellipsis",
          whiteSpace: "nowrap",
          paddingRight: 12,
        }}
      >
        {entry.title}
      </span>

      {/* Status */}
      <StatusBadge status={entry.status} />

      {/* Visibility */}
      <VisibilityBadge visibility={entry.visibility} />

      {/* Tags */}
      <div style={{ display: "flex", flexWrap: "wrap", gap: 4, overflow: "hidden" }}>
        {entry.tags.slice(0, 2).map((tag) => (
          <TagPill key={tag.id} name={tag.name} />
        ))}
        {entry.tags.length > 2 && (
          <span style={{ fontSize: "0.7rem", color: "var(--muted)" }}>
            +{String(entry.tags.length - 2)}
          </span>
        )}
      </div>

      {/* Updated */}
      <span
        style={{
          fontSize: "0.8rem",
          color: "var(--muted)",
          fontFamily: "var(--mono)",
        }}
      >
        {formatTimestamp(entry.updatedAt)}
      </span>

      {/* Delete action */}
      <button
        aria-label={`Delete ${entry.title}`}
        onClick={(e) => {
          e.stopPropagation();
          onDelete(entry.slug);
        }}
        onKeyDown={(e) => {
          e.stopPropagation();
        }}
        style={{
          background: "transparent",
          border: "none",
          cursor: "pointer",
          padding: 4,
          borderRadius: "var(--r-sm)",
          color: "var(--muted)",
          transition: "color 0.15s, background 0.15s",
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
        }}
        onMouseEnter={(e) => {
          e.currentTarget.style.color = "var(--danger)";
          e.currentTarget.style.background = "rgba(229,72,77,0.1)";
        }}
        onMouseLeave={(e) => {
          e.currentTarget.style.color = "var(--muted)";
          e.currentTarget.style.background = "transparent";
        }}
      >
        <Trash2 size={15} />
      </button>
    </div>
  );
}
