import { Capacitor, registerPlugin } from '@capacitor/core'

// Define the plugin interface
interface AppUpdatePlugin {
  getAppVersion(): Promise<{ versionName: string; versionCode: number }>
  downloadAndInstall(options: { url: string }): Promise<{ success: boolean }>
}

// Register the plugin
const AppUpdate = registerPlugin<AppUpdatePlugin>('AppUpdate')

// Update server configuration - use proxy to avoid CORS issues
const UPDATE_CHECK_URL = 'https://app.logship.de/api/mobile/app-version'
const HISTORY_URL = 'https://app.logship.de/api/mobile/app-versions'
const UPDATE_FILE_BASE = 'https://www.logyou.de/logship'

export const useAppUpdate = () => {
  const isNative = ref(false)
  const currentVersion = ref<string | null>(null)
  const latestVersion = ref<string | null>(null)
  const apkUrl = ref<string | null>(null)
  const releaseNotes = ref<string | null>(null)
  const updateAvailable = ref(false)
  const isChecking = ref(false)
  const isUpdating = ref(false)
  const error = ref<string | null>(null)

  // Version history (admin-only UI): previously released builds, newest first.
  const versionHistory = ref<any[]>([])
  const isLoadingHistory = ref(false)
  const historyError = ref<string | null>(null)
  const installingUrl = ref<string | null>(null) // which history row is currently installing

  onMounted(async () => {
    isNative.value = Capacitor.isNativePlatform()

    if (isNative.value) {
      try {
        const info = await AppUpdate.getAppVersion()
        currentVersion.value = info.versionName
        console.log('[AppUpdate] Current version:', info.versionName, 'code:', info.versionCode)
      } catch (e) {
        console.error('[AppUpdate] Failed to get app version:', e)
      }
    }
  })

  const checkForUpdate = async (): Promise<boolean> => {
    console.log('[AppUpdate] checkForUpdate called, isNative:', isNative.value)

    // Allow checking even if not detected as native (for testing)
    isChecking.value = true
    error.value = null

    try {
      console.log('[AppUpdate] Fetching:', UPDATE_CHECK_URL)
      const response = await fetch(UPDATE_CHECK_URL, {
        method: 'GET',
        cache: 'no-store',
        headers: {
          'Accept': 'application/json',
        },
      })

      console.log('[AppUpdate] Response status:', response.status)

      if (!response.ok) {
        const text = await response.text()
        throw new Error(`HTTP ${response.status}: ${text.substring(0, 100)}`)
      }

      const data = await response.json()
      console.log('[AppUpdate] Response data:', data)

      latestVersion.value = data.versionName
      releaseNotes.value = data.releaseNotes || null

      // Build full APK URL from relative path
      if (data.apkUrl) {
        // Convert relative URL to absolute URL using the update server
        apkUrl.value = data.apkUrl.startsWith('http')
          ? data.apkUrl
          : `https://www.logyou.de/logship/${data.apkUrl}`
      }

      // Compare versions - if no current version, assume update available
      if (latestVersion.value) {
        if (currentVersion.value) {
          updateAvailable.value = compareVersions(latestVersion.value, currentVersion.value) > 0
        } else {
          // Can't read the installed version (e.g. an older APK without the AppUpdate plugin, or
          // getAppVersion rejected) → offer the update instead of leaving the user stuck. Once they
          // install a build that CAN report its version, the normal comparison takes over.
          updateAvailable.value = true
        }
      }

      console.log('[AppUpdate] Latest version:', latestVersion.value, 'Current:', currentVersion.value, 'Update available:', updateAvailable.value)
      return updateAvailable.value
    } catch (e: any) {
      const errorMsg = e.message || 'Unknown error'
      error.value = `Fehler: ${errorMsg}`
      console.error('[AppUpdate] Check failed:', e)
      return false
    } finally {
      isChecking.value = false
    }
  }

  const downloadAndInstall = async (): Promise<boolean> => {
    console.log('[AppUpdate] downloadAndInstall called, isNative:', isNative.value, 'updateAvailable:', updateAvailable.value, 'apkUrl:', apkUrl.value)

    if (!isNative.value) {
      error.value = 'Nur in der nativen App verfügbar'
      console.warn('[AppUpdate] Not running in native app')
      return false
    }
    if (!updateAvailable.value) {
      error.value = 'Kein Update verfügbar'
      console.warn('[AppUpdate] No update available')
      return false
    }
    if (!apkUrl.value) {
      error.value = 'Keine APK-URL vorhanden'
      console.warn('[AppUpdate] No APK URL')
      return false
    }

    isUpdating.value = true
    error.value = null

    try {
      console.log('[AppUpdate] Starting download from:', apkUrl.value)
      const result = await AppUpdate.downloadAndInstall({ url: apkUrl.value })
      console.log('[AppUpdate] Download and install result:', result)
      return result.success
    } catch (e: any) {
      error.value = e.message || 'Download fehlgeschlagen'
      console.error('[AppUpdate] Update failed:', e)
      return false
    } finally {
      isUpdating.value = false
    }
  }

  // Load the release history (for the admin-only "Versionsverlauf"). Resolves each entry's relative
  // apkUrl to an absolute URL the native downloader can use.
  const fetchHistory = async (): Promise<any[]> => {
    isLoadingHistory.value = true
    historyError.value = null
    try {
      const response = await fetch(HISTORY_URL, {
        method: 'GET',
        cache: 'no-store',
        headers: { 'Accept': 'application/json' },
      })
      if (!response.ok) throw new Error(`HTTP ${response.status}`)
      const data = await response.json()
      const list = Array.isArray(data) ? data : []
      versionHistory.value = list
        .map((v: any) => ({
          ...v,
          apkUrlAbs: v?.apkUrl
            ? (String(v.apkUrl).startsWith('http') ? v.apkUrl : `${UPDATE_FILE_BASE}/${v.apkUrl}`)
            : null,
        }))
        .sort((a: any, b: any) => (Number(b.versionCode) || 0) - (Number(a.versionCode) || 0))
      return versionHistory.value
    } catch (e: any) {
      historyError.value = `Fehler: ${e.message || 'Verlauf konnte nicht geladen werden'}`
      console.error('[AppUpdate] History fetch failed:', e)
      return []
    } finally {
      isLoadingHistory.value = false
    }
  }

  // Install a specific (older) build by absolute APK URL — same native path as a normal update.
  // The APK must be signed with the same key as the installed app or Android refuses the sideload.
  const installVersion = async (url: string): Promise<boolean> => {
    if (!isNative.value) {
      error.value = 'Nur in der nativen App verfügbar'
      return false
    }
    if (!url) {
      error.value = 'Keine APK-URL vorhanden'
      return false
    }
    installingUrl.value = url
    isUpdating.value = true
    error.value = null
    try {
      const result = await AppUpdate.downloadAndInstall({ url })
      return result.success
    } catch (e: any) {
      error.value = e.message || 'Download fehlgeschlagen'
      console.error('[AppUpdate] Install-version failed:', e)
      return false
    } finally {
      isUpdating.value = false
      installingUrl.value = null
    }
  }

  // Compare semver versions: returns 1 if a > b, -1 if a < b, 0 if equal
  const compareVersions = (a: string, b: string): number => {
    const aParts = a.split('.').map(Number)
    const bParts = b.split('.').map(Number)
    const maxLen = Math.max(aParts.length, bParts.length)

    for (let i = 0; i < maxLen; i++) {
      const aVal = aParts[i] || 0
      const bVal = bParts[i] || 0
      if (aVal > bVal) return 1
      if (aVal < bVal) return -1
    }
    return 0
  }

  return {
    isNative: readonly(isNative),
    currentVersion: readonly(currentVersion),
    latestVersion: readonly(latestVersion),
    releaseNotes: readonly(releaseNotes),
    updateAvailable: readonly(updateAvailable),
    isChecking: readonly(isChecking),
    isUpdating: readonly(isUpdating),
    error: readonly(error),
    checkForUpdate,
    downloadAndInstall,
    // version history (admin-only UI)
    versionHistory: readonly(versionHistory),
    isLoadingHistory: readonly(isLoadingHistory),
    historyError: readonly(historyError),
    installingUrl: readonly(installingUrl),
    fetchHistory,
    installVersion,
  }
}
