import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileStatus;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URI;

public class HDFSTest {
    
    // HDFS root URI
    private static final String HDFS_URI = "hdfs://namenode:9000";
    private static FileSystem fs;

    public static void main(String[] args) {
        try {
            // 1. Initialize Configuration
            Configuration conf = new Configuration();
            fs = FileSystem.get(URI.create(HDFS_URI), conf, "root");

            // Define file paths
            Path filePath = new Path("/user/root/input/java_crud_test.txt");
            Path renamedPath = new Path("/user/root/input/java_crud_renamed.txt");

            System.out.println(">>> STARTING HDFS CRUD TEST <<<");

            // 2. CREATE: Create a file and write data
            System.out.println("\n[1] TEST: Create & Write");
            createFile(filePath, "Hello Hadoop! This is a test for CRUD operations.");

            // 3. READ: Read the content
            System.out.println("\n[2] TEST: Read");
            readFile(filePath);

            // 4. UPDATE (Rename): Rename the file
            System.out.println("\n[3] TEST: Rename");
            renameFile(filePath, renamedPath);

            // 5. LIST: Check file status
            System.out.println("\n[4] TEST: List File Status");
            listFileStatus(renamedPath);

            // 6. DELETE: Delete the file
            System.out.println("\n[5] TEST: Delete");
            deleteFile(renamedPath);

            System.out.println("\n>>> ALL TESTS PASSED SUCCESSFULLY! <<<");

            fs.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // --- Helper Methods ---

    // Create and Write
    private static void createFile(Path path, String content) throws Exception {
        // overwrite = true
        FSDataOutputStream os = fs.create(path, true);
        os.write(content.getBytes());
        os.close();
        System.out.println(">>> Success: Created file " + path.toString());
    }

    // Read
    private static void readFile(Path path) throws Exception {
        if (!fs.exists(path)) {
            System.out.println(">>> Error: File not found!");
            return;
        }
        FSDataInputStream is = fs.open(path);
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        String line = br.readLine();
        System.out.println(">>> Content: " + line);
        br.close();
        is.close();
    }

    // Rename
    private static void renameFile(Path oldPath, Path newPath) throws Exception {
        if (fs.rename(oldPath, newPath)) {
            System.out.println(">>> Success: Renamed " + oldPath.getName() + " to " + newPath.getName());
        } else {
            System.out.println(">>> Error: Rename failed!");
        }
    }

    // List Status
    private static void listFileStatus(Path path) throws Exception {
        FileStatus status = fs.getFileStatus(path);
        System.out.println(">>> File Path: " + status.getPath());
        System.out.println(">>> Owner: " + status.getOwner());
        System.out.println(">>> Size: " + status.getLen() + " bytes");
        System.out.println(">>> Replication: " + status.getReplication());
    }

    // Delete
    private static void deleteFile(Path path) throws Exception {
        // recursive = true (though not strictly needed for files)
        if (fs.delete(path, true)) {
            System.out.println(">>> Success: Deleted file " + path.toString());
        } else {
            System.out.println(">>> Error: Delete failed!");
        }
    }
}
