001/*
002 * Copyright 2025 devteam@scivicslab.com
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing,
011 * software distributed under the License is distributed on an
012 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013 * either express or implied.  See the License for the
014 * specific language governing permissions and limitations
015 * under the License.
016 */
017
018package com.scivicslab.actoriac.cli;
019
020import java.io.File;
021import java.io.IOException;
022import java.net.HttpURLConnection;
023import java.net.URL;
024import java.util.concurrent.Callable;
025
026import picocli.CommandLine;
027import picocli.CommandLine.Command;
028import picocli.CommandLine.Option;
029
030/**
031 * CLI tool for clearing (deleting) the H2 log database files.
032 *
033 * <p>This command safely deletes the database files after checking
034 * that the log server is not running.</p>
035 *
036 * <p>Usage examples:</p>
037 * <pre>
038 * # Clear the default database
039 * java -jar actor-IaC.jar db-clear --db logs
040 *
041 * # Force clear without checking log server
042 * java -jar actor-IaC.jar db-clear --db logs --force
043 * </pre>
044 *
045 * @author devteam@scivicslab.com
046 * @since 2.12.0
047 */
048@Command(
049    name = "db-clear",
050    mixinStandardHelpOptions = true,
051    versionProvider = VersionProvider.class,
052    description = "Clear (delete) the H2 log database files."
053)
054public class DbClearCLI implements Callable<Integer> {
055
056    @Option(
057        names = {"--db"},
058        description = "H2 database path (without .mv.db extension)",
059        required = true
060    )
061    private File dbPath;
062
063    @Option(
064        names = {"--http-port"},
065        description = "HTTP port to check for running log server",
066        defaultValue = "29091"
067    )
068    private int httpPort;
069
070    @Option(
071        names = {"-f", "--force"},
072        description = "Force clear without checking if log server is running"
073    )
074    private boolean force;
075
076    /**
077     * Main entry point for the db-clear CLI.
078     *
079     * @param args command line arguments
080     */
081    public static void main(String[] args) {
082        int exitCode = new CommandLine(new DbClearCLI()).execute(args);
083        System.exit(exitCode);
084    }
085
086    @Override
087    public Integer call() {
088        // Check if log server is running
089        if (!force && isLogServerRunning()) {
090            System.err.println("Error: Log server is running on HTTP port " + httpPort);
091            System.err.println("Please stop the log server first, or use --force to skip this check.");
092            return 1;
093        }
094
095        File mvDb = new File(dbPath.getAbsolutePath() + ".mv.db");
096        File traceDb = new File(dbPath.getAbsolutePath() + ".trace.db");
097
098        boolean anyDeleted = false;
099
100        if (mvDb.exists()) {
101            if (mvDb.delete()) {
102                System.out.println("Deleted: " + mvDb.getAbsolutePath());
103                anyDeleted = true;
104            } else {
105                System.err.println("Failed to delete: " + mvDb.getAbsolutePath());
106                return 1;
107            }
108        }
109
110        if (traceDb.exists()) {
111            if (traceDb.delete()) {
112                System.out.println("Deleted: " + traceDb.getAbsolutePath());
113                anyDeleted = true;
114            } else {
115                System.err.println("Failed to delete: " + traceDb.getAbsolutePath());
116                return 1;
117            }
118        }
119
120        if (!anyDeleted) {
121            System.out.println("No database files found at: " + dbPath.getAbsolutePath());
122        } else {
123            System.out.println("Database cleared successfully.");
124        }
125
126        return 0;
127    }
128
129    /**
130     * Checks if the log server is running by attempting to connect to the HTTP info endpoint.
131     *
132     * @return true if log server is running
133     */
134    private boolean isLogServerRunning() {
135        try {
136            URL url = new URL("http://localhost:" + httpPort + "/info");
137            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
138            conn.setRequestMethod("GET");
139            conn.setConnectTimeout(1000);
140            conn.setReadTimeout(1000);
141            int responseCode = conn.getResponseCode();
142            conn.disconnect();
143            return responseCode == 200;
144        } catch (IOException e) {
145            // Connection failed, server is not running
146            return false;
147        }
148    }
149}