import java.io.IOException;
import java.nio.file.*;
import java.time.Duration;
import java.util.List;
import java.util.concurrent.TimeUnit;

/** Java 21, local teaching example; arguments are passed without a shell. */
public final class TranscodeRunner {
    public record Result(int exitCode, Path log) {}
    public static Result run(List<String> command, Duration timeout, Path log)
            throws IOException, InterruptedException {
        if (command.isEmpty() || timeout.isZero() || timeout.isNegative())
            throw new IllegalArgumentException("command and positive timeout required");
        Files.createDirectories(log.toAbsolutePath().getParent());
        Process process = new ProcessBuilder(command).redirectErrorStream(true)
                .redirectOutput(log.toFile()).start();
        try {
            if (!process.waitFor(timeout.toMillis(), TimeUnit.MILLISECONDS)) {
                stop(process);
                throw new IOException("transcode timed out; see " + log);
            }
            if (process.exitValue() != 0)
                throw new IOException("transcode exited " + process.exitValue() + "; see " + log);
            return new Result(process.exitValue(), log);
        } finally {
            if (process.isAlive()) stop(process);
        }
    }
    private static void stop(Process process) throws InterruptedException {
        process.destroy();
        if (!process.waitFor(2, TimeUnit.SECONDS)) {
            process.destroyForcibly();
            process.waitFor();
        }
    }
    public static void main(String[] args) throws Exception {
        if (args.length != 2) throw new IllegalArgumentException("input.mp4 output.mp4");
        Path input = Path.of(args[0]), output = Path.of(args[1]);
        if (!Files.isRegularFile(input) || input.toRealPath().equals(output.toAbsolutePath().normalize()))
            throw new IllegalArgumentException("existing input and distinct output required");
        run(List.of("ffmpeg", "-nostdin", "-hide_banner", "-loglevel", "error", "-n", "-i", input.toString(),
                "-map", "0:v:0", "-map", "0:a:0?", "-vf", "scale=-2:360", "-c:v", "libx264", "-preset", "veryfast",
                "-c:a", "aac", output.toString()), Duration.ofSeconds(120), output.resolveSibling(output.getFileName()+".log"));
        if (!Files.isRegularFile(output) || Files.size(output) == 0) throw new IOException("missing output");
        System.out.println("Process finished. Validate tracks and decoding with ffprobe/ffmpeg before publishing.");
    }
}
