import React, { useEffect, useState } from "react";
import DashboardNavBar from "./DashboardNavBar";
import DashboardCard from "./DashboardCard";
import MarketPlaceBanner from "./MarketPlaceBanner";
import { getUserData } from "../../functions/getUserData";
import { useSocketStore } from "../../store/builder/store";
import { getAllProjects } from "../../services/dashboard/getAllProjects";
import { sharedWithMeProjects } from "../../services/dashboard/sharedWithMeProject";
import { recentlyViewed } from "../../services/dashboard/recentlyViewed";
import { getTrash } from "../../services/dashboard/getTrash";
import { searchProject } from "../../services/dashboard/searchProjects";
import { trashSearchProject } from "../../services/dashboard/trashSearchProject";
import { restoreTrash } from "../../services/dashboard/restoreTrash";
import { generateUniqueId } from "../../functions/generateUniqueId";
import ProjectSocketRes from "./socket/projectSocketRes";

interface Project {
    _id: string;
    projectName: string;
    thumbnail: string;
    createdBy: { _id: string; userName: string };
    projectUuid?: string;
    createdAt?: string;
    DeletedAt?: string;
}

interface ProjectCollection {
    [key: string]: Project[];
}

type Folder = "home" | "projects" | "shared" | "trash";

interface DashboardMainProps {
    activeFolder: Folder;
}

const DashboardMain: React.FC<DashboardMainProps> = ({ activeFolder }) => {
    const [activeSubFolder, setActiveSubFolder] = useState("myProjects");
    const [projectsData, setProjectsData] = useState<ProjectCollection>({});
    const [isSearchActive, setIsSearchActive] = useState<boolean>(false);
    const [duplicateData, setDuplicateData] = useState<Object>({});
    const [openKebabProjectId, setOpenKebabProjectId] = useState<string | null>(null);
    const [projectsCache, setProjectsCache] = useState<{
        [key: string]: ProjectCollection;
    }>({});

    const { userId, organization } = getUserData();
    const { projectSocket } = useSocketStore();

    // #region API Fetchers
    const fetchData = async () => {
        const cacheKey = activeFolder + (activeFolder === "projects" ? `-${activeSubFolder}` : "");

        if (projectsCache[cacheKey] && !isSearchActive) {
            setProjectsData(projectsCache[cacheKey]);
            return;
        }

        try {
            let projects: ProjectCollection = {}; // initialize as empty object

            switch (activeFolder) {
                case "home":
                    projects = await recentlyViewed(organization, userId);
                    break;
                case "projects":
                    if (activeSubFolder === "myProjects") {
                        projects = await getAllProjects(userId, organization);
                    } else {
                        projects = await sharedWithMeProjects();
                    }
                    break;
                case "trash":
                    projects = await getTrash(organization);
                    break;
            }

            // Only update cache if projects is not empty
            if (projects && JSON.stringify(projects) !== JSON.stringify(projectsData)) {
                setProjectsCache((prev) => ({ ...prev, [cacheKey]: projects }));
                setProjectsData(projects);
            }
        } catch (error) {
            console.error(error);
        }
    };

    // #region Search Handlers
    const handleSearch = async (inputValue: string) => {
        if (!inputValue.trim()) {
            setIsSearchActive(false);
            return;
        }

        let results;
        if (activeFolder === "trash") {
            results = await trashSearchProject(organization, userId, inputValue);
        } else {
            results = await searchProject(organization, userId, inputValue);
        }

        setIsSearchActive(true);
        setProjectsData(results?.message ? {} : results);
    };

    // #region Socket Actions
    const handleDelete = async (projectId: string): Promise<void> => {
        if (projectSocket) {
            projectSocket.emit("v1:project:delete", {
                projectId,
                organization,
                userId,
            });
        }
        updateStateAfterRemove(projectId);
    };

    const handlePermanentDelete = async (projectId: string): Promise<void> => {
        if (projectSocket) {
            projectSocket.emit("v1:trash:delete", {
                projectId,
                organization,
                userId,
            });
        }
        updateStateAfterRemove(projectId);
    };

    const handleRestore = async (projectId: string): Promise<void> => {
        await restoreTrash(organization, projectId);
        updateStateAfterRemove(projectId);
    };

    const handleDuplicate = async (projectId: string, projectName: string, thumbnail: string): Promise<void> => {
        if (projectSocket) {
            projectSocket.emit("v1:project:Duplicate", {
                userId,
                thumbnail,
                organization,
                projectUuid: generateUniqueId(),
                refProjectID: projectId,
                projectName,
            });
        }
    };

    // #region Project Map
    const updateStateAfterRemove = (projectId: string) => {
        setProjectsData((prev: ProjectCollection) => {
            const key = Object.keys(prev)[0];
            const updatedList = prev[key]?.filter((p) => p._id !== projectId) || [];
            return { ...prev, [key]: updatedList };
        });
        setIsSearchActive(false);
    };

    const renderProjects = () => {
        const key = Object.keys(projectsData)[0];
        const projectList = projectsData[key];

        if (!projectList?.length) {
            return <div className="empty-state">No projects found</div>;
        }

        return projectList.map((project) => (
            <DashboardCard
                key={project._id}
                projectName={project.projectName}
                thumbnail={project.thumbnail}
                projectId={project._id}
                createdBy={project.createdBy}
                createdAt={activeFolder === "trash" ? project.DeletedAt : project.createdAt}
                {...(activeFolder === "home" && {
                    handleDeleteProject: handleDelete,
                    handleDuplicateRecentProject: handleDuplicate,
                    setRecentDuplicateData: setDuplicateData,
                })}
                {...(activeSubFolder === "myProjects" && {
                    handleDeleteProject: handleDelete,
                    handleDuplicateWorkspaceProject: handleDuplicate,
                    setProjectDuplicateData: setDuplicateData,
                })}
                {...(activeSubFolder === "shared" && {
                    handleDuplicateWorkspaceProject: handleDuplicate,
                    setProjectDuplicateData: setDuplicateData,
                    active: "shared",
                })}
                {...(activeFolder === "trash" && {
                    handleRestoreProject: handleRestore,
                    handleTrashDeleteProject: handlePermanentDelete,
                    active: "trash",
                })}
                openKebabProjectId={openKebabProjectId}
                setOpenKebabProjectId={setOpenKebabProjectId}
            />
        ));
    };

    // #region Use Effects
    useEffect(() => {
        if (!isSearchActive) fetchData();
        // eslint-disable-next-line
    }, [activeFolder, isSearchActive, activeSubFolder]);

    return (
        <div className="dashboard-home-container">
            <DashboardNavBar
                page={activeFolder}
                {...(activeFolder === "trash" ? { handleTrashSearch: handleSearch } : { handleProjectsSearch: handleSearch, handleRecentProjectSearch: handleSearch })}
            />

            {activeFolder === "home" && <MarketPlaceBanner />}

            <div className="dashboard-container" style={{ height: "calc(100% - 87px)" }}>
                {activeFolder === "projects" && (
                    <div className="header-wrapper" style={{ display: "flex", gap: "7px" }}>
                        <button className={`header ${activeSubFolder === "myProjects" && "active"}`} onClick={() => setActiveSubFolder("myProjects")}>
                            My Projects
                        </button>
                        <button className={`header ${activeSubFolder === "shared" && "active"}`} onClick={() => setActiveSubFolder("shared")}>
                            Shared with me
                        </button>
                    </div>
                )}

                <div className="cards-container">{renderProjects()}</div>

                <ProjectSocketRes setIsSearchActive={setIsSearchActive} {...(activeFolder === "home" ? { setRecentProjects: setProjectsData } : { setWorkspaceProjects: setProjectsData })} />
            </div>
        </div>
    );
};

export default DashboardMain;
