/**
 * FilesList — File Attachment Services › Files List
 *
 * Matches the design image:
 * - Data table with File Name, Size, Category, Source Module, Uploaded By, Upload Date, Version, Actions
 * - Search, Category filter, More Filters dropdown (source_module, tags)
 * - Upload New File modal
 * - Pagination
 * - Tenant-admin sees all admin actions; tenant-user sees limited view (conditional render)
 */

import { useCallback, useEffect, useMemo, useState, type ReactElement } from "react";
import { useNavigate } from "react-router-dom";
import { useSelector } from "react-redux";
import {
  Search,
  Upload,
  FileText,
  Image,
  FileArchive,
  Table as TableIcon,
  MoreHorizontal,
  Download,
  Eye,
  Pencil,
  Trash2,
  ChevronDown,
} from "lucide-react";
import { Layout } from "@/components/layout/Layout";
import { Pagination } from "@/components/shared";
import { cn } from "@/lib/utils";
import fileAttachmentService, {
  type FileAttachment,
  type CategoriesFilterOptions,
} from "@/services/file-attachment-service";
import { moduleService } from "@/services/module-service";
import { FilterDropdown } from "@/components/shared";
import { FileUploadModal } from "@/components/shared/FileUploadModal";
import type { RootState } from "@/store/store";

// ─────────────────────────────────────────────────────────────────────────────
// Helpers
// ─────────────────────────────────────────────────────────────────────────────
function formatDate(value: string): string {
  return new Date(value).toLocaleDateString("en-US", {
    month: "short",
    day: "numeric",
    year: "numeric",
    hour: "2-digit",
    minute: "2-digit",
    hour12: true,
  });
}

function formatBytes(bytes: number): string {
  if (!bytes) return "0 B";
  const k = 1024;
  const sizes = ["B", "KB", "MB", "GB"];
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;
}

function getFileIcon(mime: string, name: string): ReactElement {
  if (mime?.startsWith("image/")) return <Image className="w-4 h-4 text-emerald-500" />;
  if (mime === "application/pdf") return <FileText className="w-4 h-4 text-red-500" />;
  if (
    mime?.includes("spreadsheet") ||
    name?.endsWith(".csv") ||
    name?.endsWith(".xlsx") ||
    name?.endsWith(".xls")
  )
    return <TableIcon className="w-4 h-4 text-green-600" />;
  if (mime?.includes("zip") || mime?.includes("archive"))
    return <FileArchive className="w-4 h-4 text-yellow-500" />;
  return <FileText className="w-4 h-4 text-[#084cc8]" />;
}

const categoryColors: Record<string, string> = {
  finance: "bg-purple-100 text-purple-700",
  marketing: "bg-orange-100 text-orange-700",
  hr: "bg-blue-100 text-blue-700",
  data: "bg-teal-100 text-teal-700",
  legal: "bg-red-100 text-red-700",
  training: "bg-yellow-100 text-yellow-700",
  other: "bg-gray-100 text-gray-600",
};

function getCategoryStyle(cat: string) {
  return categoryColors[cat?.toLowerCase()] || "bg-gray-100 text-gray-600";
}

const moduleColors: Record<string, string> = {
  platform: "bg-indigo-100 text-indigo-700",
  document: "bg-blue-100 text-blue-700",
  capa: "bg-orange-100 text-orange-700",
  training: "bg-yellow-100 text-yellow-700",
  supplier: "bg-green-100 text-green-700",
  audit: "bg-red-100 text-red-700",
  api_key: "bg-gray-100 text-gray-700",
};

function getModuleStyle(mod: string) {
  return moduleColors[mod?.toLowerCase()] || "bg-gray-100 text-gray-600";
}

function getInitials(email: string): string {
  if (!email) return "?";
  const parts = email.split("@")[0].split(".");
  return parts
    .slice(0, 2)
    .map((p) => p[0]?.toUpperCase() || "")
    .join("");
}

const avatarColors = [
  "bg-violet-100 text-violet-700",
  "bg-blue-100 text-blue-700",
  "bg-emerald-100 text-emerald-700",
  "bg-orange-100 text-orange-700",
];

function getAvatarColor(email: string) {
  const idx = (email?.charCodeAt(0) || 0) % avatarColors.length;
  return avatarColors[idx];
}

// ─────────────────────────────────────────────────────────────────────────────
// FilterDropdown (local inline, no shared dependency)
// ─────────────────────────────────────────────────────────────────────────────
interface DropOption { value: string; label: string }

function FilterPill({
  label,
  options,
  value,
  onChange,
}: {
  label: string;
  options: DropOption[];
  value: string | null;
  onChange: (v: string | null) => void;
}): ReactElement {
  const [open, setOpen] = useState(false);
  const selected = options.find((o) => o.value === value);

  return (
    <div className="relative">
      <button
        onClick={() => setOpen(!open)}
        className={cn(
          "inline-flex items-center gap-1.5 h-9 px-3 rounded-lg text-sm font-medium border transition-colors",
          value
            ? "border-[#084cc8] bg-[#084cc8]/5 text-[#084cc8]"
            : "border-[rgba(0,0,0,0.1)] bg-white text-[#475569] hover:border-[#084cc8]/30"
        )}
      >
        {label}
        {selected && <span className="text-[#084cc8]">: {selected.label}</span>}
        <ChevronDown className="w-3.5 h-3.5 opacity-60" />
      </button>
      {open && (
        <>
          <div
            className="fixed inset-0 z-10"
            onClick={() => setOpen(false)}
          />
          <div className="absolute top-full mt-1 left-0 z-20 bg-white border border-[rgba(0,0,0,0.1)] shadow-lg rounded-xl py-1 min-w-[160px]">
            <button
              onClick={() => { onChange(null); setOpen(false); }}
              className={cn(
                "w-full text-left px-3 py-2 text-sm hover:bg-gray-50",
                !value ? "font-semibold text-[#0e1b2a]" : "text-[#475569]"
              )}
            >
              All
            </button>
            {options.map((opt) => (
              <button
                key={opt.value}
                onClick={() => { onChange(opt.value); setOpen(false); }}
                className={cn(
                  "w-full text-left px-3 py-2 text-sm hover:bg-gray-50",
                  value === opt.value ? "font-semibold text-[#0e1b2a]" : "text-[#475569]"
                )}
              >
                {opt.label}
              </button>
            ))}
          </div>
        </>
      )}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// Row action menu
// ─────────────────────────────────────────────────────────────────────────────
function ActionMenu({
  onView,
  onDownload,
  onEdit,
  onDelete,
  canEdit,
  canDelete,
}: {
  onView: () => void;
  onDownload: () => void;
  onEdit: () => void;
  onDelete: () => void;
  canEdit: boolean;
  canDelete: boolean;
}): ReactElement {
  const [open, setOpen] = useState(false);

  return (
    <div className="relative">
      <button
        onClick={() => setOpen(!open)}
        className="w-7 h-7 flex items-center justify-center rounded-lg hover:bg-gray-100 text-[#6b7280] transition-colors"
      >
        <MoreHorizontal className="w-4 h-4" />
      </button>
      {open && (
        <>
          <div className="fixed inset-0 z-10" onClick={() => setOpen(false)} />
          <div className="absolute right-0 top-full mt-1 z-20 bg-white rounded-xl border border-[rgba(0,0,0,0.08)] shadow-lg py-1 min-w-[140px]">
            <button
              onClick={() => { onView(); setOpen(false); }}
              className="w-full flex items-center gap-2 px-3 py-2 text-sm text-[#0e1b2a] hover:bg-gray-50"
            >
              <Eye className="w-3.5 h-3.5 text-[#6b7280]" /> View
            </button>
            <button
              onClick={() => { onDownload(); setOpen(false); }}
              className="w-full flex items-center gap-2 px-3 py-2 text-sm text-[#0e1b2a] hover:bg-gray-50"
            >
              <Download className="w-3.5 h-3.5 text-[#6b7280]" /> Download
            </button>
            {canEdit && (
              <button
                onClick={() => { onEdit(); setOpen(false); }}
                className="w-full flex items-center gap-2 px-3 py-2 text-sm text-[#0e1b2a] hover:bg-gray-50"
              >
                <Pencil className="w-3.5 h-3.5 text-[#6b7280]" /> Edit
              </button>
            )}
            {canDelete && (
              <button
                onClick={() => { onDelete(); setOpen(false); }}
                className="w-full flex items-center gap-2 px-3 py-2 text-sm text-red-500 hover:bg-red-50"
              >
                <Trash2 className="w-3.5 h-3.5" /> Delete
              </button>
            )}
          </div>
        </>
      )}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// Main component
// ─────────────────────────────────────────────────────────────────────────────
const FilesList = (): ReactElement => {
  const navigate = useNavigate();
  const permissions = useSelector((state: RootState) => state.auth.permissions);

  // Permission checks
  const canCreate = permissions.some(
    (p) => (p.resource === "files" || p.resource === "*") && (p.action === "create" || p.action === "*")
  );
  const canUpdate = permissions.some(
    (p) => (p.resource === "files" || p.resource === "*") && (p.action === "update" || p.action === "*")
  );
  const canDelete = permissions.some(
    (p) => (p.resource === "files" || p.resource === "*") && (p.action === "delete" || p.action === "*")
  );

  // ── State ──
  const [files, setFiles] = useState<FileAttachment[]>([]);
  const [total, setTotal] = useState(0);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  // Filters
  const [search, setSearch] = useState("");
  const [categoryFilter, setCategoryFilter] = useState<string | null>(null);
  const [moduleIdFilter, setModuleIdFilter] = useState<string | null>(null);
  const [modules, setModules] = useState<{ id: string; name: string }[]>([]);

  // Pagination
  const [currentPage, setCurrentPage] = useState(1);
  const [limit] = useState(10);
  const offset = (currentPage - 1) * limit;
  const totalPages = Math.max(1, Math.ceil(total / limit));

  // Filter option data
  const [categories, setCategories] = useState<CategoriesFilterOptions["categories"]>([]);

  // Upload modal
  const [showUpload, setShowUpload] = useState(false);

  // Deleting
  const [, setDeletingId] = useState<string | null>(null);

  // ── Load categories ──
  useEffect(() => {
    fileAttachmentService.getCategoriesFilterOptions().then((res) => {
      setCategories(res.data.categories);
    }).catch(() => {});

    moduleService.getMyModules().then((res) => {
      if (res.success) {
        setModules(res.data.map(m => ({ id: m.id, name: m.name })));
      }
    }).catch(() => {});
  }, []);

  // ── Load files ──
  const loadFiles = useCallback(async () => {
    setIsLoading(true);
    setError(null);
    try {
      const res = await fileAttachmentService.list({
        search: search.trim() || undefined,
        category: categoryFilter || undefined,
        source_module_id: moduleIdFilter || undefined,
        limit,
        offset,
      });
      setFiles(res.data);
      setTotal(res.pagination.total);
    } catch (err: any) {
      setError(err?.response?.data?.error?.message || "Failed to load files");
    } finally {
      setIsLoading(false);
    }
  }, [search, categoryFilter, moduleIdFilter, limit, offset]);

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

  const categoryOptions = useMemo<DropOption[]>(() =>
    categories.map((c) => ({ value: c.category, label: c.category })),
  [categories]);

  // ── Actions ──
  const handleDownload = (file: FileAttachment) => {
    fileAttachmentService.download(file.id, file.original_name).catch(() => {});
  };

  const handleDelete = async (id: string) => {
    if (!window.confirm("Delete this file?")) return;
    setDeletingId(id);
    try {
      await fileAttachmentService.delete(id);
      await loadFiles();
    } catch {
      // silence
    } finally {
      setDeletingId(null);
    }
  };

  const clearFilters = () => {
    setSearch("");
    setCategoryFilter(null);
    setModuleIdFilter(null);
    setCurrentPage(1);
  };

  // ─────────────────────────────────────────────────────────────────────────
  // Render
  // ─────────────────────────────────────────────────────────────────────────
  return (
    <Layout
      currentPage="File Attachment Services"
      breadcrumbs={[
        { label: "File Attachment Services" },
        { label: "File List" },
      ]}
      pageHeader={{
        title: "Files List",
        description: "Manage controlled documents across their entire lifecycle.",
        action: canCreate ? (
          <button
            id="upload-new-file-btn"
            onClick={() => setShowUpload(true)}
            className="inline-flex items-center gap-2 h-9 px-4 bg-[#112868] hover:bg-[#0c1e52] text-white rounded-lg text-sm font-semibold transition-colors shadow-sm"
          >
            <Upload className="w-3.5 h-3.5" />
            Upload New File
          </button>
        ) : null,
      }}
    >
      <div className="bg-white border border-[rgba(0,0,0,0.08)] rounded-xl shadow-[0px_4px_24px_0px_rgba(0,0,0,0.02)] overflow-hidden">
        {/* Filter bar */}
        <div className="border-b border-[rgba(0,0,0,0.08)] px-5 py-3.5">
          <div className="flex flex-wrap items-center gap-3">
            {/* Search */}
            <div className="relative">
              <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-[#9aa6b2]" />
              <input
                id="files-search"
                type="text"
                value={search}
                onChange={(e) => { setSearch(e.target.value); setCurrentPage(1); }}
                placeholder="Search by name, ID..."
                className="h-9 w-[240px] pl-9 pr-3 bg-white border border-[rgba(0,0,0,0.1)] rounded-lg text-sm text-[#0e1b2a] placeholder:text-[#c4cbd6] focus:outline-none focus:ring-2 focus:ring-[#084cc8]/20 focus:border-[#084cc8]"
              />
            </div>

            {/* Category filter */}
            <FilterPill
              label="Category"
              options={categoryOptions}
              value={categoryFilter}
              onChange={(v) => { setCategoryFilter(v); setCurrentPage(1); }}
            />

            {/* Source Module filter */}
            <FilterDropdown
              label="Module"
              options={modules.map(m => ({ value: m.id, label: m.name }))}
              value={moduleIdFilter}
              onChange={(val) => {
                setModuleIdFilter(val as string | null);
                setCurrentPage(1);
              }}
              placeholder="All Modules"
            />

            {/* More Filters label pill */}
            {/* <button className="inline-flex items-center gap-1.5 h-9 px-3 rounded-lg text-sm font-medium border border-[rgba(0,0,0,0.1)] bg-white text-[#475569] hover:border-[#084cc8]/30 transition-colors">
              <SlidersHorizontal className="w-3.5 h-3.5" />
              More Filters
              <ChevronDown className="w-3.5 h-3.5 opacity-60" />
            </button> */}

            <div className="ml-auto">
              <button
                onClick={clearFilters}
                className="text-sm font-medium text-[#6b7280] hover:text-[#0f1724] transition-colors"
              >
                Clear filters
              </button>
            </div>
          </div>
        </div>

        {/* Table */}
        <div className="overflow-x-auto">
          <table className="w-full">
            <thead>
              <tr className="border-b border-[rgba(0,0,0,0.06)]">
                {["File Name", "Size", "Category", "Source Module", "Uploaded By", "Upload Date", "Version", "Actions"].map((h) => (
                  <th
                    key={h}
                    className="px-4 py-3 text-left text-[11px] font-semibold text-[#9aa6b2] uppercase tracking-wide whitespace-nowrap"
                  >
                    {h}
                  </th>
                ))}
              </tr>
            </thead>
            <tbody className="divide-y divide-[rgba(0,0,0,0.04)]">
              {isLoading ? (
                Array.from({ length: 5 }).map((_, i) => (
                  <tr key={i}>
                    {Array.from({ length: 8 }).map((__, j) => (
                      <td key={j} className="px-4 py-3">
                        <div className="h-4 bg-gray-100 rounded animate-pulse" />
                      </td>
                    ))}
                  </tr>
                ))
              ) : error ? (
                <tr>
                  <td colSpan={8} className="px-4 py-12 text-center text-sm text-red-500">
                    {error}
                  </td>
                </tr>
              ) : files.length === 0 ? (
                <tr>
                  <td colSpan={8} className="px-4 py-12 text-center">
                    <div className="flex flex-col items-center gap-2">
                      <FileText className="w-10 h-10 text-gray-200" />
                      <p className="text-sm text-[#9aa6b2]">No files found</p>
                      {canCreate && (
                        <button
                          onClick={() => setShowUpload(true)}
                          className="mt-2 text-sm font-medium text-[#084cc8] hover:underline"
                        >
                          Upload your first file
                        </button>
                      )}
                    </div>
                  </td>
                </tr>
              ) : (
                files.map((file) => (
                  <tr
                    key={file.id}
                    className="hover:bg-[#f6f9ff]/60 transition-colors group"
                  >
                    {/* File Name */}
                    <td className="px-4 py-3 min-w-[200px]">
                      <button
                        onClick={() => navigate(`/tenant/files/${file.id}`)}
                        className="flex items-center gap-2.5 hover:text-[#084cc8] transition-colors text-left"
                      >
                        <div className="w-7 h-7 rounded-md bg-gray-50 border border-[rgba(0,0,0,0.06)] flex items-center justify-center shrink-0">
                          {getFileIcon(file.mime_type, file.original_name)}
                        </div>
                        <span className="text-sm font-medium text-[#0e1b2a] group-hover:text-[#084cc8] truncate max-w-[200px]">
                          {file.original_name}
                        </span>
                      </button>
                    </td>

                    {/* Size */}
                    <td className="px-4 py-3 whitespace-nowrap">
                      <span className="text-sm text-[#6b7280]">
                        {file.file_size_formatted || formatBytes(file.file_size)}
                      </span>
                    </td>

                    {/* Category */}
                    <td className="px-4 py-3">
                      {file.category ? (
                        <span
                          className={cn(
                            "inline-block text-xs font-semibold rounded px-2 py-0.5 capitalize",
                            getCategoryStyle(file.category)
                          )}
                        >
                          {file.category}
                        </span>
                      ) : (
                        <span className="text-[#c4cbd6] text-sm">—</span>
                      )}
                    </td>

                    {/* Source Module */}
                    <td className="px-4 py-3">
                      {file.source_module ? (
                        <span
                          className={cn(
                            "inline-block text-xs font-semibold rounded px-2 py-0.5 capitalize",
                            getModuleStyle(file.source_module)
                          )}
                        >
                          {file.source_module}
                        </span>
                      ) : (
                        <span className="text-[#c4cbd6] text-sm">—</span>
                      )}
                    </td>

                    {/* Uploaded By */}
                    <td className="px-4 py-3 min-w-[140px]">
                      {file.uploaded_by_email ? (
                        <div className="flex items-center gap-2">
                          <div
                            className={cn(
                              "w-7 h-7 rounded-full flex items-center justify-center text-[10px] font-bold shrink-0",
                              getAvatarColor(file.uploaded_by_email)
                            )}
                          >
                            {getInitials(file.uploaded_by_email)}
                          </div>
                          <span className="text-sm text-[#0e1b2a] truncate max-w-[130px]">
                            {file.uploaded_by_email.split("@")[0]}
                          </span>
                        </div>
                      ) : (
                        <span className="text-sm text-[#9aa6b2]">Unknown</span>
                      )}
                    </td>

                    {/* Upload Date */}
                    <td className="px-4 py-3 whitespace-nowrap">
                      <span className="text-sm text-[#6b7280]">{formatDate(file.created_at)}</span>
                    </td>

                    {/* Version */}
                    <td className="px-4 py-3 whitespace-nowrap">
                      <span className="text-sm text-[#0e1b2a] font-medium">v{file.version}</span>
                    </td>

                    {/* Actions */}
                    <td className="px-4 py-3">
                      <ActionMenu
                        onView={() => navigate(`/tenant/files/${file.id}`)}
                        onDownload={() => handleDownload(file)}
                        onEdit={() => navigate(`/tenant/files/${file.id}`)}
                        onDelete={() => handleDelete(file.id)}
                        canEdit={canUpdate}
                        canDelete={canDelete}
                      />
                    </td>
                  </tr>
                ))
              )}
            </tbody>
          </table>
        </div>

        {/* Pagination */}
        {total > 0 && (
          <Pagination
            currentPage={currentPage}
            totalPages={totalPages}
            totalItems={total}
            limit={limit}
            onPageChange={setCurrentPage}
            onLimitChange={() => {}}
          />
        )}
      </div>

      {/* Upload modal */}
      <FileUploadModal
        isOpen={showUpload}
        onClose={() => setShowUpload(false)}
        categories={categories}
        onUploaded={() => {
          setShowUpload(false);
          void loadFiles();
        }}
        isTenantAdmin={canCreate}
      />
    </Layout>
  );
};

export default FilesList;
