import { execFile } from "node:child_process";
import { readFile } from "node:fs/promises";
import { promisify } from "node:util";
import { z } from "zod";
import type { AppConfig } from "./config.js";

const execFileAsync = promisify(execFile);

const updateStatusSchema = z.object({
  state: z.enum(["idle", "checking", "available", "building", "current", "success", "failed"]),
  message: z.string().max(500),
  fromRevision: z.string().max(64).nullable().default(null),
  toRevision: z.string().max(64).nullable().default(null),
  updatedAt: z.string()
});

export type UpdateStatus = z.infer<typeof updateStatusSchema> & {
  installedRevision: string | null;
  supported: boolean;
};

async function readTrimmed(path: string): Promise<string | null> {
  try {
    const value = (await readFile(path, "utf8")).trim();
    return value || null;
  } catch {
    return null;
  }
}

export async function readUpdateStatus(config: AppConfig): Promise<UpdateStatus> {
  const installedRevision = await readTrimmed(config.versionFile);
  try {
    const parsed = updateStatusSchema.parse(JSON.parse(await readFile(config.updateStatusPath, "utf8")));
    const updateAgeMs = Date.now() - Date.parse(parsed.updatedAt);
    if (["checking", "building"].includes(parsed.state) && Number.isFinite(updateAgeMs) && updateAgeMs > 35 * 60 * 1000) {
      return {
        ...parsed,
        state: "failed",
        message: "The previous update was interrupted. It is safe to try again.",
        installedRevision,
        supported: true
      };
    }
    return { ...parsed, installedRevision, supported: true };
  } catch {
    return {
      state: "idle",
      message: "Automatic updates are available after installing the system service.",
      fromRevision: null,
      toRevision: null,
      updatedAt: new Date(0).toISOString(),
      installedRevision,
      supported: false
    };
  }
}

export async function triggerSystemUpdate(mode: "check" | "install" = "install"): Promise<void> {
  await execFileAsync(
    "/usr/bin/sudo",
    [
      "-n",
      "/usr/bin/systemctl",
      "start",
      "--no-block",
      mode === "check" ? "pi-car-companion-update-check.service" : "pi-car-companion-update.service"
    ],
    { timeout: 10_000, maxBuffer: 16 * 1024 }
  );
}
