/**
 * App deployment and management via platform IPC.
 */
import path from "path";
import { getContext } from "../client.js";
import { writeIpcFile, pollJsonFile, clearStaleResult } from "../ipc.js";

function groupFolder(): string {
  return process.env.NANOCLAW_GROUP_FOLDER ?? "";
}

function messagesDir(ipcDir: string): string {
  return path.join(ipcDir, "messages");
}

export async function deployApp(app: string, options?: { forceRebuild?: boolean; ipcDir?: string }): Promise<void>;
export async function deployApp(app: string, ipcDir?: string): Promise<void>;
export async function deployApp(app: string, optionsOrIpcDir?: { forceRebuild?: boolean; ipcDir?: string } | string): Promise<void> {
  const options = typeof optionsOrIpcDir === "object" ? optionsOrIpcDir : {};
  const ipcDir = typeof optionsOrIpcDir === "string" ? optionsOrIpcDir : options.ipcDir;
  const dir = ipcDir ?? getContext().ipcDir;
  const payload: Record<string, unknown> = { type: "app-apply", app, groupFolder: groupFolder() };
  if (options.forceRebuild) payload.force_rebuild = true;
  writeIpcFile(messagesDir(dir), payload);
}

export async function removeApp(app: string, ipcDir?: string): Promise<void> {
  const dir = ipcDir ?? getContext().ipcDir;
  writeIpcFile(messagesDir(dir), { type: "app-remove", app, groupFolder: groupFolder() });
}

export async function stopApp(app: string, ipcDir?: string): Promise<void> {
  const dir = ipcDir ?? getContext().ipcDir;
  writeIpcFile(messagesDir(dir), { type: "compose-stop", app, groupFolder: groupFolder() });
}

export async function restartApp(app: string, services?: string[], ipcDir?: string): Promise<unknown> {
  const dir = ipcDir ?? getContext().ipcDir;
  const statusFile = path.join(dir, "hosting-status", `${app}.json`);
  let prevUpdatedAt = "";
  try {
    const { existsSync, readFileSync } = await import("fs");
    if (existsSync(statusFile)) {
      const prev = JSON.parse(readFileSync(statusFile, "utf-8"));
      prevUpdatedAt = prev.updatedAt ?? "";
    }
  } catch { /* ok */ }
  writeIpcFile(messagesDir(dir), { type: "app-restart", name: app, services, groupFolder: groupFolder() });
  return pollJsonFile(
    statusFile,
    (d) => {
      const data = d as Record<string, unknown>;
      return data.updatedAt !== prevUpdatedAt && (data.stage === "restarted" || data.stage === "restart");
    },
    60000,
  );
}

export async function execInApp(app: string, service: string, command: string[], ipcDir?: string): Promise<unknown> {
  const dir = ipcDir ?? getContext().ipcDir;
  const resultFile = path.join(dir, "hosting-status", `${app}-exec.json`);
  clearStaleResult(resultFile);
  writeIpcFile(messagesDir(dir), { type: "app-exec", app, service, command, groupFolder: groupFolder() });
  return pollJsonFile(resultFile, (d) => (d as Record<string, unknown>).ok !== undefined, 60000);
}

export async function getAppLogs(app: string, service: string, tail?: number, ipcDir?: string): Promise<unknown> {
  const dir = ipcDir ?? getContext().ipcDir;
  const resultFile = path.join(dir, "hosting-status", `${app}-logs.json`);
  clearStaleResult(resultFile);
  writeIpcFile(messagesDir(dir), { type: "app-logs", app, service, tail, groupFolder: groupFolder() });
  return pollJsonFile(resultFile, (d) => (d as Record<string, unknown>).ok !== undefined, 30000);
}

export async function listAppVolumes(app: string, ipcDir?: string): Promise<unknown> {
  const dir = ipcDir ?? getContext().ipcDir;
  const resultFile = path.join(dir, "hosting-status", `${app}-volumes.json`);
  clearStaleResult(resultFile);
  writeIpcFile(messagesDir(dir), { type: "app-volume-list", app, groupFolder: groupFolder() });
  return pollJsonFile(resultFile, (d) => (d as Record<string, unknown>).ok !== undefined, 30000);
}

export async function removeAppVolume(app: string, volume: string, ipcDir?: string): Promise<void> {
  const dir = ipcDir ?? getContext().ipcDir;
  writeIpcFile(messagesDir(dir), { type: "app-volume-remove", app, volume, groupFolder: groupFolder() });
}
