const functions = require( 'firebase-functions' )
const { integration } = functions.config()
const { db, dataFromSnap } = require( '../modules/firebase' )
const Web3 = require( 'web3' )
const web3 = new Web3()
const { getStorage } = require( 'firebase-admin/storage' )


exports.setAvatar = async function( req, res ) {

	const chain = process.env.NODE_ENV == 'development' ? '0x4' : '0x1'
	// const chain = '0x1'

	try {

		// Get request data
		const { message, signature, signatory } = req.body
		if( !message || !signatory || !signature ) throw new Error( `Malformed request` )

		// Decode message
		const confirmedSignatory = web3.eth.accounts.recover( message, signature )
		if( signatory.toLowerCase() !== confirmedSignatory.toLowerCase() ) throw new Error( `Bad signature` )

		// Validate message
		const messageObject = JSON.parse( message )
		const { signer, tokenId, validator, chainId, network } = messageObject
		if( signer.toLowerCase() !== confirmedSignatory.toLowerCase() || !tokenId || !validator || chainId !== chain || !network ) throw new Error( `Invalid message` )

		// Check if validator was already assigned
		const validatorProfile = await db.collection( `${ network }Validators` ).doc( validator ).get().then( dataFromSnap )
		if( validatorProfile.owner && validatorProfile.owner !== signatory  ) throw new Error( `Validator already claimed by another wallet. If this is in error, contact mentor.eth on Discord.\n\nThe reason someone else can claim your validator is that we don't want to you to have to expose your validator private key to the world for security reasons <3` )

		// Write new data to db
		await db.collection( `${ network }Validators` ).doc( validator ).set( {
			tokenId,
			owner: signatory,
			src: `https://storage.googleapis.com/rocketeer-nft.appspot.com/${ network }Rocketeers/${ tokenId }.jpg`,
			updated: Date.now()
		} )

		// Update the static overview JSON
		const storage = getStorage()
		const bucket = storage.bucket()
		const cacheFile = bucket.file( `integrations/${ network }Avatars.json` )

		// Load existing json
		let jsonstring = '{}'
		const [ fileExists ] = await cacheFile.exists()
		if( fileExists ) {
			// Read old json
			const [ oldJson ] = await cacheFile.download()
			jsonstring = oldJson
		}
		const cachedJson = JSON.parse( jsonstring )

		// Get items that have not been updated
		const tenSecondsAgo = Date.now() - ( 10 * 1000 )
		const shouldBeUpdated = await db.collection( `${ network }Validators` ).where( 'updated', '>', cachedJson.updated || tenSecondsAgo ).get().then( dataFromSnap )

		// Update items that should be updated ( including current update )
		shouldBeUpdated.map( doc => {
			if( !cachedJson.images ) cachedJson.images = {}
			if( !cachedJson.ids ) cachedJson.ids = {}
			cachedJson.images[ doc.uid ] = doc.src
			cachedJson.ids[ doc.uid ] = doc.tokenId
		} )

		// Save new data to file
		cachedJson.updated = Date.now()
		cachedJson.trail = shouldBeUpdated.length
		await cacheFile.save( JSON.stringify( cachedJson ) )
		await cacheFile.makePublic()

		return res.json( {
			success: true,
			url: cacheFile.publicUrl()
		} )

	} catch( e ) {

		console.error( 'avatar integration error: ', e )
		return res.json( {
			error: e.message
		} )

	}

}

exports.resetAvatar = async function( req, res ) {

	// const chain = process.env.NODE_ENV == 'development' ? '0x4' : '0x1'
	const network = 'mainnet'
	// const chain = '0x1'

	try {

		// Get request data
		const { address, secret } = req.body
		if( !address || !secret || secret != integration.secret ) throw new Error( `Malformed request` )

		// Check if validator was already assigned
		await db.collection( `${ network }Validators` ).doc( address ).delete()

		// Update the static overview JSON
		const storage = getStorage()
		const bucket = storage.bucket()
		const cacheFile = bucket.file( `integrations/${ network }Avatars.json` )

		// Load existing json
		let jsonstring = '{}'
		const [ fileExists ] = await cacheFile.exists()
		if( fileExists ) {
			// Read old json
			const [ oldJson ] = await cacheFile.download()
			jsonstring = oldJson
		}
		const cachedJson = JSON.parse( jsonstring )

		// Delete the address
		if( cachedJson.images[ address ] ) delete jsonstring.images[ address ]
		if( cachedJson.ids[ address ] ) delete jsonstring.ids[ address ]

		// Save new data to file
		cachedJson.updated = Date.now()
		await cacheFile.save( JSON.stringify( cachedJson ) )
		await cacheFile.makePublic()

		return res.json( {
			success: true,
			url: cacheFile.publicUrl()
		} )

	} catch( e ) {

		console.error( 'avatar deletion integration error: ', e )
		return res.json( {
			error: e.message
		} )

	}

}