llmApp.factory("ParamsHelperService", [
    "DataikuAPI",
    "APIXHRService",
    "$q",
    "Logger",
    function (DataikuAPI, APIXHRService, $q, Logger) {
        const CONNECTION_TYPES = {
            FILESYSTEM: "Filesystem",
            EC2: "EC2",
            FTP: "FTP",
            SSH: "SSH",
            AZURE: "Azure",
            GCS: "GCS",
            HDFS: "HDFS",
            SHAREPOINT_ONLINE: "SharePointOnline",
        };

        const service = {
            /**
             * Main entry point - mimics the Python do() function
             */
            do: function (payload, config, pluginConfig, inputs) {
                const parameterName = payload.parameterName;
                const projectKey = payload.projectKey; // Get projectKey from payload

                switch (parameterName) {
                    case "projects_keys":
                        return service.listProjects();

                    case "agents_ids":
                    case "agent_id":
                        return service.listAgents(payload);

                    case "augmented_llms_ids":
                        return service.listAugmentedLlms(payload);

                    case "augmented_llm_id":
                        return service.listSelectedAugmentedLlms(payload);

                    case "tools":
                        return service.listAgentTools(projectKey);

                    case "stories_workspace":
                        return service.listWorkspaces();

                    case "default_fs_connection":
                        return service.listConnectionsByType();

                    case "agents_folder":
                        return service.listProjectsFolders();

                    case "llm_id":
                    case "embedding_llms":
                    case "graph_generation_llm_id":
                        var purpose = payload.purpose || "GENERIC_COMPLETION";
                        return service.listLlmsByConnectionsType(projectKey, purpose);

                    case "worksspace_folder":
                        return service.listWorkspacesFolders(payload);
                    case "selected_agents":
                        return service.listSelectedAgentsAndAugmentedLlms(payload);

                    default:
                        return $q.resolve({
                            choices: [
                                {
                                    value: "wrong",
                                    label: "Problem getting the name of the parameter.",
                                },
                            ],
                        });
                }
            },

            /**
             * Get project agents mapping
             */
            /**
             * Get project agents mapping
             */
            getProjectAgentMapping: function (projectKey) {
                return DataikuAPI.pretrainedModels
                    .listAvailableLLMs(projectKey, "GENERIC_COMPLETION")
                    .then(function (response) {
                        const agentsMap = {};
                        const allLlms =
                            response.data && response.data.identifiers
                                ? response.data.identifiers
                                : [];

                        allLlms.forEach(function (llm) {
                            if (llm.id && llm.id.startsWith("agent")) {
                                agentsMap[llm.id] = llm.friendlyName;
                            }
                        });
                        return agentsMap;
                    })
                    .catch(function (error) {
                        Logger.error("Error getting project agent mapping", error);
                        return {};
                    });
            },
            /**
             * Get project agents
             */
            getProjectAgents: function (projectKey) {
                return service
                    .getProjectAgentMapping(projectKey)
                    .then(function (agentsMap) {
                        const agents = [];
                        Object.keys(agentsMap).forEach(function (agentId) {
                            agents.push({
                                value: projectKey + ":" + agentId,
                                label: agentsMap[agentId],
                                description: "",
                            });
                        });
                        return agents;
                    });
            },

            /**
             * List agents by project
             */
            listAgentsByProject: function (selectedProjects) {
                if (!selectedProjects || selectedProjects.length === 0) {
                    return $q.resolve({});
                }

                const promises = selectedProjects.map(function (projectKey) {
                    return service
                        .getProjectAgents(projectKey)
                        .then(function (agents) {
                            return {
                                projectKey: projectKey,
                                agents: agents,
                            };
                        })
                        .catch(function (error) {
                            Logger.error(
                                "Error getting agents for project: " + projectKey,
                                error
                            );
                            return {
                                projectKey: projectKey,
                                agents: [],
                            };
                        });
                });

                return $q.all(promises).then(function (results) {
                    const agentsByProject = {};
                    results.forEach(function (result) {
                        if (result.agents && result.agents.length > 0) {
                            agentsByProject[result.projectKey] = result.agents;
                        }
                    });
                    return agentsByProject;
                });
            },

            /**
             * Map agents ID to name
             */
            mapAgentsIdName: function (selectedProjects, withProjectKey) {
                withProjectKey = withProjectKey || false;

                return service
                    .listAgentsByProject(selectedProjects)
                    .then(function (agentsByProject) {
                        const agentsMap = {};
                        Object.keys(agentsByProject).forEach(function (projectKey) {
                            agentsByProject[projectKey].forEach(function (agent) {
                                const label = withProjectKey
                                    ? "[" + projectKey + "] " + agent.label
                                    : agent.label;
                                agentsMap[agent.value] = label;
                            });
                        });
                        return agentsMap;
                    });
            },

            /**
             * List selected agents
             */
            listSelectedAgents: function (payload) {
                const selectedAgents = payload.rootModel.agents_ids || [];
                const selectedProjects = payload.rootModel.projects_keys || [];

                return service
                    .mapAgentsIdName(selectedProjects, true)
                    .then(function (agentsMap) {
                        let choices =  selectedAgents.map(function (agent) {
                            return {
                                value: agent,
                                label: agentsMap[agent],
                            };
                        });

                        return { choices: choices };
                    });
            },

            /**
             * List selected augmented LLMs
             */
            listSelectedAugmentedLlms: function(payload) {
                const selectedAugLlms = payload.rootModel.augmented_llms_ids || [];
                const selectedProjects = payload.rootModel.projects_keys || [];

                if (!selectedProjects || selectedProjects.length === 0 || !selectedAugLlms || selectedAugLlms.length === 0) {
                    return $q.resolve({ choices: [] });
                }

                return service.mapAugLlmsIdName(selectedProjects, true)
                    .then(function(augLlmsMap) {
                        const choices = selectedAugLlms.map(function(llm) {
                            return {
                                value: llm,
                                label: augLlmsMap[llm] || llm
                            };
                        });
                        return { choices: choices };
                    });
            },
            /**
             * List augmented LLMs
             */
            listAugmentedLlms: function (payload) {
                const selectedProjects = payload.rootModel.projects_keys || [];

                if (!selectedProjects || selectedProjects.length === 0) {
                    return $q.resolve({choices: []});
                }

                const promises = selectedProjects.map(function (projectKey) {
                    return DataikuAPI.savedmodels.retrievalAugmentedLLMs.list(projectKey)
                        .then(function (response) {
                            const llms = response.data || response || [];
                            return {
                                projectKey: projectKey,
                                llms: llms
                            };
                        })
                        .catch(function (error) {
                            Logger.error("Error listing augmented LLMs for project: " + projectKey, error);
                            return {
                                projectKey: projectKey,
                                llms: []
                            };
                        });
                });

                return $q.all(promises).then(function (results) {
                    const choices = [];

                    results.forEach(function (result) {
                        const projectKey = result.projectKey;
                        result.llms.forEach(function (llm) {
                            choices.push({
                                value: projectKey + ":" + 'retrieval-augmented-llm' + ":" + (llm.value || llm.id),
                                label: "[" + projectKey + "] " + (llm.label || llm.name || llm.friendlyName),
                                description: llm.description || ""
                            });
                        });
                    });

                    return {choices: choices};
                });
            },

            /**
             * List selected agents and augmented LLMs combined
             */
            listSelectedAgentsAndAugmentedLlms: function(payload) {
                const selectedAgents = payload.rootModel.agents_ids || [];
                const selectedAugLlms = payload.rootModel.augmented_llms_ids || [];
                const selectedProjects = payload.rootModel.projects_keys || [];

                if (!selectedProjects || selectedProjects.length === 0) {
                    return $q.resolve({ choices: [] });
                }

                return $q.all({
                    agentsMap: service.mapAgentsIdName(selectedProjects, true),
                    augLlmsMap: service.mapAugLlmsIdName(selectedProjects, true)
                }).then(function(maps) {
                    const agentChoices = selectedAgents.map(function(agent) {
                        return {
                            value: agent,
                            label: maps.agentsMap[agent] || agent
                        };
                    });

                    const augLlmChoices = selectedAugLlms.map(function(llm) {
                        return {
                            value: llm,
                            label: maps.augLlmsMap[llm] || llm
                        };
                    });

                    return { choices: agentChoices.concat(augLlmChoices) };
                });
            },

            /**
             * List workspaces
             */
            listWorkspaces: function () {
                // Probabilistic API call - to be confirmed
                return DataikuAPI.workspaces
                    .list()
                    .then(function (workspaces) {
                        const data = workspaces.data || [];
                        const choices = data.map(function (workspace) {
                            return {
                                value: workspace.workspaceKey,
                                label: workspace.displayName,
                                description: workspace.description,
                            };
                        });
                        return {choices: choices};
                    })
                    .catch(function (error) {
                        Logger.error("Error listing workspaces", error);
                        return {choices: []};
                    });
            },

            /**
             * List project folders
             */
            listProjectsFolders: function () {
                return DataikuAPI.projectFolders.listRootContents(true, false, false, false)
                    .then(function (response) {
                        const rootFolder = response.data || response;
                        const children = rootFolder.folder && rootFolder.folder.children ? rootFolder.folder.children : [];

                        const choices = children.map(function (folder) {
                            return {
                                value: folder.id,
                                label: folder.name
                            };
                        });

                        return {choices: choices};
                    })
                    .catch(function (error) {
                        Logger.error("Error listing project folders", error);
                        return {choices: []};
                    });
            },
            /**
             * List agents
             */
            listAgents: function (payload) {
                const selectedProjects = payload.rootModel.projects_keys || [];

                return service
                    .listAgentsByProject(selectedProjects)
                    .then(function (agentsByProject) {
                        const choices = [];
                        Object.keys(agentsByProject).forEach(function (projectKey) {
                            agentsByProject[projectKey].forEach(function (agent) {
                                choices.push({
                                    value: agent.value,
                                    label: "[" + projectKey + "] " + agent.label,
                                    description: agent.description,
                                });
                            });
                        });
                        return {choices: choices};
                    })
                    .catch(function (error) {
                        Logger.error("Error listing agents", error);
                        return {choices: []};
                    });
            },

            /**
             * List projects
             */
            listProjects: function () {
                return DataikuAPI.projects.list()
                    .then(function (response) {
                        const projects = response.data || [];
                        const choices = projects.map(function (project) {
                            return {
                                value: project.projectKey,
                                label: "[" + project.projectKey + "] " + project.name
                            };
                        });
                        return {choices: choices};
                    })
                    .catch(function (error) {
                        Logger.error("Error listing projects", error);
                        return {choices: []};
                    });
            },

            /**
             * List projects by name
             */
            listProjectsName: function () {
                // Probabilistic API call - to be confirmed
                return DataikuAPI.projects
                    .list()
                    .then(function (projects) {
                        const choices = projects.map(function (project) {
                            return {
                                value: project.name,
                                label: project.name,
                            };
                        });
                        return {choices: choices};
                    })
                    .catch(function (error) {
                        Logger.error("Error listing projects by name", error);
                        return {choices: []};
                    });
            },

            /**
             * List agent tools
             */
            listAgentTools: function (projectKey) {
                // Get projectKey from parameter or try to get from $stateParams
                if (!projectKey) {
                    Logger.warn("No projectKey provided to listAgentTools");
                    return $q.resolve({choices: []});
                }

                return DataikuAPI.agentTools.list(projectKey)
                    .then(function (response) {
                        const toolDefs = response.data || response || [];
                        const choices = toolDefs.map(function (toolDef) {
                            return {
                                value: toolDef.id,
                                label: toolDef.name
                            };
                        });
                        return {choices: choices};
                    })
                    .catch(function (error) {
                        Logger.error("Error listing agent tools", error);
                        return {choices: []};
                    });
            },

            /**
             * List LLMs by connection type
             */
            /**
             * List LLMs by connection type
             */
            listLlmsByConnectionsType: function (projectKey, purpose) {
                purpose = purpose || "GENERIC_COMPLETION";
                const typesToExclude = ["SAVED_MODEL_AGENT", "RETRIEVAL_AUGMENTED"];

                return DataikuAPI.pretrainedModels
                    .listAvailableLLMs(projectKey, purpose)
                    .then(function (response) {
                        const llmByType = {};

                        // Handle new schema: response.data.identifiers
                        const allLlms =
                            response.data && response.data.identifiers
                                ? response.data.identifiers
                                : [];

                        allLlms.forEach(function (llm) {
                            const llmType = llm.type;

                            if (typesToExclude.indexOf(llmType) !== -1) {
                                return;
                            }

                            if (!llmByType[llmType]) {
                                llmByType[llmType] = [];
                            }

                            llmByType[llmType].push({
                                value: llm.id,
                                label: llm.friendlyName,
                                type: llmType,
                            });
                        });

                        return {choices: llmByType};
                    })
                    .catch(function (error) {
                        Logger.error("Error listing LLMs by connection type", error);
                        return {choices: {}};
                    });
            },
            /**
             * List connections by type
             */
            listConnectionsByType: function () {
                const connectionTypes = Object.values(CONNECTION_TYPES);
                const promises = connectionTypes.map(function (connectionType) {
                    return DataikuAPI.connections.getNames(connectionType)
                        .then(function (response) {
                            const connections = response.data || [];
                            return {
                                type: connectionType,
                                connections: connections
                            };
                        })
                        .catch(function (error) {
                            Logger.error("Error processing connection type " + connectionType, error);
                            return {
                                type: connectionType,
                                connections: []
                            };
                        });
                });

                return $q.all(promises).then(function (results) {
                    const connectionMap = {};

                    results.forEach(function (result) {
                        if (result.connections && result.connections.length > 0) {
                            // Initialize array for this connection type if not exists
                            if (!connectionMap[result.type]) {
                                connectionMap[result.type] = [];
                            }
                            // Add each connection name to the array
                            result.connections.forEach(function (connectionName) {
                                connectionMap[result.type].push(connectionName);
                            });
                        }
                    });

                    return {choices: connectionMap};
                });
            },

            /**
             * List workspace folders
             */
            listWorkspacesFolders: function (payload) {
                const projectKey = payload.projectKey;

                // Probabilistic API call - to be confirmed
                return DataikuAPI.managedFolders
                    .listByProject(projectKey)
                    .then(function (managedFolders) {
                        const choices = managedFolders.map(function (folder) {
                            return {
                                value: folder.id,
                                label: folder.name,
                            };
                        });
                        return {choices: choices};
                    })
                    .catch(function (error) {
                        Logger.error("Error listing workspace folders", error);
                        return {choices: []};
                    });
            },
            mapAugLlmsIdName: function (selectedProjects, withProjectKey) {
                withProjectKey = withProjectKey || false;

                if (!selectedProjects || selectedProjects.length === 0) {
                    return $q.resolve({});
                }

                const promises = selectedProjects.map(function (projectKey) {
                    return DataikuAPI.savedmodels.retrievalAugmentedLLMs.list(projectKey)
                        .then(function (response) {
                            const llms = response.data || response || [];
                            return {
                                projectKey: projectKey,
                                llms: llms
                            };
                        })
                        .catch(function (error) {
                            Logger.error("Error mapping augmented LLMs for project: " + projectKey, error);
                            return {
                                projectKey: projectKey,
                                llms: []
                            };
                        });
                });

                return $q.all(promises).then(function (results) {
                    const augLlmsMap = {};

                    results.forEach(function (result) {
                        const projectKey = result.projectKey;
                        result.llms.forEach(function (llm) {
                            const id = projectKey + ":" + 'retrieval-augmented-llm' + ":" + (llm.value || llm.id);
                            const name = llm.label || llm.name || llm.friendlyName;
                            const label = withProjectKey
                                ? "[" + projectKey + "] " + name
                                : name;
                            augLlmsMap[id] = label;
                        });
                    });

                    return augLlmsMap;
                });
            },

        };

        return service;
    },
]);
