import { isTauriRuntime } from './globalShortcut';

export interface UpdateState {
  available: boolean;
  version: string | null;
  notes: string | null;
  downloading: boolean;
  downloaded: boolean;
  error: string | null;
}

export const IDLE_UPDATE_STATE: UpdateState = {
  available: false,
  version: null,
  notes: null,
  downloading: false,
  downloaded: false,
  error: null,
};

// Module-local flag: main owns the real "pending update" state via
// electron-updater, but the renderer also needs to refuse installUpdate()
// calls that weren't preceded by a successful checkForUpdate().
let hasPendingUpdate = false;

export async function checkForUpdate(): Promise<UpdateState> {
  if (!isTauriRuntime()) {
    return { ...IDLE_UPDATE_STATE };
  }
  try {
    const result = await window.electronAPI.checkForUpdate();
    if (!result.available || !result.info) {
      hasPendingUpdate = false;
      return { ...IDLE_UPDATE_STATE };
    }
    hasPendingUpdate = true;
    return {
      available: true,
      version: result.info.version ?? null,
      notes: result.info.releaseNotes ?? null,
      downloading: false,
      downloaded: false,
      error: null,
    };
  } catch (err: unknown) {
    const msg = err instanceof Error ? err.message : String(err);
    const benign =
      /could not fetch a valid release json|network|timed? out|failed to fetch|connection|enotfound|econnreset|etimedout|404/i.test(
        msg,
      );
    if (!benign) {
      console.warn('checkForUpdate failed', err);
    }
    return {
      ...IDLE_UPDATE_STATE,
      error: benign ? null : msg,
    };
  }
}

// Downloads + installs the previously checked update. On Windows the
// app quits during install (passive installer); electron-updater
// triggers a relaunch on macOS/Linux.
export async function installUpdate(
  onProgress?: (downloaded: number, total: number | null) => void,
): Promise<void> {
  if (!hasPendingUpdate) {
    throw new Error('no pending update — call checkForUpdate() first');
  }
  let unsub: (() => void) | null = null;
  if (onProgress) {
    unsub = window.electronAPI.onUpdaterProgress((p) => {
      onProgress(p.transferred, p.total || null);
    });
  }
  try {
    await window.electronAPI.downloadInstallUpdate();
  } finally {
    unsub?.();
    hasPendingUpdate = false;
  }
}
