import { check as checkUpdate } from '@tauri-apps/plugin-updater';

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,
};

type UpdateHandle = Awaited<ReturnType<typeof checkUpdate>>;

let cachedUpdate: UpdateHandle | null = null;

export async function checkForUpdate(): Promise<UpdateState> {
  if (!isTauriRuntime()) {
    return { ...IDLE_UPDATE_STATE };
  }
  try {
    const update = await checkUpdate();
    if (!update) {
      cachedUpdate = null;
      return { ...IDLE_UPDATE_STATE };
    }
    cachedUpdate = update;
    return {
      available: true,
      version: update.version ?? null,
      notes: update.body ?? null,
      downloading: false,
      downloaded: false,
      error: null,
    };
  } catch (err: unknown) {
    console.warn('checkForUpdate failed', err);
    return {
      ...IDLE_UPDATE_STATE,
      error: err instanceof Error ? err.message : 'update check failed',
    };
  }
}

// Downloads + installs the previously checked update. On Windows the app
// quits during install (passive installer); on macOS/Linux tauri triggers
// a relaunch automatically.
export async function installUpdate(
  onProgress?: (downloaded: number, total: number | null) => void,
): Promise<void> {
  if (!cachedUpdate) {
    throw new Error('no pending update — call checkForUpdate() first');
  }
  let total: number | null = null;
  let downloaded = 0;
  await cachedUpdate.downloadAndInstall((event) => {
    if (event.event === 'Started') {
      total = event.data.contentLength ?? null;
      downloaded = 0;
    } else if (event.event === 'Progress') {
      downloaded += event.data.chunkLength;
    }
    onProgress?.(downloaded, total);
  });
  cachedUpdate = null;
}
