'use client'

import { useEffect, useState } from 'react'
import axios from 'axios'
import { app } from '@tauri-apps/api'
import { invoke } from '@tauri-apps/api/core'
import { openUrl } from '@tauri-apps/plugin-opener'
import { arch, platform } from '@tauri-apps/plugin-os'
import {
  BaseDirectory,
  create,
  exists,
  readTextFile,
  writeTextFile
} from '@tauri-apps/plugin-fs'
import './App.css'
import { message } from '@tauri-apps/plugin-dialog'

interface LauncherUpdate {
    id: string
    releaseDate: number
    downloadUrl: string
    sha512sum: string
}

export default function App () {
  const [state, setState] = useState<string>('Loading...')
  const [error, setError] = useState<string>('')

  useEffect(() => {
    ;(async () => {
      setState('Checking for updates...')

      let updaterLatestRequest
      let launcherLatestRequest
      let launcherUpdateData: LauncherUpdate | null

      try {
        updaterLatestRequest = await axios.get(
          'https://games.lncvrt.xyz/api/launcher/loader/latest'
        )
        launcherLatestRequest = await axios.get(
          'https://gamdes.lncvrt.xyz/api/launcher/latest'
        )
      } catch (e: unknown) {
        setState('Failed. Check internet connection.')
        setError('e0001 / ' + String(e))
        return
      }

      if (
        updaterLatestRequest.status !== 200 ||
        launcherLatestRequest.status !== 200
      ) {
        setState('Failed. Try again later.')
        setError('e0002')
        return
      }

      const version = await app.getVersion()
      if (version !== updaterLatestRequest.data) {
        setState('Loader update required')
        return
      }

      const options = {
        baseDir: BaseDirectory.AppLocalData
      }

      let latest = false
      if (await exists('.version', options))
        latest =
          (await readTextFile('.version', options)) ==
          launcherLatestRequest.data

      if (!latest) {
        setState('Downloading new update...')
        try {
          const launcherUpdateRequest = await axios.get(
            `https://games.lncvrt.xyz/api/launcher/loader/update-data?platform=${platform()}&arch=${arch()}`
          )
          launcherUpdateData = launcherUpdateRequest.data
        } catch (e: unknown) {
          setState('Failed. Check internet connection.')
          setError('e0003 / ' + String(e))
          return
        }
        if (!launcherUpdateData) {
          setState('Failed. Check internet connection.')
          setError('e0004')
          return
        }
        const downloadResult = await invoke('download', {
          url: launcherUpdateData.downloadUrl,
          hash: launcherUpdateData.sha512sum
        })
        if (downloadResult == '-1') {
          setState('Failed. Check internet connection.')
          setError('e0005 / ' + downloadResult)
          return
        } else if (downloadResult == '-2') {
          setState('File integrity check failed.')
          return
        } else if (downloadResult == '-3') {
          setState('Failed to unzip update.')
          return
        }
        if (await exists('.version', options)) await create('.version', options)
        await writeTextFile('.version', launcherLatestRequest.data, options)
      }

      setState('Starting...')
      invoke('load')
    })()
  }, [])

  return (
    <>
      <div className='absolute left-1/2 top-[20%] -translate-x-1/2 flex flex-col items-center'>
        <img src='/Icon.png' width={128} height={128} alt='' draggable={false} />
        <div
          className={`${
            state == 'Loader update required' || error != '' ? 'mt-4' : 'mt-10'
          } text-center`}
        >
          <p className='whitespace-nowrap'>{state}</p>
          <button
            hidden={state !== 'Loader update required'}
            className='mt-4'
            onClick={async () =>
              await openUrl('https://games.lncvrt.xyz/download')
            }
          >
            Update
          </button>
          <button
            hidden={error == ''}
            className='mt-4'
            onClick={async () => await message(error, { title: 'Error', kind: 'error' })}
          >
            Show error
          </button>
        </div>
      </div>
    </>
  )
}
