/* eslint-disable @typescript-eslint/no-explicit-any */
import React, { useState, useEffect, useCallback, useMemo } from "react";
import { useTranslation } from "react-i18next";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogFooter,
} from "@/shared/common/ui/dialog";
import { Button } from "@/shared/common/ui/button";
import { Input } from "@/shared/common/ui/input";
import {
  getMySubFolders,
  getMyCollaborationsSubFolders,
} from "@/DMS/api/folders.api";
import { listMyDocuments, getMyShares } from "@/DMS/api/dms.api";
import { dmsHttp } from "@/DMS/api/dms.http";
import {
  ODWinFolderSvg,
  ODIconWord,
  ODIconExcel,
  ODIconPpt,
  ODIconPdf,
  ODIconImage,
  ODIconVideo,
  ODIconFile,
} from "@/DMS/pages/_shared/od-icons";
import { detectFileKind } from "@/DMS/pages/_shared/file-kind.utils";
import {
  formatBytes,
  resolveOwnerName,
  pickName,
} from "@/DMS/pages/_shared/utils";
import {
  Search,
  ChevronRight,
  Loader2,
  FolderOpen,
  CheckCircle2,
  XCircle,
  AlertCircle,
  ChevronLeft,
  ChevronRight as ChevronRightIcon,
  HardDrive,
  Clock,
  Star,
  Share2,
  Users,
} from "lucide-react";

// ─── Section definitions ────────────────────────────────────────────────────

type SectionKey =
  | "myFiles"
  | "recents"
  | "favorites"
  | "shared"
  | "sharedWithMe";

interface SidebarSection {
  key: SectionKey;
  label: string;
  icon: React.ReactNode;
  /** Whether folder-navigation (breadcrumbs) is supported in this section */
  navigable: boolean;
}

const SECTIONS: SidebarSection[] = [
  {
    key: "myFiles",
    label: "My Files",
    icon: <HardDrive className="h-4 w-4" />,
    navigable: true,
  },
  {
    key: "recents",
    label: "Recents",
    icon: <Clock className="h-4 w-4" />,
    navigable: false,
  },
  {
    key: "favorites",
    label: "Favorites",
    icon: <Star className="h-4 w-4" />,
    navigable: true,
  },
  {
    key: "shared",
    label: "Shared",
    icon: <Share2 className="h-4 w-4" />,
    navigable: true,
  },
  {
    key: "sharedWithMe",
    label: "Shared with me",
    icon: <Users className="h-4 w-4" />,
    navigable: true,
  },
];

// ─── Props ──────────────────────────────────────────────────────────────────

interface DmsFilePickerModalProps {
  isOpen: boolean;
  onClose: () => void;
  onAttach: (selectedDocs: any[]) => void;
}

// ─── Breadcrumb node ─────────────────────────────────────────────────────────

interface BreadcrumbNode {
  id: string | null;
  name: string;
}

const itemTypeOf = (item: any) =>
  String(item?.type ?? item?.itemType ?? "").toLowerCase() === "folder"
    ? "folder"
    : "document";

const normalizeBrowseItem = (item: any) => ({
  ...item,
  id:
    itemTypeOf(item) === "folder"
      ? (item.folderId ?? item.id)
      : (item.documentId ?? item.id),
  type: itemTypeOf(item),
});

// ─── Component ───────────────────────────────────────────────────────────────

export function DmsFilePickerModal({
  isOpen,
  onClose,
  onAttach,
}: DmsFilePickerModalProps) {
  const { t } = useTranslation();

  // ── Sidebar active section ────────────────────────────────────────────────
  const [activeSection, setActiveSection] = useState<SectionKey>("myFiles");

  // ── Browsing / navigation state ───────────────────────────────────────────
  const [currentFolderId, setCurrentFolderId] = useState<string | null>(null);
  const [breadcrumbs, setBreadcrumbs] = useState<BreadcrumbNode[]>([
    { id: null, name: "My Files" },
  ]);
  const [searchQuery, setSearchQuery] = useState("");
  const [debouncedSearch, setDebouncedSearch] = useState("");

  // ── Data state ────────────────────────────────────────────────────────────
  const [items, setItems] = useState<any[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  // ── Pagination state ──────────────────────────────────────────────────────
  const [page, setPage] = useState(1);
  const [totalCount, setTotalCount] = useState(0);
  const limit = 50;

  // ── Selection state ───────────────────────────────────────────────────────
  const [selectedDocs, setSelectedDocs] = useState<Map<string, any>>(new Map());

  // ── Debounce search ───────────────────────────────────────────────────────
  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedSearch(searchQuery);
      setPage(1);
    }, 400);
    return () => clearTimeout(handler);
  }, [searchQuery]);

  // ── Reset on modal open ───────────────────────────────────────────────────
  useEffect(() => {
    if (isOpen) {
      setActiveSection("myFiles");
      setCurrentFolderId(null);
      setBreadcrumbs([{ id: null, name: "My Files" }]);
      setSearchQuery("");
      setDebouncedSearch("");
      setPage(1);
      setSelectedDocs(new Map());
    }
  }, [isOpen]);

  // ── Reset folder navigation when section changes ──────────────────────────
  const handleSectionChange = (key: SectionKey) => {
    if (key === activeSection) return;
    const sec = SECTIONS.find((s) => s.key === key)!;
    setActiveSection(key);
    setCurrentFolderId(null);
    setBreadcrumbs([{ id: null, name: sec.label }]);
    setSearchQuery("");
    setDebouncedSearch("");
    setPage(1);
    setItems([]);
  };

  // ── Data fetcher (depends on active section) ──────────────────────────────
  const loadContents = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const skip = (page - 1) * limit;
      const q = debouncedSearch.trim() || undefined;

      if (
        currentFolderId &&
        (activeSection === "favorites" || activeSection === "shared")
      ) {
        const res = await getMySubFolders(currentFolderId, {
          skip,
          take: limit,
          q,
        });
        const fetched = Array.isArray(res?.items) ? res.items : [];
        setItems(fetched.map(normalizeBrowseItem));
        setTotalCount(Number(res?.count ?? fetched.length));
      } else if (activeSection === "myFiles") {
        const res = await getMySubFolders(currentFolderId, {
          skip,
          take: limit,
          q,
        });
        const fetched = Array.isArray(res?.items) ? res.items : [];
        setItems(fetched.map(normalizeBrowseItem));
        setTotalCount(Number(res?.count ?? fetched.length));
      } else if (activeSection === "recents") {
        const res = await listMyDocuments({
          skip,
          take: limit,
          name: q,
          orderBy: "updatedAt:DESC",
        });
        // listMyDocuments returns only documents (no folders)
        const fetched = Array.isArray(res?.items) ? res.items : [];
        // Normalise to the same shape as browse items
        const docs = fetched.map((d: any) =>
          normalizeBrowseItem({ ...d, type: "document" }),
        );
        setItems(docs);
        setTotalCount(Number(res?.count ?? docs.length));
      } else if (activeSection === "favorites") {
        const res = await dmsHttp.get<{ items: any[]; count: number }>(
          "/api/favorites",
        );
        const raw: any[] = Array.isArray(res.data?.items)
          ? res.data.items
          : Array.isArray(res.data)
            ? (res.data as any[])
            : [];
        // Each favorite item wraps the document/folder in `.document` or `.folder`
        const fetched = raw
          .map((fav: any) => {
            const doc = fav.document ?? fav.folder ?? fav;
            if (!doc?.id) return null;
            return {
              ...doc,
              id: fav.folderId ?? fav.documentId ?? doc.id,
              type: fav.folder || fav.folderId ? "folder" : "document",
              fileInfo: doc.fileInfo ?? doc.presignedUrl ?? undefined,
            };
          })
          .filter(Boolean)
          .map(normalizeBrowseItem)
          .filter((item: any) => {
            if (!q) return true;
            return pickName(item.name, "")
              .toLowerCase()
              .includes(q.toLowerCase());
          });
        setItems(fetched);
        setTotalCount(fetched.length);
      } else if (activeSection === "shared") {
        // Items the current user has shared with others
        const res = await getMyShares({ skip, take: limit });
        const raw: any[] = Array.isArray(res?.items) ? res.items : [];
        const fetched = raw
          .map((share: any) => {
            if (!share.documentId && !share.folderId) return null;
            const type = share.itemType === "folder" ? "folder" : "document";
            return {
              id: type === "folder" ? share.folderId : share.documentId,
              name: share.itemName,
              type,
              ownerName: share.recipientName,
              updatedAt: share.sharedAt,
            };
          })
          .filter(Boolean)
          .map(normalizeBrowseItem)
          .filter((item: any) => {
            if (!q) return true;
            return pickName(item.name, "")
              .toLowerCase()
              .includes(q.toLowerCase());
          });
        setItems(fetched);
        setTotalCount(Number(res?.count ?? fetched.length));
      } else if (activeSection === "sharedWithMe") {
        // Items other users have shared with the current user (browsable folders)
        const res = await getMyCollaborationsSubFolders(currentFolderId, {
          skip,
          take: limit,
          q,
        });
        const fetched = Array.isArray(res?.items) ? res.items : [];
        setItems(fetched.map(normalizeBrowseItem));
        setTotalCount(Number(res?.count ?? fetched.length));
      }
    } catch (err: any) {
      console.error("Failed to load DMS contents:", err);
      setError(
        err?.message ?? "Failed to load files from DMS. Please try again.",
      );
      setItems([]);
      setTotalCount(0);
    } finally {
      setLoading(false);
    }
  }, [activeSection, currentFolderId, page, debouncedSearch]);

  useEffect(() => {
    if (isOpen) loadContents();
  }, [isOpen, loadContents]);

  // ── Folder navigation ─────────────────────────────────────────────────────
  const currentSection = SECTIONS.find((s) => s.key === activeSection)!;

  const handleFolderClick = (folder: any) => {
    if (!currentSection.navigable) return;
    setCurrentFolderId(folder.id);
    setBreadcrumbs((prev) => [
      ...prev,
      { id: folder.id, name: pickName(folder.name, "Untitled Folder") },
    ]);
    setPage(1);
    setSearchQuery("");
    setDebouncedSearch("");
  };

  const handleBreadcrumbClick = (node: BreadcrumbNode, index: number) => {
    setCurrentFolderId(node.id);
    setBreadcrumbs((prev) => prev.slice(0, index + 1));
    setPage(1);
    setSearchQuery("");
    setDebouncedSearch("");
  };

  // ── Document selection ────────────────────────────────────────────────────
  const handleDocClick = (doc: any) => {
    setSelectedDocs((prev) => {
      const next = new Map(prev);
      if (next.has(doc.id)) next.delete(doc.id);
      else next.set(doc.id, doc);
      return next;
    });
  };

  const documentsOnPage = useMemo(
    () => items.filter((x) => x?.type === "document"),
    [items],
  );
  const foldersOnPage = useMemo(
    () => items.filter((x) => x?.type === "folder"),
    [items],
  );
  const displayGroups = useMemo(
    () =>
      [
        { label: "Folders", items: foldersOnPage },
        { label: "Documents", items: documentsOnPage },
      ].filter((group) => group.items.length > 0),
    [foldersOnPage, documentsOnPage],
  );
  const isAllSelected = useMemo(
    () =>
      documentsOnPage.length > 0 &&
      documentsOnPage.every((doc) => selectedDocs.has(doc.id)),
    [documentsOnPage, selectedDocs],
  );
  const handleSelectAllToggle = () => {
    setSelectedDocs((prev) => {
      const next = new Map(prev);
      if (isAllSelected) documentsOnPage.forEach((doc) => next.delete(doc.id));
      else documentsOnPage.forEach((doc) => next.set(doc.id, doc));
      return next;
    });
  };

  // ── Attach action ─────────────────────────────────────────────────────────
  const handleAttach = () => {
    onAttach(Array.from(selectedDocs.values()));
    onClose();
  };

  const totalPages = Math.ceil(totalCount / limit);
  const selectedCount = selectedDocs.size;

  // ── Document icon helper ──────────────────────────────────────────────────
  const renderDocIcon = (item: any) => {
    const { kind } = detectFileKind(item);
    const cls = "h-8 w-8";
    switch (kind) {
      case "word":
        return <ODIconWord className={cls} />;
      case "sheet":
        return <ODIconExcel className={cls} />;
      case "slide":
        return <ODIconPpt className={cls} />;
      case "pdf":
        return <ODIconPdf className={cls} />;
      case "image":
        return <ODIconImage className={cls} />;
      case "video":
        return <ODIconVideo className={cls} />;
      default:
        return <ODIconFile className={cls} />;
    }
  };

  // ─────────────────────────────────────────────────────────────────────────
  return (
    <Dialog open={isOpen} onOpenChange={(open) => !open && onClose()}>
      <DialogContent className="h-[90vh] max-h-[780px] w-[calc(100vw-2rem)] max-w-[calc(100vw-2rem)] flex flex-col gap-0 overflow-hidden rounded-2xl border bg-white p-0 shadow-2xl dark:border-gray-800 dark:bg-gray-900 sm:w-[92vw] sm:max-w-6xl">
        {/* ── Header ─────────────────────────────────────────────────────── */}
        <DialogHeader className="px-6 py-4 border-b dark:border-gray-800 shrink-0">
          <DialogTitle className="text-xl font-bold flex items-center gap-2 dark:text-white">
            <FolderOpen className="h-5 w-5 text-primary-500" />
            {t("dms.picker.title") || "Select from DMS"}
          </DialogTitle>
        </DialogHeader>

        {/* ── Body: sidebar + main ────────────────────────────────────────── */}
        <div className="flex flex-1 overflow-hidden">
          {/* ── Left Sidebar ─────────────────────────────────────────────── */}
          <aside className="w-52 shrink-0 border-r dark:border-gray-800 bg-gray-50 dark:bg-gray-900 flex flex-col py-3 gap-0.5 overflow-y-auto">
            {SECTIONS.map((sec) => (
              <button
                key={sec.key}
                onClick={() => handleSectionChange(sec.key)}
                className={`flex items-center gap-3 px-4 py-2.5 text-sm font-medium rounded-lg mx-2 transition-colors text-left ${
                  activeSection === sec.key
                    ? "bg-primary-100 dark:bg-primary-900/40 text-primary-700 dark:text-primary-300"
                    : "text-gray-600 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-800"
                }`}
              >
                <span
                  className={
                    activeSection === sec.key
                      ? "text-primary-600 dark:text-primary-400"
                      : "text-gray-400 dark:text-gray-500"
                  }
                >
                  {sec.icon}
                </span>
                {sec.label}
              </button>
            ))}
          </aside>

          {/* ── Main Panel ───────────────────────────────────────────────── */}
          <div className="flex flex-col flex-1 overflow-hidden">
            {/* Search + breadcrumbs toolbar */}
            <div className="px-5 py-3 border-b dark:border-gray-800 shrink-0 space-y-2">
              {/* Breadcrumbs (only for navigable sections) */}
              {currentSection.navigable && (
                <div className="flex items-center gap-1 text-sm text-gray-500 dark:text-gray-400 flex-wrap">
                  {breadcrumbs.map((node, idx) => (
                    <React.Fragment key={`${node.id ?? "root"}-${idx}`}>
                      {idx > 0 && (
                        <ChevronRight className="h-3.5 w-3.5 text-gray-300 dark:text-gray-600 shrink-0" />
                      )}
                      <button
                        onClick={() => handleBreadcrumbClick(node, idx)}
                        className={`hover:underline truncate max-w-[160px] ${
                          idx === breadcrumbs.length - 1
                            ? "text-gray-900 dark:text-white font-semibold"
                            : "hover:text-primary-600 dark:hover:text-primary-400"
                        }`}
                      >
                        {node.name}
                      </button>
                    </React.Fragment>
                  ))}
                </div>
              )}

              {/* Search box */}
              <div className="relative">
                <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" />
                <Input
                  placeholder={t("dms.search") || "Search…"}
                  value={searchQuery}
                  onChange={(e) => setSearchQuery(e.target.value)}
                  className="pl-9 h-9 text-sm bg-gray-50 dark:bg-gray-800 border-gray-200 dark:border-gray-700"
                />
              </div>
            </div>

            {/* File table */}
            <div className="flex-1 overflow-y-auto">
              {loading ? (
                <div className="flex items-center justify-center h-full gap-2 text-gray-400 dark:text-gray-500">
                  <Loader2 className="h-6 w-6 animate-spin" />
                  <span className="text-sm">
                    {t("dms.loading") || "Loading…"}
                  </span>
                </div>
              ) : error ? (
                <div className="flex flex-col items-center justify-center h-full gap-2 py-16 text-red-500">
                  <AlertCircle className="h-10 w-10 text-red-300" />
                  <p className="text-sm font-medium">{error}</p>
                  <Button variant="outline" size="sm" onClick={loadContents}>
                    {t("dms.retry") || "Retry"}
                  </Button>
                </div>
              ) : items.length === 0 ? (
                <div className="flex flex-col items-center justify-center h-full gap-2 py-16 text-gray-400 dark:text-gray-500">
                  <XCircle className="h-10 w-10 text-gray-300 dark:text-gray-700" />
                  <p className="text-sm font-medium">
                    {debouncedSearch
                      ? t("dms.noSearchResults") || "No files match your search"
                      : t("dms.emptyFolder") || "Nothing to show here"}
                  </p>
                </div>
              ) : (
                <table className="w-full text-left border-collapse text-sm">
                  <thead className="sticky top-0 bg-white dark:bg-gray-900 border-b dark:border-gray-800 z-10">
                    <tr className="text-gray-500 dark:text-gray-400 font-semibold select-none">
                      <th className="p-3 w-10 text-center">
                        {documentsOnPage.length > 0 && (
                          <input
                            type="checkbox"
                            checked={isAllSelected}
                            onChange={handleSelectAllToggle}
                            className="rounded border-gray-300 text-primary-600 focus:ring-primary-500 cursor-pointer h-4 w-4"
                          />
                        )}
                      </th>
                      <th className="p-3">{t("dms.name") || "Name"}</th>
                      <th className="p-3 hidden md:table-cell">
                        {t("dms.owner") || "Owner"}
                      </th>
                      <th className="p-3 hidden sm:table-cell">
                        {t("dms.size") || "Size"}
                      </th>
                      <th className="p-3 hidden lg:table-cell">
                        {t("dms.date") || "Last Modified"}
                      </th>
                    </tr>
                  </thead>
                  <tbody className="divide-y divide-gray-100 dark:divide-gray-800 bg-white dark:bg-gray-900">
                    {displayGroups.flatMap((group) => [
                      <tr
                        key={`group-${group.label}`}
                        className="bg-gray-50 dark:bg-gray-800/60"
                      >
                        <td
                          colSpan={5}
                          className="px-3 py-2 text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400"
                        >
                          {group.label}
                        </td>
                      </tr>,
                      ...group.items.map((item) => {
                        const isFolder = item.type === "folder";
                        const isSelected = selectedDocs.has(item.id);
                        const nameStr = pickName(
                          item.name,
                          isFolder ? "Untitled Folder" : "Untitled Document",
                        );
                        const ownerName =
                          resolveOwnerName(item.ownerName) || "N/A";
                        const sizeStr = isFolder
                          ? "--"
                          : formatBytes(item.fileInfo?.size ?? item.size ?? 0);
                        const dateStr = item.updatedAt
                          ? new Date(item.updatedAt).toLocaleDateString()
                          : "--";

                        return (
                          <tr
                            key={item.id}
                            onClick={() => !isFolder && handleDocClick(item)}
                            onDoubleClick={() =>
                              isFolder && handleFolderClick(item)
                            }
                            className={`hover:bg-gray-50 dark:hover:bg-gray-800/40 transition-colors select-none cursor-pointer ${
                              isSelected
                                ? "bg-primary-50/50 dark:bg-primary-950/20"
                                : ""
                            }`}
                          >
                            {/* Checkbox */}
                            <td
                              className="p-3 text-center"
                              onClick={(e) => e.stopPropagation()}
                            >
                              {!isFolder ? (
                                <input
                                  type="checkbox"
                                  checked={isSelected}
                                  onChange={() => handleDocClick(item)}
                                  className="rounded border-gray-300 text-primary-600 focus:ring-primary-500 cursor-pointer h-4 w-4"
                                />
                              ) : (
                                <div className="h-4 w-4" />
                              )}
                            </td>

                            {/* Icon + Name */}
                            <td className="p-3 font-medium flex items-center gap-3 truncate max-w-xs sm:max-w-md">
                              <div className="shrink-0 flex items-center justify-center">
                                {isFolder ? (
                                  <ODWinFolderSvg className="h-8 w-8 text-amber-400 dark:text-amber-500" />
                                ) : (
                                  renderDocIcon(item)
                                )}
                              </div>
                              <span
                                className={`truncate text-gray-800 dark:text-gray-200 ${
                                  isFolder
                                    ? "hover:underline font-semibold"
                                    : ""
                                }`}
                                onClick={(e) => {
                                  if (isFolder) {
                                    e.stopPropagation();
                                    handleFolderClick(item);
                                  }
                                }}
                              >
                                {nameStr}
                              </span>
                              {isSelected && (
                                <CheckCircle2 className="h-4 w-4 text-primary-500 shrink-0 ml-auto" />
                              )}
                            </td>

                            {/* Owner */}
                            <td className="p-3 text-gray-500 dark:text-gray-400 truncate hidden md:table-cell">
                              {ownerName}
                            </td>

                            {/* Size */}
                            <td className="p-3 text-gray-500 dark:text-gray-400 hidden sm:table-cell">
                              {sizeStr}
                            </td>

                            {/* Date */}
                            <td className="p-3 text-gray-500 dark:text-gray-400 hidden lg:table-cell">
                              {dateStr}
                            </td>
                          </tr>
                        );
                      }),
                    ])}
                  </tbody>
                </table>
              )}
            </div>

            {/* Pagination */}
            {totalPages > 1 && (
              <div className="px-5 py-3 border-t dark:border-gray-800 flex items-center justify-between shrink-0 bg-white dark:bg-gray-900">
                <span className="text-xs text-gray-500 dark:text-gray-400">
                  Page {page} of {totalPages} &bull; {totalCount} item
                  {totalCount !== 1 ? "s" : ""}
                </span>
                <div className="flex items-center gap-1">
                  <Button
                    variant="outline"
                    size="sm"
                    onClick={() => setPage((p) => Math.max(1, p - 1))}
                    disabled={page <= 1}
                  >
                    <ChevronLeft className="h-4 w-4" />
                  </Button>
                  <Button
                    variant="outline"
                    size="sm"
                    onClick={() => setPage((p) => Math.min(totalPages, p + 1))}
                    disabled={page >= totalPages}
                  >
                    <ChevronRightIcon className="h-4 w-4" />
                  </Button>
                </div>
              </div>
            )}
          </div>
        </div>

        {/* ── Footer ─────────────────────────────────────────────────────── */}
        <DialogFooter className="px-6 py-4 border-t dark:border-gray-800 flex items-center justify-between shrink-0 bg-white dark:bg-gray-900">
          <span className="text-sm text-gray-500 dark:text-gray-400">
            {selectedCount > 0
              ? `${selectedCount} file${selectedCount !== 1 ? "s" : ""} selected`
              : t("dms.picker.hint") || "Click a file to select it"}
          </span>
          <div className="flex gap-2">
            <Button variant="outline" onClick={onClose}>
              {t("common.cancel") || "Cancel"}
            </Button>
            <Button
              onClick={handleAttach}
              disabled={selectedCount === 0}
              className="gap-1.5"
            >
              <CheckCircle2 className="h-4 w-4" />
              {t("dms.picker.attach") || "Attach"}{" "}
              {selectedCount > 0 && `(${selectedCount})`}
            </Button>
          </div>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
