#include "BigDataStatMeth.hpp"

//' Move HDF5 Dataset
//'
//' @description
//' Moves an HDF5 dataset from one location to another within the same HDF5 file.
//' This function automatically handles moving associated rownames and colnames 
//' datasets, creates parent groups if needed, and updates all internal references.
//'
//' @param filename Character string. Path to the HDF5 file
//' @param source_path Character string. Current path to the dataset (e.g., "/group1/dataset1")
//' @param dest_path Character string. New path for the dataset (e.g., "/group2/new_name")
//' @param overwrite Logical. Whether to overwrite destination if it exists (default: FALSE)
//'
//' @return List with components. If an error occurs, all string values are 
//' returned as empty strings (""):
//' \describe{
//'   \item{fn}{Character string with the HDF5 filename}
//'   \item{ds}{Character string with the full dataset path to the moved dataset 
//'   in its new location (group/dataset)}
//' }
//'
//' @details
//' This function provides a high-level interface for moving datasets within HDF5 files.
//' The operation is efficient as it uses HDF5's native linking mechanism without 
//' copying actual data.
//'
//' Key features:
//' \itemize{
//'   \item Moves main dataset and associated rownames/colnames datasets
//'   \item Creates parent directory structure automatically
//'   \item Preserves all dataset attributes and properties
//'   \item Updates internal dataset references
//'   \item Efficient metadata-only operation
//'   \item Comprehensive error handling
//' }
//'
//' @section Behavior:
//' \itemize{
//'   \item If the destination parent groups don't exist, they will be created automatically
//'   \item Associated rownames and colnames datasets are moved to the same new group
//'   \item All dataset attributes and properties are preserved during the move
//'   \item The operation is atomic - either all elements move successfully or none do
//' }
//'
//' @section Requirements:
//' \itemize{
//'   \item The HDF5 file must exist and be accessible
//'   \item The source dataset must exist
//'   \item The file must not be locked by another process
//'   \item User must have read-write permissions on the file
//' }
//'
//' @examples
//' \donttest{
//' fn <- tempfile(fileext = ".h5")
//' 
//' # Create a dataset to move
//' hdf5_create_matrix(fn, "old_group/my_dataset",
//'                    data = matrix(rnorm(100), 10, 10))
//' 
//' # Move dataset to a different group
//' res <- bdmove_hdf5_dataset(fn,
//'                            source_path = "old_group/my_dataset",
//'                            dest_path   = "new_group/my_dataset")
//' 
//' # Rename dataset within the same group
//' hdf5_create_matrix(fn, "data/old_name",
//'                    data = matrix(rnorm(100), 10, 10))
//' res <- bdmove_hdf5_dataset(fn,
//'                            source_path = "data/old_name",
//'                            dest_path   = "data/new_name")
//' 
//' hdf5_close_all()
//' unlink(fn)
//' }
//'
//' @family BigDataStatMeth HDF5 utilities
//' @author BigDataStatMeth package authors
//' @export
 // [[Rcpp::export]]
Rcpp::List bdmove_hdf5_dataset(std::string filename,
                     std::string source_path,
                     std::string dest_path, 
                     bool overwrite = false)
{
    
    
    Rcpp::List lst_return = Rcpp::List::create(Rcpp::Named("fn") = "",
                                               Rcpp::Named("ds") = "");
     
     try {
         
         H5::Exception::dontPrint();

        //  BigDataStatMeth::hdf5Dataset* dataset = nullptr;
         std::unique_ptr<BigDataStatMeth::hdf5Dataset> dataset(nullptr);
         
         // Input validation
         if (filename.empty()) {
             Rcpp::stop("Error: filename cannot be empty");
             return(lst_return);
         }
         
         if (source_path.empty()) {
             Rcpp::stop("Error: source_path cannot be empty");
             return(lst_return);
         }
         
         if (dest_path.empty()) {
             Rcpp::stop("Error: dest_path cannot be empty");
             return(lst_return);
         }
         
         if (source_path == dest_path) {
             Rcpp::stop("Error: source_path and dest_path cannot be the same");
             return(lst_return);
         }
         
         // Create hdf5Dataset object with current path
        //  dataset = new BigDataStatMeth::hdf5Dataset(filename, source_path, false);
        dataset.reset( new BigDataStatMeth::hdf5Dataset(filename, source_path, false) );
        dataset->openDataset();
         
        // Perform the move operation
        dataset->moveDataset(dest_path, overwrite);
         
        //  // Clean up
        //  delete dataset; dataset = nullptr;
         
         lst_return["fn"] = filename;
         lst_return["ds"] = dest_path;
         
         return(lst_return);
         
     } catch (const std::exception& e) {
         Rcpp::stop("Exception in bdmove_hdf5_dataset: " + std::string(e.what()));
         return(lst_return);
     } catch (...) {
         Rcpp::stop("Unknown exception in bdmove_hdf5_dataset");
         return(lst_return);
     }
 }
