import { Capacitor } from '@capacitor/core'
import { CapacitorUpdater } from '@capgo/capacitor-updater'
import { ElNotification } from 'element-plus'
import http from '../api/http'

interface AppUpdateCheckResponse {
  available: boolean
  version?: string
  nativeVersion: string
  platform: 'Android' | 'Ios'
  channel: 'Production' | 'Staging'
  downloadUrl?: string
  releaseNotes?: string
  fileSize?: number
  sha256?: string
  publishedAt?: string
}

const updateChannel =
  import.meta.env.VITE_APP_UPDATE_CHANNEL?.trim() || 'production'

function absoluteApiUrl(relativePath: string) {
  const configuredBase = String(http.defaults.baseURL ?? '/api')
  const publicBase =
    import.meta.env.VITE_PUBLIC_BASE_URL?.trim() || window.location.origin
  const apiBase = new URL(
    configuredBase.endsWith('/') ? configuredBase : `${configuredBase}/`,
    publicBase,
  )
  return new URL(relativePath, apiBase).toString()
}

export async function initializeAppUpdates() {
  if (!Capacitor.isNativePlatform()) return

  try {
    // Only confirm the bundle after Vue has mounted successfully. If a newly
    // installed bundle cannot reach this point, the native plugin rolls back.
    await CapacitorUpdater.notifyAppReady()

    const platform = Capacitor.getPlatform()
    if (platform !== 'android' && platform !== 'ios') return

    const [current, builtin, next] = await Promise.all([
      CapacitorUpdater.current(),
      CapacitorUpdater.getBuiltinVersion(),
      CapacitorUpdater.getNextBundle(),
    ])
    const currentVersion =
      current.bundle.id === 'builtin'
        ? builtin.version
        : current.bundle.version

    const { data } = await http.get<AppUpdateCheckResponse>(
      '/app-updates/latest',
      {
        params: {
          platform,
          channel: updateChannel,
          nativeVersion: current.native,
          currentVersion,
        },
        timeout: 15000,
      },
    )
    if (
      !data.available ||
      !data.version ||
      !data.downloadUrl ||
      !data.sha256 ||
      next?.version === data.version
    ) {
      return
    }

    const downloaded = await CapacitorUpdater.download({
      url: absoluteApiUrl(data.downloadUrl),
      version: data.version,
      checksum: data.sha256,
    })
    await CapacitorUpdater.next({ id: downloaded.id })

    ElNotification({
      title: `新版本 ${data.version} 已就绪`,
      message: data.releaseNotes || '更新将在下次启动应用时自动生效。',
      type: 'success',
      duration: 6000,
    })
  } catch (error) {
    // OTA failure must never stop users from entering the bundled application.
    console.warn('[app-update] update check failed', error)
  }
}
