// File: src/pages/User/Dashboard/Dashboard.jsx
// UIX version - Theme-aware Dashboard with performance optimizations

import React, { useState, useEffect, useCallback, useMemo, useRef } from "react";
import { useNavigate, useLocation, Link } from "react-router";
import {
  useDashboard,
  useFiles,
  useCrypto,
  useAuth,
} from "../../../services/Services";
import withPasswordProtection from "../../../hocs/withPasswordProtection";
import Layout from "../../../components/Layout/Layout";
import { Card, Button, Alert, Spinner, useUIXTheme } from "../../../components/UIX";
import {
  CloudArrowUpIcon,
  FolderIcon,
  DocumentIcon,
  ArrowDownTrayIcon,
  ArrowPathIcon,
  ArrowTrendingUpIcon,
  ClockIcon,
  SparklesIcon,
} from "@heroicons/react/24/outline";

// Cache the dynamic import to avoid repeated imports
let FileCryptoServiceCache = null;
const getFileCryptoService = async () => {
  if (!FileCryptoServiceCache) {
    const module = await import("../../../services/Crypto/FileCryptoService.js");
    FileCryptoServiceCache = module.default;
  }
  return FileCryptoServiceCache;
};

const Dashboard = () => {
  const navigate = useNavigate();
  const location = useLocation();
  const { getThemeClasses } = useUIXTheme();
  const { dashboardManager } = useDashboard();
  const { getCollectionManager, downloadFileManager, createFileManager } =
    useFiles();
  const { CollectionCryptoService } = useCrypto();
  const { authManager } = useAuth();

  // Refs for cleanup
  const isMountedRef = useRef(true);

  const [isLoading, setIsLoading] = useState(true);
  const [isInitialized, setIsInitialized] = useState(false);
  const [generalError, setGeneralError] = useState("");
  const [fieldErrors, setFieldErrors] = useState({});
  const [dashboardData, setDashboardData] = useState(null);
  const [downloadingFiles, setDownloadingFiles] = useState(new Set());

  // Note: Collection keys are now pre-populated from the dashboard API response
  // in DashboardManager.cacheCollectionKeysFromDashboard()
  // This function only verifies the keys are cached - it does NOT make API calls
  const ensureCollectionKeysLoaded = useCallback(
    async (collectionIds) => {
      // Simply verify keys are in cache - they should have been populated
      // by DashboardManager.cacheCollectionKeysFromDashboard() from the dashboard API response
      const missingKeys = collectionIds.filter(
        (id) => !CollectionCryptoService.getCachedCollectionKey(id)
      );

      if (missingKeys.length > 0 && import.meta.env.DEV) {
        console.warn(
          "[Dashboard] Some collection keys were not provided by dashboard API:",
          missingKeys
        );
      }
    },
    [CollectionCryptoService],
  );

  const reDecryptRecentFiles = useCallback(
    async (files) => {
      if (!files || files.length === 0) return [];

      // Use cached import for better performance
      const FileCryptoService = await getFileCryptoService();

      // Process files in parallel for better performance
      const decryptedFiles = await Promise.all(
        files.map(async (file) => {
          try {
            const collectionKey = CollectionCryptoService.getCachedCollectionKey(
              file.collection_id,
            );
            if (!collectionKey) {
              return {
                ...file,
                name: "Locked File",
                _isDecrypted: false,
              };
            }

            const decryptedFile = await FileCryptoService.decryptFileFromAPI(
              file,
              collectionKey,
            );
            return decryptedFile;
          } catch {
            return {
              ...file,
              name: "Locked File",
              _isDecrypted: false,
            };
          }
        })
      );

      return decryptedFiles;
    },
    [CollectionCryptoService],
  );

  const loadDashboardData = useCallback(
    async (forceRefresh = false) => {
      if (!dashboardManager) return;

      setIsLoading(true);
      setGeneralError("");
      setFieldErrors({});

      try {
        if (import.meta.env.DEV) {
          console.log("[Dashboard] Loading dashboard data...", { forceRefresh });
        }
        const data = await dashboardManager.getDashboardData(forceRefresh);

        if (data.recent_files && data.recent_files.length > 0) {
          const filesByCollection = {};
          data.recent_files.forEach((file) => {
            const collectionId = file.collection_id;
            if (!filesByCollection[collectionId]) {
              filesByCollection[collectionId] = [];
            }
            filesByCollection[collectionId].push(file);
          });

          const collectionIds = Object.keys(filesByCollection);
          await ensureCollectionKeysLoaded(collectionIds);
          const reDecryptedFiles = await reDecryptRecentFiles(
            data.recent_files,
          );
          data.recent_files = reDecryptedFiles;
        }

        if (isMountedRef.current) {
          setDashboardData(data);
          setIsInitialized(true);
          if (import.meta.env.DEV) {
            console.log("[Dashboard] Dashboard loaded successfully");
          }
        }
      } catch (err) {
        if (import.meta.env.DEV) {
          console.error("[Dashboard] Failed to load dashboard:", err);
        }

        if (!isMountedRef.current) return;

        // Handle RFC 9457 errors with field-specific validation
        if (err.fieldErrors && Object.keys(err.fieldErrors).length > 0) {
          setFieldErrors(err.fieldErrors);
        }

        if (err.message) {
          setGeneralError(err.message);
        } else {
          setGeneralError("Could not load your dashboard. Please try again.");
        }
        setIsInitialized(true);
      } finally {
        if (isMountedRef.current) {
          setIsLoading(false);
        }
      }
    },
    [dashboardManager, ensureCollectionKeysLoaded, reDecryptRecentFiles],
  );

  const handleFileUploadEvents = useCallback(
    (eventType, eventData) => {
      if (import.meta.env.DEV) {
        console.log(
          "[Dashboard] File upload event received:",
          eventType,
          eventData,
        );
      }

      if (eventType === "file_upload_completed") {
        if (import.meta.env.DEV) {
          console.log(
            "[Dashboard] File upload completed, refreshing dashboard...",
          );
        }
        loadDashboardData(true);
      }
    },
    [loadDashboardData],
  );

  const clearDashboardCache = useCallback(() => {
    if (dashboardManager) {
      if (import.meta.env.DEV) {
        console.log("[Dashboard] Clearing dashboard cache");
      }
      dashboardManager.clearAllCaches();
    }
  }, [dashboardManager]);

  useEffect(() => {
    isMountedRef.current = true;
    return () => {
      isMountedRef.current = false;
    };
  }, []);

  // Initial load when managers become available
  useEffect(() => {
    if (dashboardManager && authManager?.isAuthenticated() && !isInitialized) {
      // Always force refresh on page load to ensure fresh data
      // This handles cases where sharing/unsharing happened in other tabs
      // or when the user was removed from a shared collection
      clearDashboardCache();
      loadDashboardData(true);
    }
  }, [dashboardManager, authManager, isInitialized, loadDashboardData, clearDashboardCache]);

  useEffect(() => {
    if (createFileManager) {
      if (import.meta.env.DEV) {
        console.log("[Dashboard] Adding file upload event listener");
      }
      createFileManager.addFileCreationListener(handleFileUploadEvents);

      return () => {
        if (import.meta.env.DEV) {
          console.log("[Dashboard] Removing file upload event listener");
        }
        createFileManager.removeFileCreationListener(handleFileUploadEvents);
      };
    }
  }, [createFileManager, handleFileUploadEvents]);

  useEffect(() => {
    if (location.state?.refreshDashboard || location.state?.uploadCompleted) {
      if (import.meta.env.DEV) {
        console.log("[Dashboard] Detected upload completion, forcing refresh");
      }
      clearDashboardCache();
      loadDashboardData(true);

      navigate(location.pathname, { replace: true, state: {} });
    }
  }, [
    location.state,
    loadDashboardData,
    clearDashboardCache,
    navigate,
    location.pathname,
  ]);

  useEffect(() => {
    const handleStorageChange = (e) => {
      if (e.key && e.key.includes("file") && e.key.includes("upload")) {
        if (import.meta.env.DEV) {
          console.log(
            "[Dashboard] Storage change detected, refreshing dashboard",
          );
        }
        loadDashboardData(true);
      }
    };

    window.addEventListener("storage", handleStorageChange);
    return () => window.removeEventListener("storage", handleStorageChange);
  }, [loadDashboardData]);

  useEffect(() => {
    const handleDashboardRefresh = () => {
      if (import.meta.env.DEV) {
        console.log("[Dashboard] Dashboard refresh event received");
      }
      clearDashboardCache();
      loadDashboardData(true);
    };

    window.addEventListener("dashboardRefresh", handleDashboardRefresh);
    return () =>
      window.removeEventListener("dashboardRefresh", handleDashboardRefresh);
  }, [loadDashboardData, clearDashboardCache]);

  const handleDownloadFile = useCallback(async (fileId) => {
    if (!downloadFileManager) return;

    try {
      setDownloadingFiles((prev) => new Set(prev).add(fileId));
      await downloadFileManager.downloadFile(fileId, { saveToDisk: true });
    } catch (err) {
      if (import.meta.env.DEV) {
        console.error("[Dashboard] Failed to download file:", err);
      }
      setGeneralError("Could not download file. Please try again.");
    } finally {
      setDownloadingFiles((prev) => {
        const next = new Set(prev);
        next.delete(fileId);
        return next;
      });
    }
  }, [downloadFileManager]);

  const handleManualRefresh = useCallback(async () => {
    if (import.meta.env.DEV) {
      console.log("[Dashboard] Manual refresh triggered");
    }
    clearDashboardCache();
    await loadDashboardData(true);
  }, [clearDashboardCache, loadDashboardData]);

  const handleUploadClick = useCallback(() => {
    navigate("/file-manager/upload");
  }, [navigate]);

  const formatFileSize = useCallback((bytes) => {
    if (!bytes) return "0 B";
    const sizes = ["B", "KB", "MB", "GB", "TB"];
    const i = Math.floor(Math.log(bytes) / Math.log(1024));
    return `${Math.round(bytes / 1024 ** i)} ${sizes[i]}`;
  }, []);

  const getTimeAgo = useCallback((dateString) => {
    if (!dateString) return "Recently";
    const now = new Date();
    const date = new Date(dateString);
    const diffInMinutes = Math.floor((now - date) / (1000 * 60));

    if (diffInMinutes < 60) return "Just now";
    if (diffInMinutes < 1440) return "Today";
    if (diffInMinutes < 2880) return "Yesterday";
    return "This week";
  }, []);

  const getFileIcon = useCallback((fileName) => {
    if (!fileName || fileName === "Locked File") {
      return <DocumentIcon className={`h-5 w-5 ${getThemeClasses("file-icon-default")}`} />;
    }
    const extension = fileName.split(".").pop().toLowerCase();
    const iconClass = "h-5 w-5";

    if (["pdf"].includes(extension)) {
      return <DocumentIcon className={`${iconClass} ${getThemeClasses("file-icon-pdf")}`} />;
    }
    if (["doc", "docx"].includes(extension)) {
      return <DocumentIcon className={`${iconClass} ${getThemeClasses("file-icon-doc")}`} />;
    }
    if (["fig", "sketch"].includes(extension)) {
      return <DocumentIcon className={`${iconClass} ${getThemeClasses("file-icon-design")}`} />;
    }
    return <DocumentIcon className={`${iconClass} ${getThemeClasses("file-icon-default")}`} />;
  }, [getThemeClasses]);

  const stats = useMemo(() =>
    dashboardData
      ? [
          {
            label: "Total Files",
            value: dashboardData.summary?.total_files || 0,
            icon: DocumentIcon,
            gradient: getThemeClasses("stat-files-gradient"),
            bgColor: getThemeClasses("stat-files-bg"),
            textColor: getThemeClasses("stat-files-text"),
          },
          {
            label: "Total Folders",
            value: dashboardData.summary?.total_folders || 0,
            icon: FolderIcon,
            gradient: getThemeClasses("stat-folders-gradient"),
            bgColor: getThemeClasses("stat-folders-bg"),
            textColor: getThemeClasses("stat-folders-text"),
          },
          {
            label: "Storage Limit",
            value:
              dashboardManager?.formatStorageValue(
                dashboardData.summary?.storage_limit,
              ) || "0 GB",
            subtitle: "available",
            icon: CloudArrowUpIcon,
            gradient: getThemeClasses("bg-gradient-secondary"),
            bgColor: getThemeClasses("alert-info-bg"),
            textColor: getThemeClasses("text-primary"),
          },
        ]
      : [],
    [dashboardData, dashboardManager, getThemeClasses]
  );

  const recentFilesDisplay = useMemo(() =>
    dashboardData?.recent_files?.slice(0, 5) || [],
    [dashboardData]
  );

  return (
    <Layout>
      <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
        {/* Header */}
        <div className="mb-8 animate-fade-in-down">
          <div className="flex items-center justify-between">
            <div>
              <h1 className={`text-3xl font-bold ${getThemeClasses("text-primary")} flex items-center`}>
                Welcome Back
                <SparklesIcon className={`h-8 w-8 ${getThemeClasses("icon-sparkles")} ml-2`} />
              </h1>
              <p className={`${getThemeClasses("text-secondary")} mt-1`}>
                Here's what's happening with your files today
              </p>
            </div>
            <div className="flex items-center space-x-3">
              <Button
                onClick={handleManualRefresh}
                disabled={isLoading}
                variant="secondary"
              >
                <span className="flex items-center whitespace-nowrap">
                  <ArrowPathIcon
                    className={`h-4 w-4 mr-2 flex-shrink-0 ${isLoading ? "animate-spin" : ""}`}
                  />
                  Refresh
                </span>
              </Button>
              <Button
                onClick={handleUploadClick}
                variant="primary"
              >
                <span className="flex items-center whitespace-nowrap">
                  <CloudArrowUpIcon className="h-4 w-4 mr-2 flex-shrink-0" />
                  Upload
                </span>
              </Button>
            </div>
          </div>
        </div>

        {/* Loading State */}
        {isLoading && !dashboardData && (
          <div className="flex items-center justify-center py-12">
            <div className="text-center">
              <Spinner size="lg" className="mx-auto mb-4" />
              <p className={getThemeClasses("text-secondary")}>Loading your dashboard...</p>
            </div>
          </div>
        )}

        {/* Error State */}
        {(generalError || Object.keys(fieldErrors).length > 0) && !dashboardData && (
          <Alert type="error" className="mb-8">
            <div>
              <h3 className="text-sm font-medium">
                Error loading dashboard
              </h3>
              {generalError && (
                <p className="text-sm mt-1">{generalError}</p>
              )}
              {Object.keys(fieldErrors).length > 0 && (
                <div className="mt-2">
                  <p className="text-sm font-semibold mb-1">
                    Please fix the following errors:
                  </p>
                  <ul className="list-disc list-inside text-sm space-y-1">
                    {Object.entries(fieldErrors).map(([field, message]) => (
                      <li key={field}>
                        <span className="font-medium capitalize">{field}:</span> {message}
                      </li>
                    ))}
                  </ul>
                </div>
              )}
            </div>
          </Alert>
        )}

        {/* Dashboard Content */}
        {dashboardData && (
          <>
            {/* Stats Grid */}
            <div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8" role="list" aria-label="Dashboard statistics">
              {stats.map((stat, index) => (
                <Card
                  key={stat.label}
                  role="listitem"
                  aria-label={`${stat.label}: ${stat.value}${stat.subtitle ? `, ${stat.subtitle}` : ""}`}
                  className="hover:shadow-lg transform hover:-translate-y-1 transition-all duration-300 animate-fade-in-up overflow-hidden"
                  style={{ animationDelay: `${index * 100}ms` }}
                >
                  <div className="p-6">
                    <div className="flex items-center justify-between mb-4">
                      <div
                        className={`h-12 w-12 ${stat.bgColor} rounded-xl flex items-center justify-center`}
                      >
                        <stat.icon className={`h-6 w-6 ${stat.textColor}`} />
                      </div>
                      <ArrowTrendingUpIcon className={`h-5 w-5 ${getThemeClasses("icon-trending")}`} />
                    </div>
                    <h3 className={`text-3xl font-bold ${getThemeClasses("text-primary")}`}>
                      {stat.value}
                    </h3>
                    <p className={`text-sm ${getThemeClasses("text-secondary")} mt-1`}>
                      {stat.label}
                      {stat.subtitle && (
                        <span className="text-xs text-gray-400 ml-1">({stat.subtitle})</span>
                      )}
                    </p>
                  </div>
                  <div className={`h-1 ${stat.gradient}`}></div>
                </Card>
              ))}
            </div>

            {/* Recent Files */}
            <Card
              className="animate-fade-in-up"
              style={{ animationDelay: "300ms" }}
            >
              <div className="p-6 border-b border-gray-100">
                <div className="flex items-center justify-between">
                  <h2 className={`text-lg font-semibold ${getThemeClasses("text-primary")}`}>
                    Recent Files
                  </h2>
                  <Link
                    to="/file-manager"
                    className={`text-sm font-medium ${getThemeClasses("link-primary")} transition-colors duration-200`}
                  >
                    View all →
                  </Link>
                </div>
              </div>

              {recentFilesDisplay.length > 0 ? (
                <div role="list" aria-label="Recent files" className="divide-y divide-gray-100">
                  {recentFilesDisplay.map((file) => (
                    <div
                      key={file.id}
                      role="listitem"
                      tabIndex={0}
                      aria-label={`${file.name || "Locked File"}, ${formatFileSize(file.size)}, ${getTimeAgo(file.created_at)}`}
                      className="p-4 hover:bg-gray-50 focus:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-blue-500 transition-colors duration-200 group"
                      onKeyDown={(e) => {
                        if ((e.key === "Enter" || e.key === " ") && file._isDecrypted && !downloadingFiles.has(file.id)) {
                          e.preventDefault();
                          handleDownloadFile(file.id);
                        }
                      }}
                    >
                      <div className="flex items-center justify-between">
                        <div className="flex items-center space-x-4">
                          <div className="h-10 w-10 bg-gray-50 rounded-lg flex items-center justify-center group-hover:bg-gray-100 transition-colors duration-200" aria-hidden="true">
                            {getFileIcon(file.name)}
                          </div>
                          <div>
                            <h3 className={`text-sm font-medium ${getThemeClasses("text-primary")}`}>
                              {file.name || "Locked File"}
                            </h3>
                            <div className="flex items-center space-x-4 mt-1">
                              <span className={`text-xs ${getThemeClasses("text-secondary")}`}>
                                {formatFileSize(file.size)}
                              </span>
                              <span className="text-xs text-gray-400" aria-hidden="true">•</span>
                              <span className={`text-xs ${getThemeClasses("text-secondary")} flex items-center`}>
                                <ClockIcon className="h-3 w-3 mr-1" aria-hidden="true" />
                                {getTimeAgo(file.created_at)}
                              </span>
                            </div>
                          </div>
                        </div>
                        <Button
                          onClick={() => handleDownloadFile(file.id)}
                          disabled={
                            !file._isDecrypted || downloadingFiles.has(file.id)
                          }
                          variant="ghost"
                          size="sm"
                          className="opacity-0 group-hover:opacity-100 group-focus-within:opacity-100 transition-opacity duration-200"
                          aria-label={`Download ${file.name || 'file'}`}
                        >
                          {downloadingFiles.has(file.id) ? (
                            <ArrowPathIcon className="h-4 w-4 animate-spin" />
                          ) : (
                            <ArrowDownTrayIcon className="h-4 w-4" />
                          )}
                        </Button>
                      </div>
                    </div>
                  ))}
                </div>
              ) : (
                <div className="p-12 text-center">
                  <div className="h-16 w-16 bg-gray-100 rounded-2xl flex items-center justify-center mx-auto mb-4">
                    <DocumentIcon className="h-8 w-8 text-gray-400" />
                  </div>
                  <h3 className={`text-base font-medium ${getThemeClasses("text-primary")} mb-2`}>
                    No recent files
                  </h3>
                  <p className={`text-sm ${getThemeClasses("text-secondary")}`}>
                    Your recently accessed files will appear here
                  </p>
                </div>
              )}
            </Card>
          </>
        )}

      </div>
    </Layout>
  );
};

export default withPasswordProtection(Dashboard);
