import useState from '~/hooks/useState'
import { MessageType} from '~/typs'
import { show_message } from './utils.js'

export const check_credentials = async(url: string, data: any): Promise<any> => {
  let dataJsonString = ''
  try {
    dataJsonString = JSON.stringify(data)
  }
  catch (e) {
    console.log(e)
    return
  }
  try {
    const response = await fetch(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: dataJsonString,
    })
    if (!response.ok) {
      const errorMessage = await response.text()
      // throw new Error(errorMessage)
      console.log(errorMessage)
      return
    }
    if (response.ok && response.status === 200)
      return response.json()
  }
  catch (e) {
    useState().connection.value.state = 'connection.error'
    console.log(e)
  }
}
export const parseJwt = (token: string|null): any => {
	let res = {}
	if (token && token.length === 0 || token === "?") {
		return res
	}
	if (token) {
		try {
			const base64Url = token.split('.')[1];
			const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
			const jsonPayload = decodeURIComponent(atob(base64).split('').map((c) => 
				'%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
			).join(''));
			res = JSON.parse(jsonPayload);
		} catch(e) {
			console.log(e)
			localStorage.removeItem(useState().AUTHKEY.value)
		}
	}
	return res
}
export const authExpired = (): boolean => {
	const payload = parseJwt(localStorage.getItem(useState().AUTHKEY.value))
	if (payload.exp) {
		const now = Date.now() / 1000;
		return payload.exp - now < 0 
	} else {
		return true
	}
}
export const onTimeoutAuth = () => {
	if (useState().timeoutAuth.value > 0) {
		if (useState().isDevelmode.value)
		  console.log(`timeout already set to: ${useState().timeoutAuth.value}`)
		return 
	}
	const payload = parseJwt(localStorage.getItem(useState().AUTHKEY.value))
	const now = Date.now() / 1000;
	if (payload.exp) {
		let timeout = Math.round(payload.exp - now) 
		const limit = useState().TKNLIMIT.value * 60
		timeout = timeout < limit ? timeout - (useState().REFRESHTIME.value * 60) : limit - (useState().REFRESHTIME.value * 60)
		timeout = timeout < 0 ? 100 : timeout
	  useState().timeoutAuth.value = timeout
		if (useState().isDevelmode.value)
			console.log(`AUTH timeout(${limit}): ${timeout} [${Math.round(payload.exp - now)}]`)
		setTimeout(() => {
			const r = async() => {
				useState().timeoutAuth.value=0
				await refreshAuth()
			}
			r()
		}, (timeout*1000))
	}
}
export const refreshAuth = async(val = 0) => {
	const	url = useState().CONFURLS.value.refreshauth || ''
	if (url.length == 0) {
		console.log('URL not found for refreshToken')
		return
  }
	let res: any = '', error: any = ''
	const headers: any = {} // { 'Content-Type': 'application/json' }
	headers['Accept']='application/json'
	const token = localStorage.getItem(useState().AUTHKEY.value)
	if (token && token.length > 0) {
		 headers['Authorization'] =`Bearer ${token}`
	}
	try {
    const response = await self.fetch(url, {
			method: 'GET',
      headers,
	    //mode: 'cors',
    })
		res = await response.json()
		if (!response.ok && res.message && res.message.length > 0)
	    error=res.message
	}
	catch (err: any) {
		error = err.message
	}
	if (res && res.error && res.error.length > 0) {
		error = res.error
	}
	if (error && error.length > 0) {
	  show_message(MessageType.Error, `'Auth Refresh' -> ${error}`,5000)
    useState().connection.value.state = 'connection.error'	
		setTimeout(() => {
      location.href = '/logout'
		}, 1000)
		return
	}
  if (res && res[useState().AUTHKEY.value]) {
		localStorage.setItem(useState().AUTHKEY.value,res[useState().AUTHKEY.value])
	  console.log(`New auth: ${localStorage.getItem(useState().AUTHKEY.value)}`)
	  onTimeoutAuth()
	}	
}
export const getAuth = async(urlpath = '',val = 0): Promise<[any,string]> => {
	const urlkey = location.search.replace(useState().URLKEY.value,'')
	const uuid = urlkey.length > 0 ? urlkey : useState().UUIDNONE.value 
	const url =  urlpath.length > 0 ? urlpath : (useState().CONFURLS.value.auth ? useState().CONFURLS.value.auth.replace('URLKEY',uuid) : '')
  if (url.length === 0) {
		console.log('URL not found to get Auth')
    return [null,'']
	}
	let res: any = ''
	let errmsg: any = ''
	try {
    const response = await self.fetch(url, {
			method: 'GET',
	    //mode: 'cors',
    })
		res = await response.json()
		if (!response.ok && res.message.length > 0)
		  errmsg=res.message
	}
	catch (e: any) {
		errmsg = e.message
	}
	if (errmsg && errmsg.length > 0) {
	  show_message(MessageType.Error, `'Auth Data Load' -> ${errmsg}`,5000)
    useState().connection.value.state = 'connection.error'
	}
	if (res && res.auth) {
		if (res.auth === "?") {
			useState().userID.value = "?"
		} else {
			useState().userID.value = res.user ? res.user : ''
			localStorage.setItem(useState().AUTHKEY.value,res.auth)
			onTimeoutAuth()
		}
	}
	return [res,errmsg]
}
export const checkUserAuth = async(val: string): Promise<boolean> => {
	if (val.length === 0) {
		return false
	}
	const urlkey = location.search.replace(useState().URLKEY.value,'')
	const uuid = urlkey.length > 0 ? urlkey : useState().UUIDNONE.value 
	const urlpath = useState().CONFURLS.value.auth ? useState().CONFURLS.value.auth.replace('URLKEY',uuid) : ''
  if (urlpath.length === 0) {
		console.log('URL not found to check Auth')
		return false
	}
	const psw = btoa(val)
	const url = `${urlpath}${useState().AUTH_SEPCHAR.value}${psw}`
  const [res,errmsg] = await getAuth(url,0)
	if (errmsg.length === 0 && res && res.user) {
	  useState().allowView.value=true 
		const payload = parseJwt(localStorage.getItem(useState().AUTHKEY.value))
	  if (payload && payload.id && payload.id === res.user) {
	    return true
		}
	}
	return false
}
export const checkPerms = async(auth: string|null): Promise<boolean> => {
	if (auth && auth.length === 0 || auth === '?')
	  return false
	if (useState().allowView.value)
	  return true
	const payload = parseJwt(auth)
	if (payload && payload.uuid && payload.uuid !== useState().UUIDNONE.value) {
		useState().allowView.value=false
		return true
	}
	useState().allowView.value=true
	return true
}
export const checkAuth = async(urlpath = '',val = 0): Promise<string|null> => {
	if (authExpired()) {
		const [res,errmsg] = await getAuth(urlpath,val)
		if (errmsg.length === 0 && res && res.auth) {
			return await checkPerms(res.auth) ? res.auth : ''
		} 
		return ''
	} 
	if (location.pathname === '/' && useState().URLKEY.value.length > 0) {
	  const urlkey = location.search.replace(useState().URLKEY.value,'')
	  const uuid = urlkey.length > 0 ? urlkey : useState().UUIDNONE.value 
		const data = authData()
		if (data.payload && data.payload.uuid && data.payload.uuid !== uuid) {
			const url = useState().CONFURLS.value.auth ? useState().CONFURLS.value.auth.replace('URLKEY',uuid) : ''
			if (url.length === 0) {
				console.log('URL not found to check Perms')
			  return ''
			}	
			const [res,_err] = await getAuth(url,val)
			if (res.auth) { 
			  return await checkPerms(res.auth) ? res.auth : ''
			}			
			return ''
		} else {
	    onTimeoutAuth()
			return await checkPerms(data.auth) ? data.auth : ''
		}
	} else {
    const data = authData()
		if (data.payload && data.payload.id)		
			useState().userID.value = data.payload.id
		else
			return ''
	}
	onTimeoutAuth()
	const res: string|null = localStorage.getItem(useState().AUTHKEY.value)
	return await checkPerms(res) ? res : ''
}
export const authData = ():any => {
	const auth = localStorage.getItem(useState().AUTHKEY.value) || ''
	const uidefs = {}
	const payload = parseJwt(localStorage.getItem(useState().AUTHKEY.value))
  return {auth, payload, uidefs}
}
export const is_logged_user = (): boolean => {
	const urlkey = location.search.replace(useState().URLKEY.value, '')
	if (urlkey.length > 0) {
		if (authExpired()) {
			return false
		}
		return true
	}
	return false
}
export default {
  check_credentials,
	parseJwt,
	authExpired,
	checkAuth,
	checkUserAuth,
	refreshAuth,
	getAuth,
	authData,
	is_logged_user,
}
